Python
646 浏览 5 years, 10 months
10 装饰器
版权声明: 转载请注明出处 http://www.codingsoho.com/装饰器
装饰器是一种非嵌入式的修改你代码的行为
本节涉及以下几个内容:
- 什么是装饰器,其意义是什么?
- 被装饰的对象
- 装饰器使用的形式
- 实现装饰器
- 装饰器的副作用及如何弥补
什么是装饰器
装饰器是一种非嵌入式
修改python对象的定义,改变其行为的工具。
这些对象一般是函数
,方法
或类
,通过改变其代码,在其定义
、执行
或者实例化
的时候,执行额外的代码,来修改或者增添新的行为。
装饰器语法:@
问题:如果我们想在一些函数执行的开始和结束打印一些信息,怎么做?
如果是函数:在每一个函数里添加打印 >> 工作量巨大,且不易维护
如果是类:在基类里面添加,并且确认需要的继承类里面保证调用基类的。
Python有更简单的方法 : 装饰器 decorator
被decorator的函数,会在函数体之外额外执行一个操作。函数本身不会改变,但实现的功能会更丰富。
@decorator
def function( parameter )
body
在装饰器函数内,函数会变成一个可调用对象 function will become a callable object inside decorator function
function = decorator (function)
装饰是一种重新绑定行为
代码实例:
def decor_wrap_enter_exit(function): #(1)
def wrap_enter_exit(param): #(2)
print "call function enter " + function.__name__ #(3)
function(param) #(4)
print "call function exit " + getattr(function,'__name__') #(5)
return wrap_enter_exit #(6)
@decor_wrap_enter_exit #(7)
def hello_world(param): #(8)
print "hi "+ param
if __name__ == "__main__":
hello_world("hello world!")
解释如下:
- 装饰器函数,在需要被装饰的函数前面添加
@ decor_wrap_enter_exit
, 参数function为被装饰函数 - 因为装饰器函数需要返回一个函数,所以需要在装饰器函数内部定义一个函数完成装饰功能,然后该函数作为装饰器函数的返回值
- 装饰功能:在函数调用之前先打印enter信息,这儿
f.__name__
会返回被装饰函数的名字。函数本身也是一个对象,它有一个name属性,返回函数的名字。 - 真正的调用函数
- 装饰功能:在函数调用结束之后打印exit信息,这儿
getattr(f,’__name__’)
同样返回被装饰函数的名字 - 装饰器返回经过装饰的函数。装饰器是一个
闭包函数
,返回内部定义的一个函数。 - 执行装饰
- 函数名
hello_word
和参数param
分别对应于(1)和(2)两个函数的参数
装饰器的特点
- 装饰器也是一个闭包函数, 闭包函数返回内部定义的一个函数
- 装饰器接收函数作为参数,是一个高阶函数
- 装饰器返回一个函数
- 装饰器置于函数定义的前一行,并前置@符号, @符号表示这是一个装饰器
- 调用时相当于执行
函数=装饰器(函数)
语句 - 函数名被重新赋值了
- 调用时相当于执行
- 如果想要
__name__
返回原来的函数名, 在装饰器中需要返回的函数前调用@functools.wraps(func)
(这个后面章节描述)
import functools
def decor_wrap_enter_exit(function):
@functools.wraps(func)
def wrap_enter_exit(param):
......
- 装饰器函数的参数param形式是
(*args, **kwargs)
, 它接收任意形式的参数 (这个后面章节描述)