OOP: method overriding works in mysterious ways?

Mike Meyer mwm at mired.org
Mon Jan 2 20:08:06 EST 2006


"John M. Gabriele" <john_sips_teaz at yahooz.com> writes:

> Consider the following:
>
> #!/usr/bin/python
>
> #-----------------------------------------------------------------
> class Grand_parent( object ):
>
>      def speak( self ):
>          print 'Grand_parent.speak()'
>          self.advise()
>
>      def advise( self ):
>          print 'Grand_parent.advise()'
>          self.critique()
>
>      def critique( self ):
>          print 'Grand_parent.critique()'
>
>
> #-----------------------------------------------------------------
> class Parent( Grand_parent ):
>
>      def speak( self ):
>          print '\tParent.speak()'
>          self.advise()
>
>      def advise( self ):
>          print '\tParent.advise()'
>          self.critique()
>
>      # ATM, the Parent is at a loss for words, and has no critique.
>
>
> #-----------------------------------------------------------------
> class Child( Parent ):
>
>      def speak( self ):
>          print '\t\tChild.speak()'
>          self.advise()
>
>      # Currently, the Child has no really useful advice to give.
>
>      def critique( self ):
>          print '\t\tChild.critique()'
>
>
> #-----------------------------------------------------------------
> print 'speak() calls advise(), then advise() calls critique().'
> print
>
> people = [ Grand_parent(), Parent(), Child() ]
> for person in people:
>      person.speak()
>      print
>
>
>
> ====================
> The output is:
>
> speak() calls advise(), then advise() calls critique().
>
> Grand_parent.speak()
> Grand_parent.advise()
> Grand_parent.critique()
>
>          Parent.speak()
>          Parent.advise()
> Grand_parent.critique()
>
>                  Child.speak()
>          Parent.advise()
>                  Child.critique()
>
>
> What's going on here with that last "Child.critique()"? The
> Parent called self.critique(), and since it *had* no critique()
> method, it should've deferred to it's parent's critique()
> method, right? But instead, somehow Child.critique() got called.
> Why?

Because that's the way Python searchs for object attributes. Nobody
made it explicit, so I will. This is simplified, ignoring various
complications:

        When looking up a value for self.foo, you first look for
        attribute foo of self. You then check the class of self for
        attribute foo. You then check the parent class of the last
        class you checked for attribute foo. You repeat that last step
        until there is no parent class.

Like I said, that's simplified. But it's sufficent to explain what
you're seeing.

       <mike
-- 
Mike Meyer <mwm at mired.org>			http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.



More information about the Python-list mailing list