4

I'm quite new to programming and still learning my ropes. Apologies if this question is too elementary.

I feel it somewhat difficult to clarify my question, so here's an example of what I want to accomplish: Suppose that a is an instance of class X, and is supposed to have attributes a1, a2, a3, b1, b2, b3, c1, c2 and c3. I want to put a1 through a3, b1 through b3 and c1 through c3 into their own classes A, B, C nested under X for ease of use. What would be the correct syntax to do so?

 class X:
    def __init__ (self, name, A, B, C):
        self.name = name
        self.A = A
        self.B = B
        self.C = C
    class A (X):
       def _init_ (self, name, a1, a2, a3):
           self.name = name
           self.a1 = a1
           self.a2 = a2
           self.a3 = a3
    class B (x):
       def _init_ (self, name, b1, b2, b3):
           self.name = name
           self.b1 = a1
           self.b2 = a2
           self.b3 = a3
    class C (X):
       def _init_ (self, name, c1, c2, c3):
           self.name = name
           self.c1 = a1
           self.c2 = a2
           self.c3 = a3

Since This was built entirely on guesswork, I'm 99.9% certain it's wrong, but I am not sure what I should do next to make it right. I have tried searching for "nested classes" answers, but the answers I have found didn't really clarify my position.

Please explain proper Syntax for nested classes in Python.

Thanks for your help, and my apologies for this elementary question.

EDIT: There were some crucial typos in my codes that I have corrected just now. My apologies for any inconvenience.

1
  • 1. Don't feel bad. If you're trying to give us the information we need, we will try to help you. 2. What do you mean by "nested class"? What is the problem that you are trying to solve with such nesting, and why do you think such nesting is the correct solution for that problem? Commented May 22, 2012 at 6:08

2 Answers 2

3

A nested class is simply one whose definition exists within the scope of another. They generally aren't all that useful in Python. However, it is possible to do what you want and derive the attributes of one class from that of many; the two main methods are mixins / multiple inheritance and composition.

The mixin approach is like so:

class A(object):
    def __init__(self, a=None, *args, **kwargs):
        self.a = a
        super(A, self).__init__(*args, **kwargs)

class B(object):
    def __init__(self, b=None, *args, **kwargs):
        self.b = b
        super(B, self).__init__(*args, **kwargs)

class X(A, B):
    def __init__(self, *args, **kwargs):
        super(X, self).__init__(*args, **kwargs)

x = X(a='foo', b='bar')
print x.a, x.b
  • As X is to have the attributes of both A and B, we have it inheriting from both: class X(A, B).

  • Each __init__ accepts *args, **kwargs as parameters; our super() call in X passes named parameters to the initialisers of A and B, so we need it to be able to accept (and then ignore) parameters for the other initialisers. That is, we pass both a and b into A.__init__ but only use a.

  • Reading up on super() is essential for understanding Python's inheritance.

However, multiple inheritance can be difficult to manage past simple examples, so it's often recommended that you use composition instead:

class A(object):
    def __init__(self, a):
        self.a = a

class B(object):
    def __init__(self, b):
        self.b = b

class X(object):
    def __init__(self, a, b):
        self.A = A(a)
        self.B = B(b)

x = X('foo', 'bar')
print x.A.a, x.B.b

You can see this removes the need for the super() calls and for any special parameter handling on the initialiser, making it a lot clearer. Here we take two parameters, then construct the relevant classes internally and attach them to the X instance. This makes attribute lookup a little more awkward, but there are ways to simplify that:

class X(object):
    # <etc>
    @property
    def a(self):
        return self.A.a

It's also possible to override __getattr__ and do some dynamic lookups instead of hand-coding each property.

class X(object):
    # <etc>
    def __getattr__(self, item):
        for component in (getattr(self, c) for c in ['A', 'B']):
            if hasattr(component, item):
                return getattr(component, item)

Another option is to pass the composed instances in yourself:

class X(object):
    def __init__(self, A, B):
        self.A = A
        self.B = B

x = X(A('foo'), B('bar'))
print x.A.a, x.B.b

This removes any need for X to know anything about A and B other than their interface. This makes encapsulation easier: you can now stick A and B into their own modules if that's appropriate. You can also use a factory function for convenience:

def make_X(a, b):
    return X(
        A(a), 
        B(b)
    )
Sign up to request clarification or add additional context in comments.

Comments

1

You're looking for inheritance.

Also, I notice that you are missing that python is case sensitive. This means that a and A are NOT the same variable

 class X:
    def __init__ (self, name, a, b, c):
        self.name = name
        self.a = a

class A (X):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.a1 = a1
       self.a2 = a2
       self.a3 = a3

class B (A):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.b1 = a1
       self.b2 = a2
       self.b3 = a3

class C (A):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.c1 = a1
       self.c2 = a2
       self.c3 = a3

Hope this helps

2 Comments

My apologies for the inconvenience, but I have carelessly omitted some crucial information in my code the first time through. The code above is what I have tried - and failed. Once again, I would very much appreciate it if you could help me point out what went wrong.
None of this code will work. There's no way subclasses of X will add their attributes to an instance of X. There are no super calls so no inheritance is happening at all.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.