2013-07-08 18 views
5

Chciałbym użyć dekoratora, który akceptuje argument, sprawdza, czy ten argument nie jest Brak, a jeśli True, pozwala funkcja ozdobna uruchomić.Jak przekazać zmienną klasy do dekoratora wewnątrz definicji klasy?

Chcę użyć tego dekoratora wewnątrz definicji klasy, ponieważ mam zestaw metod klasy, która rozpoczyna się od sprawdzenia, czy konkretna zmienna klasy jest Brak lub nie. Myślę, że byłoby ładniej, gdybym użył dekoratora.

chciałbym zrobić coś takiego:

# 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 

Odpowiedz

5

To jest trochę trudne, ponieważ chcemy, aby zrobić kilka rzeczy, a każdy z nich trochę wybredny: (1) chcesz przekazać argument do dekoratora i (2) chcesz, aby ten argument odnosił się do instancji, ale instancja nie istnieje w czasie dekoracji, więc musimy ją odłożyć w jakiś sposób. Możesz użyć funkcji lub itemgetter, ale tutaj użyję napisu i nie będę używał functools.wraps jak powinienem, bo jestem leniwy.

Coś jak:

# 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 

powinno działać:

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

"lub' itemgetter'": ​​lub nawet [' attrgetter'] (http://docs.python.org/ 2/library/operator.html # operator.attrgetter) - którego istnienia nie znałem już teraz. – glglgl

+0

@glglgl: dobry punkt, w ten sposób nie musiałbyś dodawać '__getitem__'. – DSM

Powiązane problemy