decorator.py 是一个非常简单的装饰器加强包。你可以很直观的先定义包装函数wrapper() ,再使用decorate(func, wrapper) 方法就可以完成一个装饰器。
from decorator import decorate
def wrapper(func, *args, **kwargs):
"""print log before a function."""
print "[DEBUG] {}: enter {}()".format(datetime.now(), func.__name__)
return func(*args, **kwargs)
def logging(func):
return decorate(func, wrapper) # 用wrapper装饰func
你也可以使用它自带的@decorator 装饰器来完成你的装饰器。
from decorator import decorator
@decorator
def logging(func, *args, **kwargs):
print "[DEBUG] {}: enter {}()".format(datetime.now(), func.__name__)
return func(*args, **kwargs)
decorator.py 实现的装饰器能完整保留原函数的name ,doc 和args ,唯一有问题的就是inspect.getsource(func) 返回的还是装饰器的源代码,你需要改成inspect.getsource(func.__wrapped__) 。
wrapt
wrapt是一个功能非常完善的包,用于实现各种你想到或者你没想到的装饰器。使用wrapt实现的装饰器你不需要担心之前inspect中遇到的所有问题,因为它都帮你处理了,甚至inspect.getsource(func) 也准确无误。
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
关于wrapt的使用,建议查阅官方文档,在此不在赘述。
- http://wrapt.readthedocs.io/en/latest/quick-start.html
小结
Python的装饰器和Java的注解(Annotation)并不是同一回事,和C#中的特性(Attribute)也不一样,完全是两个概念。
装饰器的理念是对原函数、对象的加强,相当于重新封装,所以一般装饰器函数都被命名为wrapper() ,意义在于包装。函数只有在被调用时才会发挥其作用。比如@logging 装饰器可以在函数执行时额外输出日志,@cache 装饰过的函数可以缓存计算结果等等。
而注解和特性则是对目标函数或对象添加一些属性,相当于将其分类。这些属性可以通过反射拿到,在程序运行时对不同的特性函数或对象加以干预。比如带有Setup 的函数就当成准备步骤执行,或者找到所有带有TestMethod 的函数依次执行等等。
至此我所了解的装饰器已经讲完,但是还有一些内容没有提到,比如装饰类的装饰器。有机会再补充。谢谢观看。
本文源码 https://github.com/tobyqin/python_decorator
关于作者:Python技术爱好者,目前从事测试开发相关工作,转载请注明原文出处。
欢迎关注我的博客 http://betacat.online,你可以到我的公众号中去当吃瓜群众。

(编辑:淮北站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|