1 装饰器初阶
装饰器是一种设计模式,起到装饰的作用。就是在不修改函数代码的情况下,给函数增加一些功能。
1.1 没有使用装饰器的例子
现有一个返回字符串的函数,在不修改该函数的情况下,将返回的字符串转换为大写字符串。
def uppercase_decorator(func): # 定义一个函数,其参数func是函数类型参数
def inner(): # 嵌套函数inner
s = func() # 调用func()函数并将返回值赋值给s变量
make_uppercase = s.upper() # 将字符串转换为大写并赋值给make_uppercase
return make_uppercase # 结束嵌套函数func()调用,返回转换之后的字符串
return inner # 结束函数uppercase_decorator()调用, 返回嵌套函数inner
def say_hello():
return 'hello world.'
if __name__=="__main__":
say_hello2 = uppercase_decorator(say_hello) # 调用uppercase_decorator()函数,实参是say_hello()函数,返回值say_hello2变量也是一个函数
print(say_hello2()) # 调用say_hello2函数
1.2 使用装饰器
Python提供了装饰器注释功能,装饰器本质上是一个函数。
上述代码使用装饰器修改如下:
def uppercase_decorator(func):
def inner():
s = func()
make_uppercase = s.upper()
return make_uppercase
return inner
@uppercase_decorator # 使用@uppercase_decorator装饰器声明say_hello1()函数
def say_hello1():
return "zhang cheng."
if __name__=="__main__":
print(say_hello1()) # 使用装饰器不需要显式调用uppercase_decorator()函数,直接调用say_hello1()函数即可。
1.3 同时使用多个装饰器
一个函数可以有多个装饰器声明。
def uppercase_decorator(func): # 将字符串转换成大写
def inner():
s = func()
make_uppercase = s.upper()
return make_uppercase
return inner
def backet_decorator(func): # 给字符串添加括号
def inner():
s = func()
make_bracket = '(' + s + ')'
return make_bracket
return inner
@backet_decorator
@uppercase_decorator
def say_hello():
return 'hello world.'
if __name__=="__main__":
print(say_hello())
1.4 给装饰器传递参数
装饰器本质上是函数,因此可以给装饰器传递参数。
def calc(func): # 定义装饰器函数calc(func),其参数还是一个函数
def wrapper(arg1): # 定义嵌套函数wrapper(arg1),这个函数参数列表与装饰器要注释的函数参数列表一致
return func(arg1)
return wrapper
@calc
def square(n):
return n * n
@calc
def abs(n):
return n if n > 0 else -n
if __name__=="__main__":
print(f"3's square is {square(3)}")
print(f"-30's absulate is {abs(-30)}")
2 装饰器高阶
2.1 wraps(func)使用
需要使用包:
from functools import wraps
作用:不改变使用装饰器的原有函数func的结构。(比如入参格式等,__name__, __doc__ );
因为一个原函数使用了装饰器之后,那么它就自动默认指向了装饰器函数的内存地址。
没有使用wraps装饰器,代码如下:
def add_decorator(func):
def inner():
"""
This is a decorator.
:return:
"""
func()
pass
return inner
@add_decorator
def add():
"""
This is a add.
:return:
"""
pass
if __name__=="__main__":
print(add.__name__)
print(add.__doc__)
运行结果:
inner
This is a decorator.
:return:
结果分析:未加上@wraps()装饰器,结果得知add函数指向的是引用的装饰器函数inner.
使用wraps装饰器,代码如下:
from functools import wraps
def add_decorator(func):
@wraps(func)
def inner():
"""
This is a decorator.
:return:
"""
func()
pass
return inner
@add_decorator
def add():
"""
This is a add.
:return:
"""
pass
if __name__=="__main__":
print(add.__name__)
print(add.__doc__)
运行结果如下:
add
This is a add.
:return:
结果分析:加上@wraps()装饰器,结果得知add函数的结构保持不变.
提示:__name__输出函数名; __doc__输出对应函数内的注释信息。
2.2 多层嵌套使用
from functools import wraps
def add_deco(z):
def add_decorator(func):
@wraps(func)
def inner(x, y):
return z + func(x, y)
return inner
return add_decorator
@add_deco(z=10)
def add(x, y):
return x + y
if __name__=="__main__":
print(add(5, 10))
运行结果如下:
25