2013-07-08 16 views
5

Mi piacerebbe utilizzare un decoratore che accetta un argomento, controlla se tale argomento non è None e se True consente di eseguire la funzione decorata.Come passare una variabile di classe a un decoratore all'interno della definizione di classe?

Desidero utilizzare questo decoratore all'interno di una definizione di classe, perché ho un set di metodi di classe che inizia con il controllo se una variabile di classe specifica è None o no. Penso che sarebbe più bello se usassi un decoratore.

mi piacerebbe fare qualcosa di simile:

# decorator 
def variable_tester(arg): 
    def wrap(f): 
     def wrapped_f(*args): 
      if arg is not None: 
       f(*args) 
      else: 
       pass 
     return wrapped_f 
    return wrap 

# class definition 
class my_class(object): 
    def __init__(self): 
     self.var = None 

    @variable_tester(self.var) # This is wrong. How to pass self.var to decorator? 
    def printout(self): 
     print self.var 

    def setvar(self, v): 
     self.var = v 

# testing code 
my_instance = my_class() 
my_instance.printout() # It should print nothing 

my_instance.setvar('foobar') 
my_instance.printout() # It should print foobar 

risposta

5

Questo è un po 'difficile, perché si vuole fare diverse cose, ognuno di loro un po' schizzinoso: (1) che si desidera passare un argomento per un decoratore e (2) vuoi che quell'argomento faccia riferimento all'istanza, ma l'istanza non esiste al momento della decorazione, quindi dovremo differirla in qualche modo. Potresti usare una funzione o un itemgetter, ma qui userò una stringa e non userò lo functools.wraps come se dovessi essere pigro.

Qualcosa di simile:

# really, it's variable-tester-factory 
def variable_tester(target): 
    def deco(function): 
     def inner(self, *args, **kwargs): 
      if getattr(self, target) is not None: 
       return function(self, *args, **kwargs) 
     return inner 
    return deco 

class my_class(object): 
    def __init__(self): 
     self.var = None 

    @variable_tester('var') 
    def printout(self): 
     print self.var 

dovrebbe funzionare:

>>> a = my_class() 
>>> print a.var 
None 
>>> a.printout() 
>>> a.var = 'apple' 
>>> a.printout() 
apple 
+1

"o un' itemgetter'": ​​o anche un [' attrgetter'] (http://docs.python.org/ 2/library/operator.html # operator.attrgetter) - di cui non ero a conoscenza dell'esistenza fino adesso. – glglgl

+0

@glglgl: buon punto, in questo modo non dovresti aggiungere un '__getitem__'. – DSM

Problemi correlati