2012-06-05 16 views
5

Ho una classe denominata Server che può essere avviata e arrestata. Alcuni metodi non dovrebbero essere chiamati a meno che il Server non sia avviato, nel qual caso dovrebbe essere sollevata una NotConnectedException. C'è un modo per chiamare un metodo prima di ogni metodo in una classe e determinare se la variabile di classe _started è impostata su True?Controllare le condizioni prima del metodo chiamare

Ho provato a utilizzare un decoratore, ma la funzione decoratore non ha accesso alla variabile di classe. Stavo cercando di fare qualcosa di simile:

class Server(object): 
    _started = False 
    def started(self): 
     if(self._started == False): 
      raise NotConnectedException 

    @started 
    def doServerAction(self): 
     ... 
+0

hai provato a mettere il decoratore direttamente in classe? Non ho lavorato abbastanza sui decoratori per sapere quanto avrebbe funzionato, ma è dove vorrei iniziare a cercare – inspectorG4dget

+0

come questo [post] (http://stackoverflow.com/questions/2366713/can-a-python-decorator- of-an-instance-method-access-the-class) ha detto, se è python2.6 o successivo, c'è un modo per il decoratore di accedere alla variabile di classe – xvatar

+0

@ inspectorG4dget Sì, il decoratore è nella classe. – BlueVoid

risposta

8

ricordare cosa decoratori sono:

@decorate 
def foo(...): 
    ... 

è esattamente equivalente a:

def foo(...): 
    ... 
foo = decorate(foo) 

Il decoratore è chiamato sulla funzione , quindi chiamando il primo parametro auto non fa senso. Inoltre, il decoratore viene chiamato sulla funzione quando viene definito e qualsiasi cosa restituisce viene utilizzata al posto della funzione. Pertanto, anche se il tuo decoratore started non ha lanciato un AttributeError tentando di accedere all'attributo _started di una funzione, restituisce quindi None, impostando tutti i metodi su None e quindi non è nemmeno possibile chiamarlo.

quello che vuoi è qualcosa di simile:

import functools 

def started(func): 
    @functools.wraps(func) 
    def wrapper(self, *args, **kwargs): 
     if not self._started: 
      raise ... 
     else: 
      return func(self, *args, **kwargs) 
    return wrapper 

Quasi tutti i decoratori sono di questa forma; prendono una funzione, creano un wrapper che fa qualcosa "attorno" alla funzione ricevuta e quindi restituisce il wrapper. L'uso di functools.wraps qui è utile se si finisce mai con questo codice in una sessione di interprete interattivo; aggiorna automaticamente la funzione wrapper con il nome e la docstring della funzione originale, il che rende le funzioni decorate "simili" alla funzione originale un po 'di più.

È irrilevante se questo è definito all'interno della classe oppure no.

+0

Questo è esattamente quello che stavo cercando. Grazie! – BlueVoid

Problemi correlati