装饰器作为一种设计模式在Python中有着广泛的应用,由于Python在源码中就有了装饰器实现的支持基础,本从通过实例着重展示下其运行过程,以及装饰器到被装饰函数的信息传递。
前面介绍过自由变量和闭包的概念,实际上Python的装饰器是一个特殊的闭包,其自由变量是一个函数。Python装饰器一般通过一个有嵌套函数的函数实现,参数为函数对象。
也有一些默认的装饰器如,property、staticmethod、classmethod。
其结果为:
@装饰器符号是Python语法定义的一种格式,这点在Python解析器和编译器中有详细的介绍,本文的重点不在于此。@装饰等价于funcRegister(firsrFunc)
这个结果有两个有趣的地方值得我们注意
1:装饰器函数funcRegister在main函数运行之前运行,而不是在firsrFunc被调用时执行。实际上函数装饰器在导入模块时立即执行,而被装饰的函数只在明确调用时运行。
2:firsrFunc函数对象并不是firsrFunc本身,而是被装饰器替换成了wrapper函数对象。实际上Python装饰器把被装饰的函数替换成新函数,二者接受相同的参数,而且返回被装饰的函数本该返回的值,同时还会做些额外操作。
由于装饰器会改变被装饰函数的函数对象,这并不是我们使用装饰器功能的初衷,所以使用装饰时还需要把被装饰函数的属性信息__name__,__doc__等替换到装饰器返回的函数对象上来,如上例中在返回wrapper之前,要把func函数对象的信息更新到wrapper中去。幸运的是,Python提供了现成的装饰器库帮我们方便地做这些事情,也就是functools.wraps。
其结果为:
装饰器功能还可以通过可调用对象的方式实现,实际上Python的装饰器也就是一个可调用的函数对象,只不过其参数是一个函数。
在Python自定义类中,实现__call__函数就可以实现对象的可调用,使其像函数一样使用。另外Python装饰器也可以有自己的参数,如下面的示例。
领取专属 10元无门槛券
私享最新 技术干货