开发者

Confused about behaviour of base class

This follows a question I asked a few hours ago.

I have this code:

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

class B(A):
    def __init__(self, b, a):
        print 'B called.'

x = B(1, 2)
print x.a

This gives the error: AttributeError: 'B' object has no attribute 'a', as expected. I can fix this by calling super(B, self).__init__(a).

However, I have this code:

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

class B(A):
    def __init__(self, b, a):
        print 'B called.'
        print a

x = B(1, 2)

Whose output is:

B called.
2

Why does this work? And more importantly, how does it work when I have not initialized the base class? Also, notice that it does not call the initializer of A. Is it because when I do a:

def __init__(self, b, a)

I am declaring b to be an attribute of B? If yes, how can I check b is an a开发者_如何学JAVAttribute of which class - the subclass or the superclass?


The way you defined it B does not have any attributes. When you do print a the a refers to the local variable a in the __init__ method, not to any attribute.

If you replace print a with print self.a you will get the same error message as before.


In your second code, calling print a works because you are printing the variable passed as a parameter to B's __init__ function, not the self.a variable (which is not initialized because A.__init__ was not called). Once you leave the scope of the __init__ function you will loose access to the a.


The short answer is that __init__ isn't a constructor in the sense of other languages, like C++. It's really just a function that runs on an object after the "bare" object is created. B's __init__ function is conventionally responsible for calling A's __init__, but it doesn't have to - if A.__init__ never gets called, then then A's attribute a doesn't get added to the object, and so you get an error when you try to access it.


To fix this problem, you'll need to use

class B(A):
    def __init__(self, b, a):
        super(A, self).__init__(a)

Make sure you declare the classes as new style objects, something you're already doing

[edit: clarification]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜