2013-01-06 11 views
5

domanda simmilar (collegati al python2: Python: check if method is static)python3: verificare se il metodo è statico

Lets considerate questo seguente definizione di classe:

class A: 
    def f(self): 
    return 'this is f' 

    @staticmethod 
    def g(): 
    return 'this is g' 

In Python 3 non c'è più instancemethod, tutto è funzione, in modo la risposta relativa a Python 2 non funzionerà più.

Come ho detto, tutto è funzione, quindi possiamo chiamare A.f(0), ma ovviamente non possiamo chiamare A.f() (argomento missmatch). Ma se facciamo un'istanza a=A() e chiamiamo a.f() Python passa alla funzione A.f il self come primo argomento. Chiamare a.g() impedisce di inviarlo o cattura lo self - quindi ci deve essere un modo per verificare se questo è staticmethod o meno.

Quindi è possibile verificare in Python3 se un metodo è stato dichiarato come static o no?

+0

Posso chiedere perché si sta cercando di fare questo? –

+1

ovviamente, sto creando il mio framework di plugin e voglio controllare alcune dichiarazioni dell'interfaccia e mi piacerebbe sapere se qualcosa è stato dichiarato come staticmethod oppure no :) –

risposta

8
class A: 
    def f(self): 
    return 'this is f' 

    @staticmethod 
    def g(): 
    return 'this is g' 
print(type(A.__dict__['g'])) 
print(type(A.g)) 

<class 'staticmethod'> 
<class 'function'> 
+0

great! Potresti spiegare anche perché 'A .__ dict __ ['g']' fornisce qualcos'altro oltre a 'A.g'? –

+5

'A .__ dict __ ['g']' è diverso da 'A.g' perché le funzioni sono [descrittori] (http://docs.python.org/2/reference/datamodel.html#descriptors). Gli oggetti funzione sono descrittori perché definiscono un metodo '__get__', che viene invocato dalla magia quando si accede all'oggetto usando la notazione a punti (come' A.f'). Il protocollo descrittore è come (per esempio) un _function_ viene trasformato in un metodo _bound quando viene chiamato su un'istanza. Passando attraverso '__dict__', anziché usare la notazione dot, si ignora il protocollo descrittore. –

1

avevo bisogno di questa soluzione e ha scritto quanto segue in base alla risposta da @root

def is_method_static(cls, method_name): 
    # http://stackoverflow.com/questions/14187973/python3-check-if-method-is-static 
    for c in cls.mro(): 
     if method_name in c.__dict__: 
      return isinstance(c.__dict__[method_name], staticmethod) 
    raise RuntimeError("Unable to find %s in %s" % (method_name, cls.__name__)) 
+0

Funziona solo con metodi statici non ereditati. Puoi usare 'inspect.getattr_static' invece di accedere direttamente a' __dict__' se vuoi supportare metodi statici ereditati. –

+0

Grazie, getattr_static è nuovo in 3.2. Il mio codice funziona sia in Python2 che in Python3 –