13

Prima di tutto, capisco come, in generale, un decoratore funzioni. E so @staticmethod toglie l'argomento istanza nella firma, rendendoQualcuno può spiegare come funziona il codice sorgente di staticmethod in python

class C(object): 
    @staticmethod 
    def foo(): 
     print 'foo' 
C.foo //<function foo at 0x10efd4050> 
C().foo //<function foo at 0x10efd4050> 

valido.

Tuttavia, non capisco come il codice sourcec di staticmethod accada ciò.

Mi sembra che quando avvolgendo metodo foo in staticmethod, un'istanza di staticmethod viene istanziato, quindi qualche magia accade, rendendo C.foo() legit.

Quindi .. cosa succede in quelle magia? che cosa ha fatto staticmethod?

Sono a conoscenza degli enormi argomenti su SO per quanto riguarda lo staticmethods ma nessuno di loro risolve i miei dubbi. Ma forse non ho colpito la parola chiave magica. Se è così, per favore, fammi sapere.

Per chi cerca staticmethod codice sorgente, si rimanda alla https://hg.python.org/cpython/file/c6880edaf6f3/Objects/funcobject.c

risposta

12

Un oggetto staticmethod è un descriptor. La magia che ti manca è che Python chiama il metodo __get__ quando accede all'oggetto come attributo su una classe o un'istanza.

Così accedere all'oggetto come C.foo risultati in Python traduzione che a C.__dict__['foo'].__get__(None, C), mentre instance_of_C.foo diventa type(instace_of_C).__dict__['foo'].__get__(instance_of_C, type(instance_of_C)).

L'oggetto staticmethod è defined in C code, ma un equivalente in Python sarebbe:

class staticmethod(object): 
    def __init__(self, callable): 
     self.f = callable 
    def __get__(self, obj, type=None): 
     return self.f 
    @property 
    def __func__(self): 
     return self.f 

dove self.f è la funzione originale avvolto.

Tutto ciò è necessario perché le funzioni sono anch'esse dei descrittori; è il protocollo descrittore che ti dà oggetti metodo (vedi python bound and unbound method object per maggiori dettagli). Poiché anche loro hanno un metodo __get__, senza un oggetto staticmethod che avvolge la funzione, una chiamata functionobj.__get__ produce invece un oggetto metodo, passando in un argomento self.

V'è anche un classmethod, che utilizza il secondo argomento descriptor.__get__ di impegnare una funzione alla classe, e quindi ci sono property oggetti, che si traducono vincolante in una chiamata di funzione direttamente. Vedi How does the @property decorator work?.

+0

Ho ottenuto il codice sorgente da PyCharm IDE .. che non ho idea se si tratti della copia reale ... – user2829759

+0

@ user2829759: PyCharm non può accedere al codice sorgente effettivo (dato che è codice C compilato) in modo che ricostruisce uno spessore per te dall'introspezione dell'oggetto. –

+0

@martijinpieters Riflette cosa sta succedendo nel codice C? – user2829759

Problemi correlati