instance attributes not inherited?

Bengt Richter bokr at oz.net
Sun Jan 15 21:19:59 EST 2006


On Sun, 15 Jan 2006 18:44:50 -0500, "John M. Gabriele" <john_sips_teaz at yahooz.com> wrote:

>The following short program fails:
to do what you intended, but it does not fail to do what you programmed ;-)
>
>
>----------------------- code ------------------------
>#!/usr/bin/python
>
>class Parent( object ):
>     def __init__( self ):
>         self.x = 9
>         print "Inside Parent.__init__()"
>
>
>class Child( Parent ):
>     def __init__( self ):
>         print "Inside Child.__init__()"
>
>
>p1 = Parent()
>p2 = Parent()
>c1 = Child()
>foo = [p1,p2,c1]
>
>for i in foo:
>     print "x =", i.x
>----------------- /code ----------------------
>
>
>
>yielding the following output:
>
>---------------- output ------------------
>Inside Parent.__init__()
>Inside Parent.__init__()
>Inside Child.__init__()
>x = 9
>x = 9
>x =
>Traceback (most recent call last):
>   File "./foo.py", line 21, in ?
>     print "x =", i.x
>AttributeError: 'Child' object has no attribute 'x'
>---------------- /output ---------------------
>
>
>Why isn't the instance attribute x getting inherited?
It would be if it existed, but your Child defines __init__
and that overrides the Parent __init__, so since you do not
call Parent.__init__ (directly or by way of super), x does not get set,
and there is nothing to "inherit".

BTW, "inherit" is not really what makes x visible as an attribute of the
instance in this case. The x attribute happens to be assigned in Parent.__init__,
but that does not make it an inherited attribute of Parent. IOW, Parent.__init__
is a function that becomes bound to the instance and then operates on the instance
to set the instance's x attribute, but any function could do that. Or any statement
with access to the instance in some way could do it. Inheritance would be if there were
e.g. a Parent.x class variable or property. Then Child().x would find that by inheritance.

BTW, if you did _not_ define Child.__init__ at all, Child would inherit Parent.__init__
and it would be called, and would set the x attribute on the child instance.

>
>My experience with OOP has been with C++ and (more
>recently) Java. If I create an instance of a Child object,
>I expect it to *be* a Parent object (just as, if I subclass
>a Car class to create a VW class, I expect all VW's to *be*
>Cars).
>
>That is to say, if there's something a Parent can do, shouldn't
>the Child be able to do it too? Consider a similar program:
>
>------------------- code ------------------------
>#!/usr/bin/python
>
>
>class Parent( object ):
>     def __init__( self ):
>         self.x = 9
>         print "Inside Parent.__init__()"
>
>     def wash_dishes( self ):
>         print "Just washed", self.x, "dishes."
>
>
>class Child( Parent ):
>     def __init__( self ):
>         print "Inside Child.__init__()"
>
>
>p1 = Parent()
>p2 = Parent()
>c1 = Child()
>foo = [p1,p2,c1]
>
>for i in foo:
>     i.wash_dishes()
>------------------- /code -----------------------
>
>But that fails with:
>
>------------------- output ----------------------
>Inside Parent.__init__()
>Inside Parent.__init__()
>Inside Child.__init__()
>Just washed 9 dishes.
>Just washed 9 dishes.
>Just washed
>Traceback (most recent call last):
>   File "./foo.py", line 24, in ?
>     i.wash_dishes()
>   File "./foo.py", line 10, in wash_dishes
>     print "Just washed", self.x, "dishes."
>AttributeError: 'Child' object has no attribute 'x'
>------------------- /output ---------------------
>
>Why isn't this inherited method call working right?
The method call is working fine. It's just that as before
Child.__init__ overrides Parent.__init__ without calling
Parent.__init__ or setting the x attribute itself, so
"AttributeError: 'Child' object has no attribute 'x'"
is telling the truth. And it's telling that was discovered
at "File "./foo.py", line 10, in wash_dishes" -- in other
words _inside_ wash_dishes, meaning the call worked, but
you hadn't provided for the initialization of the x attribute
it depended on.

There are various ways to fix this besides calling Parent.__init__
from Child.__init__, depending on desired semantics.

>Is this a problem with Python's notion of how OO works?
Nope ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list