pi.
pi.

Reputation: 1

Python: Binding method

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

Upvotes: 0

Views: 2683

Answers (3)

Alex Martelli
Alex Martelli

Reputation: 881705

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.

Upvotes: 2

robince
robince

Reputation: 10967

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.]

Upvotes: 0

Jonathan Feinberg
Jonathan Feinberg

Reputation: 45324

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!

Upvotes: 1

Related Questions