2013-07-08 101 views
5

我想使用接受参数的装饰器,检查该参数是否为无,如果为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

相关问题