How to replace a method in an instance.

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Wed Aug 22 01:48:18 EDT 2007


kyosohma at gmail.com a écrit :
> On Aug 24, 11:02 am, "Steven W. Orr" <ste... at syslang.net> wrote:
> 
>>In the program below, I want this instance to end up calling repmeth
>>whenever inst.m1 is called. As it is now, I get this error:
>>
>>Hello from init
>>inst =  <__main__.CC instance at 0x402105ec>
>>Traceback (most recent call last):
>>   File "./foo9.py", line 17, in ?
>>     inst.m1()
>>TypeError: repmeth() takes exactly 1 argument (0 given)
>>
>>#! /usr/bin/python
>>def repmeth( self ):
>>     print "repmeth"
>>
>>class CC:
>>     def __init__( self ):
>>         self.m1 = repmeth
>>         print 'Hello from init'
>>
>>     def m1 ( self ):
>>         print "m1"
>>
>>inst = CC()
>>inst.m1()
>>
>>TIA
>>
> 
> Remove "self" from repmeth as it's not required in a function, only in
> functions that are defined within a class.

Obviously wrong. 'self' (or whatever-you-name-it) as first arg is 
mandatory for functions used as instance methods. The fact that a 
function is defined outside a class doesn't mean it cannot be used as a 
method...

> Of course, a function in a
> class is also know as a method.

Less obvious but still wrong !-)

A function object, whereever (and however) it's defined, is a function 
object, not a method objet. Now what happens is that functions defined 
inside a class are wrapped in method (by default, instancemethod) objects.

To be more accurate - and talking only about how it works for new-style 
classes - function objects implements the descriptor protocol, so when a 
function is a class attribute (which is what happens when the function 
is defined in the class statement's body), and is looked up on an 
instance, it returns an instancemethod object that has the instance and 
the function as attributes. This instancemethod object is itself 
callable, and when called returns the result of calling the function 
with the instance as first argument. classmethods and staticmethods are 
variants fo this scheme, calling the function with either the class as 
first arg (for classmethods) or just as-is (for staticmethods).

Now when you set a function as an *instance* (not class) attribute, the 
descriptor protocol isn't invoked (it only works on class attributes), 
so if you want to use the function as a method, you have to do the 
wrapping by yourself (cf my other answer to the OP).

HTH



More information about the Python-list mailing list