2009-11-04 9 views
7

Ho difficoltà a capire come funziona un oggetto classmethod in Python, specialmente nel contesto dei metaclassi e in __new__. Nel mio caso particolare mi piacerebbe ottenere il nome di un membro classmethod, quando eseguo l'iterazione con lo members assegnato a __new__.Come funziona un oggetto classmethod?

Per i metodi normali, il nome viene semplicemente memorizzato in un attributo __name__, ma per un metodo di classe apparentemente non esiste un attributo di questo tipo. Non vedo nemmeno come viene chiamato il metodo di classe, in quanto non esiste alcun attributo __call__.

Qualcuno può spiegarmi come funziona un metodo di classe o indicarmi una documentazione? Googling non mi ha portato da nessuna parte. Grazie!

+0

Non ho informazioni sul "mancante" '__name__', ma per essere sicuro che i metodi di classe hanno un wrapper' __call__'. – mjv

risposta

18

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' 
+0

Grazie, questo ha risolto il mio problema! Mi sento un po 'stupido da quando, in linea di principio, conoscevo i descrittori. Ma dovevo confondermi nel vedere che un classmethod è racchiuso in un descrittore non callable :-) – nikow

+0

Scusa, ho dimenticato di sottolineare quanto apprezzo la tua risposta molto dettagliata, questo è semplicemente fantastico. – nikow

1

This sembra che abbia la merce.

+0

Grazie, non ero a conoscenza del termine Metamethods, quindi è stata una lettura interessante. Ma temo che non ci fossero molte informazioni sull'oggetto classmethod stesso. – nikow

Problemi correlati