Confused with classmethods
Ruud de Jong
ruud<dot>de<dot>jong<at>consunet <dot>
Fri Mar 11 12:11:12 EST 2005
jfj schreef:
> Diez B. Roggisch wrote:
>
>>> I understand that this is a very peculiar use of
>>> classmethods but is this error intentional?
>>> Or did I completely missed the point somewhere?
>>
Note that this is not really related to classmethods. A similar
"problem" exists if you want to use an ordinary function as a method:
>>> def g(self):
print "argument: " + str(self)
>>> class A(object):
pass
>>> a=A()
>>> a.x = g
>>> a.x
<function g at 0x00B9F070>
Here you see that none of the class magic has been performed; a.x
is *not* a method, but an ordinary function. It has absolutely no
relation to / knowledge of the class that a belongs to.
Calling a.x() leads to an exception:
>>> a.x()
Traceback (most recent call last):
File "<pyshell#53>", line 1, in -toplevel-
a.x()
TypeError: g() takes exactly 1 argument (0 given)
And of course, if you supply an argument, everything works fine:
>>> a.x(1)
argument: 1
To get the method behaviour the function needs to be associated
with the class:
>>> del a.x
>>> A.x = g
>>> a.x
<bound method A.g of <__main__.A object at 0x00B93B90>>
>>> a.x()
argument: <__main__.A object at 0x00B93B90>
>>>
The mechanism is basically as follows (with thanks to Alex Martelli's
execellent Python in a Nutshell, Chapter 5). When a.x is being resolved,
first a.__dict__['x'] is tried. In the first case x was indeed defined
in a.__dict__, and its value was returned (the function also known as
g). No class magic at all. The same happened with your
classmethod foo: you get a bare classmethod, and apparently these
are not callable.
In the second case, a.__dict__ did not have a key 'x'. The lookup then
continues in a's class: A.__dict__['x']. Again it finds the function.
But when a class __dict__ lookup returns a function, the result is
first wrapped into a bound or unbound method object (depending on
whether you arrived there via a.x or A.x).
So far for *how* it works. As to *why* it works like this, I don't know
for sure. But my guess is that the reasoning was something as follows:
if you define a function (regular or something special like a
classmethod) only for an instance of a class, you obviously don't
want to use it in a class context: it is -by definition- invisible to
the class, or to other instances of the same class.
One possible use case would be to store a callback function.
And in that case you definitely don't want the class magic to happen
when you reference the function.
Just my 2 cents
Regards,
Ruud
--
'@'.join('.'.join(s) for s in (['ruud','de','jong'],['tiscali','nl']))
More information about the Python-list
mailing list