On Sun, 15 Jan 2006 18:44:50 -0500, "John M. Gabriele" <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list