2014-11-07 8 views
7

Perché non è possibile rendere statico un metodo __call__ di classe utilizzando il decoratore @staticmethod?decorare __call__ con @staticmethod

class Foo(object): 
    @staticmethod 
    def bar(): 
     return 'bar' 

    @staticmethod 
    def __call__(): 
     return '__call__' 

print Foo.bar() 
print Foo() 

uscite

bar 
<__main__.Foo object at 0x7fabf93c89d0> 

ma mi aspetterei che per l'uscita

bar 
__call__ 

risposta

12

È necessario sovrascrivere __call__ sul metaclasse. I metodi speciali definiti in una classe sono per le sue istanze, per cambiare i metodi speciali di una classe è necessario cambiarli nella sua classe, cioè la metaclasse. (Quando si chiama Foo() di solito l'ordine è: Meta.__call__() ->Foo.__new__() ->Foo.__init__(), solo se tornano normalmente)

class Meta(type): 
    @staticmethod 
    def __call__(): 
     return '__call__' 


class Foo(object): 
    __metaclass__ = Meta 

    @staticmethod 
    def bar(): 
     return 'bar' 

print Foo() 
#__call__ 

Come si sta cercando di modificare la classe di un'istanza, un altro modo sarà per ignorare __new__ sulla classe stessa e tornare __call__ da esso (quando __new__ restituisce qualcosa di diverso da un'istanza del metodo __init__ non viene mai chiamato):

class Foo(object): 

    def __new__(*args): 
     #ignore the args 
     return '__call__' 

    @staticmethod 
    def bar(): 
     return 'bar' 

print Foo() 
#__call__ 
+0

Grazie! Questo lo risolve per me. Cosa intendi con 'Meta .__ call __()' -> 'Foo .__ new __()' -> 'Foo .__ init __()'? Le frecce significano "chiamate"? – fragapanagos

+0

@fragapanagos Questo è l'ordine seguito da Python quando viene creata un'istanza di una classe. Vedi: http://ideone.com/4gxeiN –

Problemi correlati