8

I'd like to use a decorator which accepts an argument, checks if that argument is not None, and if True it lets the decorated function run.

I want to use this decorator inside a class definition, because I have a set of class methods which starts with checking if a specific instance variable is None or not. I think it would look nicer if I used a decorator.

I'd like to do something like this:

# 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
4

1 回答 1

7

这有点棘手,因为你想做几件事,每件事都有点挑剔:(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
于 2013-07-09T12:09:09.417 回答