2013-07-08 2 views
5

Я хотел бы использовать декоратор, который принимает аргумент, проверяет, не является ли этот аргумент не None, а если True, он разрешает выполнение декорированной функции.Как передать переменную класса в определение декоратора внутри класса?

Я хочу использовать этот декоратор внутри определения класса, потому что у меня есть набор методов класса, который начинается с проверки, является ли конкретная переменная класса None или нет. Я думаю, что было бы лучше, если бы я использовал декоратор.

Я хотел бы сделать что-то вроде этого:

# 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 

ответ

5

Это немного сложнее, потому что вы хотите сделать несколько вещей, каждый из них немного привередливы: (1) вы хотите передать аргумент декоратору и (2) вы хотите, чтобы этот аргумент ссылался на экземпляр, но экземпляр не существует во время декорирования, поэтому нам придется как-то отложить его. Вы можете использовать функцию или itemgetter, но здесь я буду использовать строку, и я не буду использовать functools.wraps, как я должен, потому что я ленив.

Что-то вроде:

# 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 

должно работать:

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

"или' itemgetter'": ​​или даже [' attrgetter'] (http://docs.python.org/ 2/library/operator.html # operator.attrgetter), о существовании которого я не знал до сих пор. – glglgl

+0

@glglgl: хорошая точка, таким образом вам не нужно будет добавлять '__getitem__'. – DSM