[Tutor] Dynamically changing a class

Kent Johnson kent37 at tds.net
Wed Sep 5 02:21:05 CEST 2007


Ricardo Aráoz wrote:
> So lets take it a notch up.
> Wanted to change the mfunc method but ONLY for an instance, not a class:
> 
>>>> MyObj = MyClass()
>>>> MyObj.mfunc(data)
> pre change behavior
>>>> MyObj.mfunc = newfunc
>>>> MyObj.mfunc(data)
> Traceback (most recent call last):
>   File "<input>", line 1, in <module>
> TypeError: newfunc() takes exactly 2 arguments (1 given)

I believe the correct way to do this is to use the __get__() method of 
the function object to create a bound method and assign that to the 
instance attribute:

In [13]: class MyClass(object): pass
    ....:
In [14]: myObj = MyClass()
In [15]: def newfunc(self):
    ....:     print 'post change behavior'
    ....:
    ....:

All functions are descriptors. The __get__() method returns a bound method:

In [16]: newfunc.__get__?
Type:           method-wrapper
Base Class:     <type 'method-wrapper'>
String Form:    <method-wrapper '__get__' of function object at 0x20a6cb0>
Namespace:      Interactive
Docstring:
     descr.__get__(obj[, type]) -> value

In [17]: newfunc.__get__(myObj, MyClass)
Out[17]: <bound method MyClass.newfunc of <__main__.MyClass object at 
0x20ba950>>

Assigning the bound method to myObj.mfunc has the desired behaviour:
In [18]: myObj.mfunc = newfunc.__get__(myObj, MyClass)
In [19]: myObj.mfunc()
post change behavior

I have a writeup of descriptors here:
http://personalpages.tds.net/~kent37/kk/00008.html

You can also use types.MethodType to do the same thing:

In [20]: from types import MethodType
In [21]: MethodType(newfunc, myObj, MyClass)
Out[21]: <bound method MyClass.newfunc of <__main__.MyClass object at 
0x20ba950>>

Kent


More information about the Tutor mailing list