A classmethod
l'oggetto è un descrittore. Devi capire come funzionano i descrittori.
In poche parole, un descrittore è un oggetto che ha un metodo __get__
, che accetta tre parametri: self
delle instance
e un instance type
.
Durante il normale ricerca attributo, se un oggetto guardato-up A
ha un metodo __get__
, tale metodo viene chiamato e cosa restituisce è sostituito in posizione per l'oggetto A
. Questo è il modo in cui le funzioni (che sono anche descrittori) diventano metodi associati quando si chiama un metodo su un oggetto.
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'
Un oggetto classmethod
funziona allo stesso modo. Quando viene rilevato, viene chiamato il suo metodo __get__
. Lo __get__
di un metodo class scarta l'argomento corrispondente allo instance
(se ce n'era uno) e passa solo lungo lo instance_type
quando chiama __get__
sulla funzione di avvolgimento.
uno scarabocchio illustrativo:
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'>
Maggiori informazioni su descrittori può essere trovato qui (tra l'altro): http://users.rcn.com/python/download/Descriptor.htm
per il compito specifico di ottenere il nome della funzione avvolto da un classmethod
:
In [29]: cm.__get__(None, dict).im_func.__name__
Out[29]: 'foo'
Non ho informazioni sul "mancante" '__name__', ma per essere sicuro che i metodi di classe hanno un wrapper' __call__'. – mjv