You are producing a classmethod
descriptor object:
print(classmethod(C))
returns the class C
wrapped in a new classmethod
object. This is not a generator, this is what Python actually stores in your class when you decorate a method with it.
Remember that a @decorator_expression
line above a function or class is just syntactic sugar for an extra function call replacing that object; @classmethod
above def f(...)
just means that Python will replace f
with f = classmethod(f)
.
You can see the same type of object when looking at the C.__dict__['f']
value; that's same type of object:
>>> class C:
... @classmethod
... def f(x,y):
... print('words')
...
>>> C.__dict__['f']
<classmethod object at 0x107d00810>
>>> C.__dict__['f'].__get__(None, C)
<bound method type.f of <class '__main__.C'>>
>>> C.f
<bound method type.f of <class '__main__.C'>>
It is the __get__
method on the descriptor object that is invoked when you try and access the C.f
attribute.
Functions themselves are descriptors too; a classmethod
bypasses the function's .__get__
method to provide a binding to the class instead of the normal binding to an instance.
See the descriptor HOWTO to understand what a descriptor is, and how a classmethod
object works.
To see what an the method itself returns, just call it on the class or on an instance:
>>> class C:
... @classmethod
... def f(*args, **kw):
... return args, kw
... def regular(*args, **kw):
... return args, kw
...
>>> C.f()
((<class '__main__.C'>,), {})
>>> C().f()
((<class '__main__.C'>,), {})
>>> C.regular()
((), {})
>>> C().regular()
((<__main__.C object at 0x1085b0790>,), {})
Instead of the usual self
instance object, the method is instead passed a reference to the class. For both the C.f()
call (directly on the class) and the C().f()
(on an instance of C
), the first argument to f()
is C
itself.
Compare this to the C.regular()
method; this is a normal method and when called directly on the class with C.regular()
no arguments were passed in, when called on an instance with C().regular()
a first argument, the instance, was passed in. This is what you normally would use self
for in the method signature.
For class methods, then the first argument is usually named cls
when declaring your method.