2013-07-08 60 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

相關問題