装饰器(Decorators)是 Python 的一个重要部分,他们是修改其他函数的功能的函数。装饰器本质是一个闭包函数 。
在python中万物皆对象,函数也可以作为对象进行传递
def hello(name):
print('hello',name)
greet = hello #hello是函数对象的引用,而hello()是一个可执行的函数
# 我们把这个引用赋值给greet,这样greet也就有了hello的功能,
greet('james')
#输出:hello james
函数作为参数进行传递
一个简单的装饰器函数
这里wrapper就是一个装饰器函数,say_hello就是一个被装饰函数
输出结果为:Hello
Good moning
语法糖
简化代码
def wrapper(func):
def say_moning():
func()
print('Good moning')
return say_moning
@wrapper # 相当于say_hello = wrapper(say_hello)
def say_hello():
print('Hello')
say_hello()
装饰器的一点小问题
def wrapper(func):
def say_moning():
'''这是一个向你问好的函数'''
func()
print('Good moning')
return say_moning
@wrapper
def say_hello():
'''say hello函数'''
print('Hello')
print(say_hello.__name__) #因为say_hello其实是say_moning函数,所以这里会显示say_name的名字与文档
print(say_hello.__doc__)
解决
从functools中导入wraps,@wraps
from functools import wraps
def wrapper(func):
'''
@wraps接受一个函数来进行装饰,并加入了复制函数名称、注释文档、参数列表等等的功能。
这可以让我们在装饰器里面访问在装饰之前的函数的属性
'''
@wraps(func)
def say_moning():
'''这是一个向你问好的函数'''
func()
print('Good moning')
return say_moning
@wrapper
def say_hello():
'''say hello函数'''
print('Hello')
print(say_hello.__name__)
print(say_hello.__doc__)
带参数的装饰器
from functools import wraps
def log_out(logfile='out_log'):
def wrapper(func):
@wraps(func)
def record_execution(*args,**kwargs):
ret = func(*args,**kwargs)
record = func.__name__ + ' was executed'
print(record)
with open(logfile,'a',encoding='utf-8') as open_file:
open_file.write(record)
return ret
return record_execution
return wrapper
@log_out() #@log_out = [@ + log_out()] = @wrapper = func1 = wrapper(func1)
def func1():
pass
func1()
多个装饰器装饰一个函数
所以返回结果为
执行调用被装饰函数前的操作2
执行调用被装饰函数前的操作1
测试函数
执行调用被装饰函数后的操作1
执行调用被装饰函数后的操作2