[Tutor] How to access an instance variable of a superclass from an instance of the subclass?
Alan Gauld
alan.gauld at yahoo.co.uk
Thu Feb 23 05:09:27 EST 2017
On 23/02/17 04:25, boB Stepp wrote:
> I am trying to wrap my head around the mechanics of inheritance in
> Python 3. I thought that all attributes of a superclass were
> accessible to an instance of a subclass.
For class attributes that happens automatically.
>>> class A:
a = 'A'
def __init__(self):
self.aa = 'aa'
>>> class X(A): pass
>>> x = X()
>>> x.a
'A'
>>> x.aa
'aa'
Notice that both the class and instance variables
are inherited. That's because there is no
__init__() in X so the inherited A.__init__()
is called.
Now, if we add an init to the subclass:
>>> class B(A):
b = 'B'
def __init__(self):
self.bb='bb'
>>> b = B()
>>> b.a
'A'
>>> b.bb
'bb'
>>> b.aa
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
b.aa
AttributeError: 'B' object has no attribute 'aa'
We get the scenario you found. (But with the additional fact
that B can access A's class variable 'a')
The B.__init__() is called, but it does not create an aa instance
variable. To do so we need to call the superclass constructor:
>>> class C(A):
c = 'C'
def __init__(self):
super().__init__()
self.cc = 'cc'
>>> c = C()
>>> c.a
'A'
>>> c.aa
'aa'
>>> c.cc
'cc'
>>> c.bb
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
c.bb
AttributeError: 'C' object has no attribute 'bb'
>>>
Now C can access cc and aa (as well as a), but
not B.bb of course because its not in the inheritance line.
There is no real magic(*) going on here.
When you call SomeClass() the SomeClass.__new__() method
gets called which is usually the one defined in object.
That method results in __init__() getting called. The
usual method lookup applies, the first init() found will
be executed. If it doesn't explicitly call the
superclass init then that method will never be
called.
(*)Actually its not quite this straightforward because
meta-classes are involved in the invocation of new()
and it all gets a bit mind-bending. But as a concept
you can stick with new() as the constructor calling
init() as the initializer and both being subject
to the usual method resolution rules.
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos
More information about the Tutor
mailing list