Dynamically adding and removing methods

Ron Adam rrr at ronadam.com
Tue Sep 27 18:42:21 CEST 2005


Steven D'Aprano wrote:
> On Sun, 25 Sep 2005 14:52:56 +0000, Ron Adam wrote:
> 
> 
>>Steven D'Aprano wrote:
>>
>>
>>
>>>Or you could put the method in the class and have all instances recognise
>>>it:
>>>
>>>py> C.eggs = new.instancemethod(eggs, None, C)
>>>py> C().eggs(3)
>>>eggs * 3
>>
>>Why not just add it to the class directly?  You just have to be sure 
>>it's a class and not an instance of a class.
> 
> 
> Because I started off explicitly adding functions to instances directly,
> and when I discovered that didn't work properly, I never even tried adding
> it to the class until after I discovered that instancemethod() worked.
> 
> As far as I can see, Python's treatment of functions when you dynamically
> add them to classes and instances is rather confused. See, for example:
> 
> py> class Klass:
> ...     pass
> ...
> py> def eggs(self, x):
> ...     print "eggs * %s" % x
> ...
> py> inst = Klass()  # Create a class instance.
> py> inst.eggs = eggs  # Dynamically add a function/method.
> py> inst.eggs(1)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> TypeError: eggs() takes exactly 2 arguments (1 given)
> 
> From this, I can conclude that when you assign the function to the
> instance attribute, it gets modified to take two arguments instead of one.
> Test it by explicitly passing an instance:
> 
> py> inst.eggs(inst, 1)
> eggs * 1
> 
> My hypothesis is confirmed.

You defined it to take two arguements.. (self, x).  If it's found 
directly in the object instead of indirectly in the objects parent 
objects, it calls it just as you defined it.


>> >>> def beacon(self, x):
>>...    print "beacon + %s" % x
>>...
> 
> 
> Did you mean bacon? *wink*

Of course... remembering arbitrary word letter sequences is probably my 
worst skill. ;-)  That, and I think for some reason the name Francis 
Beacon was in my mind at the time.

>> >>> C.beacon = beacon
>> >>> dir(A)
>>['__doc__', '__module__', 'beacon', 'ham', 'spam']
> 
> 
> Okay, you aren't showing all your code. What is A?

'A' is an instace of 'C' which has 'ham' and 'spam' methods in it.

Define a funciton and add it directly to class 'C'.

 >>> def beacon(self, x):
...    print "beacon + %s" % x
...
 >>> C.beacon = beacon


Show that it shows up in instance 'A' and can be used.

 >>> dir(A)
['__doc__', '__module__', 'beacon', 'ham', 'spam']
 >>> A.beacon(3)
beacon + 3


Delete the function.  And show it's usable as a method from instance 'A'.

 >>> del beacon
 >>> dir(A)
['__doc__', '__module__', 'beacon', 'ham', 'spam']
 >>> A.beacon(3)
beacon + 3

Show it's still bound to class 'C' even thought the function was deleted.

 >>> dir(C)
['__doc__', '__module__', 'beacon', 'ham', 'spam']


Cheers,
Ron







More information about the Python-list mailing list