[Tutor] Overriding a method in a class

Terry Carroll carroll at tjc.com
Sat May 14 04:57:42 CEST 2011


On Fri, 13 May 2011, David Knupp wrote:

> I think the problem is this bit about overriding an object's internal 
> method with one that is defined externally.

Yes, that describes the phenomenon.

> My gut feeilng is that you'd 
> now have to explicitly pass the object (i.e., self) as well as the 
> string, i.e.:
>
> B.addstuff(B, "WXYZ")
>
> ...which seems clunky.

But worse, it would mean that you couldn't have the default un-overridden 
method for those cases where you don't need to override it.

> I'm not familiar with this particular technique. Is it common to do 
> something like this?

Certainly the problem is common.

For my specific case, I'm going to go with a Plan B of using callbacks; 
and provide default unbound callbacks present in the module, but not 
defined in the class itself.

But I'd still like to have a better understanding of how the call gets 
transmuted from a two-argument call to a one-argument call based upon the 
target.  I suspect something along these lines is going on:

<begin uninformed speculation>
When a bound method is called, Python inserts a reference to self as an 
additional first argument, before the other arguments.  It does not do this 
with unbound methods.

In my first case, when I created object A, the name add_the_stuff 
references the bound method add_the_stuff as defined in the Thing class. 
When add_stuff calls add_the_stuff, because add_the_stuff references a 
bound method, Python does the automagical insertion of the self argument.

In my second case, when I created the object B, the name add_the_stuff 
*initially* references the bound method add_the_stuff; but then, when I 
override, I make B.add_the_stuff reference the unbound external method. 
Now, when addstuff calls add_the_stuff, Python sees that it is referencing 
an unbound method, and does not insert the self reference into the 
argument list.
<end uninformed speculation>

Now I'll wait for one of the experts to edify me.

> On Fri, 13 May 2011, Terry Carroll wrote:
>
>> I have a pretty basic point of confusion that I'm hoping I can have 
>> explained to me.  I have a class in which I want to override a method, and 
>> have my method defined externally to the class definition invoked instead. 
>> But when I do so, my external method is invoked with a different argument 
>> signature than the method it overrides.
>> 
>> (I'll illustrate with a toy example named toy.py that maintains a list of 
>> strings; the actual use case is a wxPython drag-and-drop shell that I find 
>> I keep re-using over and over, so I decided to try to turn it into a 
>> general-purpose module for my own use.)
>> 
>> ### example 1 begin
>> 
>> class Thing(object):
>>    def __init__(self):
>>        self.stuff = []
>>    def addstuff(self, text):
>>        self.add_the_stuff(text)
>>    def add_the_stuff(self, s1):
>>        self.stuff.append(s1)
>> 
>> A = Thing()
>> A.addstuff("ABCDEFG")
>> print A.stuff
>> 
>> ### example 1 end
>> 
>> So far, this works as expected.  addstuff invokes add_the_stuff; and the 
>> line "print A.stuff" prints out as ['ABCDEFG'], as expected.
>> 
>> Now, here's where I am getting befuddled, with the following additional 
>> lines:
>> 
>> ### example, continued
>> def addlower(self, s2):
>>    self.stuff.append(s2.lower()) # add it as lower case
>> 
>> B = Thing()
>> B.add_the_stuff=addlower
>> B.addstuff("WXYZ")
>> print B.stuff
>> ### end
>> 
>> My *intent* here is to patch the Thing object named B so that the B's 
>> add_the_stuff method is replaced with this additional addlower method that 
>> I define external to the object.  My expectation would be that, just as 
>> add_the_stuff method was called with two arguments (self and the string), 
>> the patched-in addlower would also get called the same way.
>> 
>> What I *expect* is to see ['abcdefg'] printed.  What I get is:
>> 
>> Traceback (most recent call last):
>>  File "E:\Personal\py\DragDrop\toy.py", line 22, in <module>
>>    B.addstuff("WXYZ")
>>  File "E:\Personal\py\DragDrop\toy.py", line 7, in addstuff
>>    self.add_the_stuff(text)
>> TypeError: addlower() takes exactly 2 arguments (1 given)
>> 
>> I'm assuming I'm missing some fundamental concept.  What is it?
>> _______________________________________________
>> Tutor maillist  -  Tutor at python.org
>> To unsubscribe or change subscription options:
>> http://mail.python.org/mailman/listinfo/tutor
>> 
>> 
>


More information about the Tutor mailing list