[Tutor] question about classes and atributes

Kent Johnson kent37 at tds.net
Fri Nov 3 19:43:37 CET 2006


Alan Gauld wrote:
> "euoar" <euoar at yahoo.es> wrote in 
>> So, in python, you can add methods at run time to an 
>> object, and even you can add them to a class at run time?
> 
> I'm not sure about adding methods at run time, I've never 
> tried it but I think the magic around the self parameter 
> might not work. But you can definitely add attributes.

Sure it works:

In [1]: class foo(object): pass
    ...:

In [2]: f=foo()

In [3]: f.show()
---------------------------------------------------------------------------
<type 'exceptions.AttributeError'>        Traceback (most recent call last)

D:\Projects\e3po\<ipython console> in <module>()

<type 'exceptions.AttributeError'>: 'foo' object has no attribute 'show'

In [4]: def show(self): print "Hi, I'm a foo"
    ...:

In [5]: foo.show=show

In [6]: f.show()
Hi, I'm a foo


More advanced explanation:
The magic around the self parameter is actually built-in to every 
function object (or its class, anyway). Functions have __get__() methods 
which means they can be used as descriptors. When Python evaluates 
f.show(), quite a few steps happen:

- find the value of the show attribute in the class definition. This 
finds the show function object.
- the function object has a __get__() method, so call show.__get__(obj) 
where obj is the original object being accessed.
- the __get__() method wraps obj and the original function into a new 
callable object and returns that.
- finally the temporary callable is actually called (by calling its 
__call__() method) and the wrapper adds the self parameter to the 
argument list and dispatches to the wrapped (original) function.


The descriptor mechanism is only used for class attributes, not instance 
attributes, so if you want to add a method to an individual instance you 
have to do a little more work using new.instancemethod:

In [12]: def show2(self): print "I'm still a foo"
    ....:

The naive approach won't work:
In [14]: f.show2 = show2

In [15]: f.show2()
<type 'exceptions.TypeError'>: show2() takes exactly 1 argument (0 given)

In [17]: import new

In [21]: f.show2 = new.instancemethod(show2, f)

In [22]: f.show2()
I'm still a foo

I hope that makes sense to someone; I had to see it about 10 times 
myself before a light bulb went on. (This is number 10 :-)

More info here and in the references:
http://www.python.org/doc/2.2.3/whatsnew/sect-rellinks.html#SECTION000320000000000000000

Kent



More information about the Tutor mailing list