Python 修饰符 @ 的用法汇总
为已经存在的函数A,添加新的功能B
一、Python 修饰符 @
1.1 例子:为函数 Fun_A 添加 Fun_B 的新功能
1.2 复杂一点的例子:嵌套
1.3 更复杂的例子:带有参数
1.4 再复杂一点的例子:返回一个函数
二、functools 模块中修改函数属性的方法 @wraps
2.1 保留新功能的函数名
2.2 新增功能带有多个参数
2.3 修饰符带有参数
1.1 例子:为函数 Fun_A 添加 Fun_B 的新功能
1.2 复杂一点的例子:嵌套
1.3 更复杂的例子:带有参数
1.4 再复杂一点的例子:返回一个函数
二、functools 模块中修改函数属性的方法 @wraps
2.1 保留新功能的函数名
2.2 新增功能带有多个参数
2.3 修饰符带有参数
一、Python 修饰符 @
1.1 例子:为函数 Fun_A 添加 Fun_B 的新功能
def Func_A(f):
f() # 在这里添加新功能
print("Func_A is running")
f() # 在这里也添加新功能
return
@Func_A # 调用 Func_A 并加入新功能
def Func_B(): # 新功能 Func_B 的定义
print("Func_B is running")
return
运行结果:
Func_B is running
Func_A is running
Func_B is running
1.2 复杂一点的例子:嵌套
def Func_1(f):
f()
print("Func_1 is running")
return
def Func_2(f):
print("Func_2 is running")
f()
return
@Func_1
def Func_3():
print("Func_3 is running")
@Func_2
def Func_4():
print("Func_4 is running")
运行结果:
Func_3 is running
Func_2 is running
Func_4 is running
Func_1 is running
1.3 更复杂的例子:带有参数
def Func_A(f):
f("111") # 在这里添加带有参数新功能
print("Func_A is running")
f("222") # 在这里也添加带有参数新功能
return
@Func_A # 调用 Func_A 并加入新功能
def Func_B(s): # 新功能 Func_B 的定义
print(s+"Func_B is running")
return
运行结果:
111Func_B is running
Func_A is running
222Func_B is running
1.4 再复杂一点的例子:返回一个函数
def log(func):
def wrapper():
print('log开始 ...')
func("uuu")
print('log结束 ...')
return wrapper # 运行后会返回一个函数
@log # 用新的方法修饰 log 并运行
def test1(s):
print(s+'test1 ..')
@log
def test2(s):
print(s+'test2 ..')
print(log.__name__) # 即显示原函数的名字
print(test1.__name__) # 显示返回来的函数的名字,即 wrapper
print(test2.__name__) # 显示返回来的函数的名字,即 wrapper
print('\n')
test1() # 由于返回了一个函数,即可以直接运行
print('\n')
test2() # 由于返回了一个函数,即可以直接运行
运行结果:
log
wrapper
wrapper
log开始 ...
uuutest1 ..
log结束 ...
log开始 ...
uuutest2 ..
log结束 ...
二、functools 模块中修改函数属性的方法 @wraps
前面的例子中看到,用 @ 修饰符添加新功能,返回一个函数,那新功能的函数名称发生变化
这个变化我们希望避免
于是可以用 functools 模块中修改函数属性的方法 @wraps
2.1 保留新功能的函数名
from functools import wraps
def log(func):
@wraps(func)
def wrapper():
print('log开始 ...')
func()
print('log结束 ...')
return wrapper
@log
def test1():
print('test1 ..')
@log
def test2():
print('test2 ..')
print(test1.__name__)
print(test2.__name__)
print('\n')
test1()
print('\n')
test2()
运行结果:
test1
test2
log开始 ...
test1 ..
log结束 ...
log开始 ...
test2 ..
log结束 ...
2.2 新增功能带有多个参数
from functools import wraps
def log(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('log开始 ...', func.__name__)
ret = func(*args, **kwargs)
print('log结束 ...')
return ret
return wrapper
@log
def test1(s):
print('test1 ..', s)
return s
@log
def test2(s1, s2):
print('test2 ..', s1, s2)
return s1 + s2
# 首先这里用修饰符添加新功能后,返回的是一个函数
# 这个函数的作用在于:
# 1、打印 'log开始 ...',打印函数名(通用功能)
# 2、运行函数特有功能,返回一个值
# 3、打印 'log结束 ...'(通用功能)
# 4、返回之前的值
answer_1 = test1('a') # 这里直接运行了返回的函数 wrapper
print("\n")
answer_2 = test2('a', 'bc') # 这里直接运行了返回的函数 wrapper
print("\n")
print(answer_1) # 打印返回值
print(answer_2) # 打印返回值
运行结果:
log开始 ... test1
test1 .. a
log结束 ...
log开始 ... test2
test2 .. a bc
log结束 ...
a
abc
2.3 修饰符带有参数
from functools import wraps
def log(arg):
def _log(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('log开始 ...', func.__name__, arg)
ret = func(*args, **kwargs)
print('log结束 ...')
return ret
return wrapper
return _log
@log('module1')
def test1(s):
print('test1 ..', s)
return s
@log('module2')
def test2(s1, s2):
print('test2 ..', s1, s2)
return s1 + s2
answer_1 = test1('a')
print("\n")
answer_2 = test2('a', 'bc')
print("\n")
print(answer_1)
print(answer_2)
运行结果:
log开始 ... test1 module1
test1 .. a
log结束 ...
log开始 ... test2 module2
test2 .. a bc
log结束 ...
a
abc