1.在理解python解释器前先了解以下知识点:
闭包是什么?
函数中定义函数,且外层函数的返回值是内层函数,例如:
def outer(a):
def inner(b):
return a+b
return inner
print(outer(5)(6)) # 输出的结果是11
# 说明:python中函数本身就是对象,所以outer(5)实际引用的和inner同一个内存地址也就是同一个对象,
# outer(5)(6)实际就是在调用inner这个函数对象
*args和**kwargs的作用
是函数可以接收数量不确定的参数,*args在参数中以元组形式接收, **kwargs以字典key-value的形式接收
def aaa(a,b):
print(a+b)
def bbb(*args, **kwargs):
aaa(*args, **kwargs)
bbb(1,2) # 不会报错
bbb(1,2,3) # 会报错,原因是在bbb函数中调用aaa函数时值参数不对,aaa函数只能接收2个参数,
# bbb函数会以元组的形式接受(1,2,3),当调用aaa时*args会解析(1,2,3)为3个参数传递给aaa,
# 所以参数数量不匹配报错
2.无参函数装饰器
给一个函数添加附带功能
def decorator(func)
def wrapper(*args, *kwargs):
print("start")
func(*args, **kwargs)
print(end)
@decorator
def add(a,b):
print(a+b)
add(1,2)
# 这里的add是 def add这个对象吗? 不是,这里add实际是wrapper函数指向的对象。@会被python解释器
# 加载代码时自动执行,等价与 add = decorator(add), 所以add引用的是wrapper函数对象,wrapper对象里面的func引用的才是def add定义的函数对象
decorator(add)(1,2) # 想想这个函数执行会输出什么,关键是这里add指的是什么
3.有参函数装饰器
基于上面的分析,有参函数装饰器关键是理解@arg_decorator("Level1","Running")
是怎么执行的
def arg_decorator(Level, Status):
print("Level=%,Status=%s"%(Level,Status))
def inner_deco(func):
def wrapper(*args, **kwargs):
print("Level=%,Status=%s"%(Level,Status))
print("start")
func(*args, **kwargs)
print("end")
return wrapper
return inner_deco
@arg_decorator("Level1", "Running")
def add(a,b):
print(a+b)
add(1,2) # 如果将add(1,2)这行注释掉直接执行,会有输出吗?
# 说明程序在python解释器加载代码时,自动执行 arg_decorator("Level1","Running"),
# 会返回inner_deco这个函数对象,所以就等价于@inner_deco, 成了一个无参函数装饰器了
4.元信息的保存
元信息指一个函数和类对象名称__name__
,文档注解__doc__
等等,其他内置属性参考:
pyhton内置的函数属性
from functools import wraps
def arg_decorator(Level, Status):
print("Level=%,Status=%s"%(Level,Status))
def inner_deco(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Level=%,Status=%s"%(Level,Status))
print("start")
func(*args, **kwargs)
print("end")
return wrapper
return inner_deco **
@arg_decorator("Level1", "Running")
def add(a,b):
print(a+b)
print(add.__doc__)
print(add.__name__)
5.无参数类装饰器
将装饰器定义成一个类,你必须确保这个类实现了__call__()
和__init__
方法。
from functools import wraps
class ClsDecorator():
def __init__(self, func):
print("__init__ called")
wraps(func)(self) # 此句会修改类的元信息为func的元信息
self.f = func
def __call__(self, *args, **kwargs):
print("__call__ called")
print("start")
print(self.f(*args, **kwargs))
print("end")
@ClsDecorator
def add(a, b):
return a + b
add(1,2) # 这里的add实际上ClsDecorator的实例对象
# 说明:执行的过程是:@ClsDecorator执行的过程是
# 1.add = ClsDecorator(add)生成实例对象,(在python解释器加载代码时自动执行)
# 2.add(1,2)实际上调用的是__call__函数
6.有参数的类装饰器
和有参数的函数装饰器一样,主要是理解@ClsDecorator(1,2)
的执行过程
from functools import wraps
class ClsDecorator():
def __init(self, a, b):
print(a,b)
def __call__(self, func):
print("__call__ called")
@wraps(func) # 获取元信息
def wrapper(*args, **kwargs):
print("start")
func(*args, **kwargs)
print("end")
@ClsDecorator(1, 2)
def add(a, b):
print(a + b)