In following example I am trying to bind a method object via types.MethodType(...). It does not seem to work. Any suggestions? Thanks in advance.
import types
class Base:
def payload(self, *args):
print "Base:payload"
class Drvd(Base):
def iter(self, func):
derived_func = types.MethodType(func, self, Drvd) # bind
print "drvd_func:", derived_func
derived_func() # result: calls Base:payload
# expected:calls Drvd:payload; why???
def payload(self, *args):
print "Drvd:payload"
derived = Drvd()
base_func = Base.payload
print "base_func:", base_func
derived.iter(base_func) # pass unbound method object
The output shows:
base_func: <unbound method Base.payload>
drvd_func: <bound method Drvd.payload of <main.Drvd instance at 0x00B51648>>
Base:payload
-
Since the subclass inherits the superclass function, why are you doing this? What's the point?S.Lott– S.Lott2009年11月19日 20:39:50 +00:00Commented Nov 19, 2009 at 20:39
-
Alex has pointed out, that the original unbound method Base.payload cannot be converted to another classes member function with the same name. Even with inherited classes. I am currently setting up a tree iteration. Looks like I should use a Visitor/Multimethod approach or have IDs per payload handler with a dispatcher per node. It will be used to store XML output from a Sax parser-pi.– pi.2009年11月19日 21:06:49 +00:00Commented Nov 19, 2009 at 21:06
-
Use Visitor whenever possible. Avoid magic.S.Lott– S.Lott2009年11月19日 21:40:40 +00:00Commented Nov 19, 2009 at 21:40
3 Answers 3
You're specifically requesting the use of the underlying function (im_func) of Base.payload, with a fake im_class of Drvd. Add after the existing print in iter:
print "w/class:", derived_func.im_class
print "w/func:", derived_func.im_func
and you'll see the total output as:
$ python bou.py
base_func: <unbound method Base.payload>
drvd_func: <bound method Drvd.payload of <__main__.Drvd instance at 0x24a918>>
w/class: __main__.Drvd
w/func: <unbound method Base.payload>
Base:payload
i.e., as you've asked, the underlying code being used is indeed Base.payload -- which is also what you observe in the call.
From Base.payload there is no direct way to get to Drvd.payload except by getting the name and using it to do a getattr on self (a Drvd instance), or equivalent.
1 Comment
Because you passed Base's payload (not Drvd's) to iter!
Hint:
print "%s: Base:payload"%repr(self)
Kudos for creating an accursed chimera of a thing, though!
Comments
I don't really understand what you're trying to do - but to me it's working as I'd expect. You are binding Base.payload to Drvd - from your print out you can see it is binding correctly to your Drvd instance. I'm not sure why you are then expecting it to call Drvd.payload - you have bound the function object Base.payload. It is always going to be that function.
[edit: just to add - it might be helpful if you say what your trying to do in general terms. What you're doing at the moment doesn't make much sense - Python has inheritence so if you want to override the payload method you can just do it - you don't need to do any manual binding.]