import wrapt # without argument in decorator @wrapt.decorator def logging(wrapped, instance, args, kwargs): # instance is must print "[DEBUG]: enter {}()".format(wrapped.__name__) return wrapped(*args, **kwargs) @logging def say(something): pass
使用wrapt你只需要定义一个装饰器函数,但是函数签名是固定的,必须是(wrapped, instance, args, kwargs)
,注意第二个参数instance
是必须的,就算你不用它。当装饰器装饰在不同位置时它将得到不同的值,比如装饰在类实例方法时你可以拿到这个类实例。根据instance
的值你能够更加灵活的调整你的装饰器。另外,args
和kwargs
也是固定的,注意前面没有星号。在装饰器内部调用原函数时才带星号。
如果你需要使用wrapt写一个带参数的装饰器,可以这样写。 def logging(level): @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): print "[{}]: enter {}()".format(level, wrapped.__name__) return wrapped(*args, **kwargs) return wrapper @logging(level="INFO") def do(work): pass
- http://wrapt.readthedocs.io/en/latest/quick-start.html