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@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor



_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to