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?
If you define a function in the class body and then instantiate that class class A(object): def method(self, x): print x a = A() an attribute access like a.method will be translated to a.method.__get__(a, A) which returns a bound method object. This is called "descriptor protocol", the same mechanism that allows the implementation of properties. You can find a thorough explanation at http://users.rcn.com/python/download/Descriptor.htm However, if you put a function into an instance the attribute will be returned as is. You have to inform it about self either by explicitly invoking __get__() def f(self, x): print x*x a.method = f.__get__(a, type(a)) or by using partial function application: from functools import partial a.method = partial(method, a) _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor