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']))
--
http://mail.python.org/mailman/listinfo/python-list
  • Re... Jong <ruud<dot>de<dot>jong<at>consunet <dot>
    • ... jfj
    • ... Jong <ruud<dot>de<dot>jong<at>consunet <dot>
    • ... Steve Holden
    • ... Bengt Richter

Reply via email to