Python装饰器
Python装饰器
简单装饰器
def print_func(func):
def wrapper():
print(f'{func.__name__} is running ')
return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
return wrapper
def foo():
print("I'm foo")
foo = print_func(foo) # 因为装饰器 print_func(foo) 返回的是函数对象 wrapper,这条语句相当于 foo = wrapper
foo() # 执行foo()就相当于执行 wrapper()
print_func 就是一个装饰器,他是一个普通函数。 他把真正的业务函数func包裹在里面,看起来foo就像被print_func函数装饰了一样。print_func返回的也是一个函数,这个函数的名字是wrapper
。在这个例子中,函数的进入和退出,被称为一个横切面,这就是面向切面的编程。
@ 语法糖
"@"符号是Python装饰器的语法糖。什么是语法糖自行Google,简单可以理解为一个简单快捷的语法。将他放在要执行的函数前面,就可以省略上个例子中的赋值的过程,代码如下
def print_func(func):
def wrapper():
print(f'{func.__name__} is running ')
return func() # 把 foo 当做参数传递进来时,执行func()就相当于执行foo()
return wrapper
@print_func
def foo():
print("I'm foo")
foo()
装饰器如此方便的一个原因就是因为Python有个特殊的性能,它可以将方法作为参数传递给其他的方法,可以被赋值给其他变量,可以作为返回值,可以被定义在另一个方法内
*args, **kwargs
如果foo方法需要带参数,该怎么处理呢,如
def foo(name):
print(f'I am {name}')
此时我的装饰器wrapper应该怎么写呢?当业务函数需要带参数时,wrapper函数也可以需要带参数进行处理,代码如下
def print_func(func):
def wrapper(name):
print(f'{func.__name__} is running ')
# 把foo当做参数传递进来时,执行func()就相当于执行foo()
return func(name)
return wrapper
此时就可以满足带参数的方法了。但是不满足有多个参数。所以为了同时满足带参数或者不带参数的情况,装饰器的参数应该是不定长度,使用*args.装饰器应该是如下写法:
def print_func(func):
# 当函数的参数个数不确定且不需要指定参数名称时
# *args的格式是常规的参数 val1[,val2,val3....]
def wrapper(*args):
print(f'{func.__name__} is running ')
return func(*args)
return wrapper
当参数个数不确定且带有参数名字时,我们使用**kwargs放入装饰器wrapper中,如下
def print_func(func):
# 当函数的参数是有名称且不确定个数的时候,可以使用**kwargs
# **kwargs的参数格式是 key1=value1,[key2=value2,key3=value3,....]
# 函数对**kwargs是以键值对类似字典的方式进行解析。
def wrapper(**kwargs):
print(f'{func.__name__} is running ')
return func(**kwargs)
return wrapper
装饰器带参数
由于装饰器是一个普通函数,所以他接收的参数除了业务函数之外,还可以接受其他的参数,进行更为复杂的业务处理。比如,我们在打印这个函数名字的时候,可以根据我们传入的参数进行判断,如果传入的是yes,就进行打印,否则输出错误提示,具体代码如下:
def print_func(isprint):
def decorator(func):
def wrapper(*args, **kwargs):
if isprint == 'yes':
print(f'{func.__name__} is running ')
else:
print('input is wrong...')
return func(*args, **kwargs)
return wrapper
return decorator
@print_func(isprint='no')
def foo(name):
print(f"I'm {name}")
foo('Tom')

浙公网安备 33010602011771号