How does the classmethod object work?

I find it difficult to understand how the classmethod object works in Python, especially in the context of metaclasses and in __new__ . In my special case, I would like to get the name of the classmethod element when I repeat through the members that were provided by __new__ .

For ordinary methods, the name is simply stored in the __name__ attribute, but for the class method, there seems to be no such attribute. I don’t even see how the classmode method is called, since the __call__ attribute __call__ not exist.

Can someone explain to me how the classmethod works or tell me some documentation? Googling didn't bring me anywhere. Thanks!

+7
python metaclass class-method
source share
2 answers

A classmethod object is a handle. You need to understand how descriptors work.

In a nutshell, a descriptor is an object that has a __get__ method that takes three arguments: self , instance and instance type .

In a regular attribute search, if the search object A has the __get__ method, this method is called and its return is replaced with a place for the object A This is how functions (which are also descriptors) become methods bound when you call a method on an object.

 class Foo(object): def bar(self, arg1, arg2): print arg1, arg2 foo = Foo() # this: foo.bar(1,2) # prints '1 2' # does about the same thing as this: Foo.__dict__['bar'].__get__(foo, type(foo))(1,2) # prints '1 2' 

A classmethod works the same way. When it opens, its __get__ method __get__ called. __get__ of a class method discards the argument corresponding to instance (if any), and passes only through instance_type when it calls __get__ on a wrapped function.

Illustrative Doodle:

 In [14]: def foo(cls): ....: print cls ....: In [15]: classmethod(foo) Out[15]: <classmethod object at 0x756e50> In [16]: cm = classmethod(foo) In [17]: cm.__get__(None, dict) Out[17]: <bound method type.foo of <type 'dict'>> In [18]: cm.__get__(None, dict)() <type 'dict'> In [19]: cm.__get__({}, dict) Out[19]: <bound method type.foo of <type 'dict'>> In [20]: cm.__get__({}, dict)() <type 'dict'> In [21]: cm.__get__("Some bogus unused string", dict)() <type 'dict'> 

More information on descriptors can be found here (among other places): http://users.rcn.com/python/download/Descriptor.htm

For the specific task of getting the name of a function wrapped by classmethod :

 In [29]: cm.__get__(None, dict).im_func.__name__ Out[29]: 'foo' 
+18
source share
+1
source share

All Articles