Dynamic method
Bruno Desthuilliers
bruno.42.desthuilliers at wtf.websiteburo.oops.com
Wed Jul 11 05:00:37 EDT 2007
Daniel Nogradi a écrit :
(snip)
>> > def method_for_instance( message ):
>> > print message
>> >
>> > class myClass( object ):
>> > pass
>> >
>> > inst = myClass( )
>> > inst.method = method_for_instance
>> >
>> > inst.method( 'hello' )
(snip)
>> This won't work as expected:
>>
>> class Bidule(object):
>> def __init__(self, name):
>> self.name = name
>>
>> def greet(self, who):
>> print "hello %s, my name is %s" % (who, self.name)
>>
>> b = Bidule('Bruno')
>> b.greet = greet
>> b.greet('Daniel')
>>
>> =>
>> Traceback (most recent call last):
>> File "<stdin>", line 1, in <module>
>> File "/tmp/python-23258Nq5.py", line 10, in <module>
>> b.greet('Daniel')
>> TypeError: greet() takes exactly 2 arguments (1 given)
>
>
> Well, I thought the name method_for_instance and method_for_class are
> clear enough that if you want to 'attach' one of them to an instance
> then method_for_instance should be used :)
> And method_for_instance has only one argument and so will work as in
> the example I gave (I guess you just overlooked them).
I didn't overlooked anything. *You* did. Your "method_for_instance" is
*not* a method - it's a function. It's easy to check this out:
>>> class Toto(object):
... def truc(self):
... print "%s.truc" % self
...
>>> def chose():
... print "in chose, no 'self' here"
...
>>> t = Toto()
>>> t.truc
<bound method Toto.truc of <__main__.Toto object at 0xb7925c0c>>
>>> t.chose = chose
>>> t.chose
<function chose at 0xb7db541c>
>>>
The whole point of methods is that they do have access to the object
(instance or class) - which is not the case of your
"method_for_instance". Please reread the following:
>
>> The point is that Python functions are descriptor objects that, when
>> looked up, return a (bound or unbound) method object wrapping
>> themselves. So to attach functions as method *on a per-instance basis*,
>> you either need to use new.instancemethod (as explained by Alex), or
>> directly use the descriptor protocol, ie:
>>
>> b.greet = greet.__get__(b)
>> b.greet('Daniel')
>> => hello Daniel, my name is Bruno
>>
>> Note that you don't need this to attach a function as method to a class
>> - the descriptor protocol will then JustWork(tm).
>
>
> I agree that in general the solution explained by Alex and you is better.
They are not "better" - they are correct.
HTH
More information about the Python-list
mailing list