装饰器(decorator)
python把函数也作为对象,装饰器是在不修改函数源代码的情况下,给函数去增加一些功能,把原函数wrapper起来
例子1 · 用户态文件系统的编写
Winfsp允许用户编写或者是使用自己的文件系统(不是win的),OS只是去调用你写的相关的文件操作函数,你自己去在Windows的文件系统以外维护一个盘,比如Z盘
operations = {}defoperation(func):defwrapper(file_name):print("[operation] 正在执行", func.__name__)return func(file_name) # 假如原函数将来有返回值,装饰以后返回值与原函数保持一致。 operations[func.__name__] = wrapperreturn wrapper@operationdefcreate_file(file_name):print(f"创建文件:{file_name}")@operationdefopen_file(file_name):print(f"打开文件:{file_name}")@operationdefdelete_file(file_name):print(f"删除文件:{file_name}")print("已经注册的操作:", operations.keys())operations["create_file"]("notes.txt")operations["open_file"]("notes.txt")operations["delete_file"]("notes.txt")
说明一下代码的运行流程,大家就清楚装饰器是做什么的:涉及到函数是first-class,闭包的知识
代码执行到 :
@operationdefcreate_file(file_name):print(f"创建文件:{file_name}")
解释器会做create_file = operation(create_file),这里函数是一等公民,可以像变量一样被传来传去,也可以作为外层函数的返回值
此时,执行operation函数流,func是create_file,operations["create_file"] = wrapper,根据闭包,当前operation环境下,func是create_file
然后create_file函数会变成上面那个wrapper(相当于被包装起来),不是原来的。
此时:create_file为wrapper(环境1,func=create_file,这是之前的函数) operations = {"create_file": wrapper}`
注意:func 是“原函数对象”,不是修改后的名字
以此类推
最后:
- •
create_file为wrapper(环境1,func=create_file`,这是之前的函数) - •
open_file为wrapper(环境2,func= open_file` ,这是之前的函数) - •
delete_file为wrapper(环境3,func=delete_file`,这是之前的函数) - •
operations = {"create_file": wrapper, "open_file": wrapper, "delete_file": wrapper}
三个 wrapper 不是同一个函数,闭包环境不同
总结
装饰器会把原函数装饰成另外一个函数,一般叫wrapper,不同的原函数,因为闭包不同,所以wrapper不同