当程序使用“@函数”(比如函数 A)装饰另一个函数(比如函数 B)时,实际上完成如下两步:
将被修饰的函数(函数 B)作为参数传给 @ 符号引用的函数(函数 A)
将函数 B 替换(装饰)成第 1 步的返回值。
举个栗子~~~
def funA(fn):
print('A')
fn() # 执行传入的fn参数
return 'fkit'
'''
下面装饰效果相当于:funA(funB),
funB 将会替换(装饰)成 funA() 语句的返回值;
由于funA()函数返回 fkit,因此 funB 就是 fkit
'''
@funA
def funB():
print('B')
print(funB) # fkit
上面程序使用 @funA 修饰 funB,这意味着程序要完成两步操作:
- 将 funB 作为 funA() 的参数,也就是上面代码中 @funA 相当于执行 funA(funB)。
- 将 funB 替换成 funA() 执行的结果,funA() 执行完成后返回 fkit,因此 funB 就不再是函数,而是被替换成一个字符串。
运行上面程序,可以看到如下输出结果:
A
B
fkit
被修饰的函数总是被替换成 @ 符号所引用的函数的返回值,因此被修饰的函数会变成什么,完全由于 @ 符号所引用的函数的返回值决定,换句话说,如果 @ 符号所引用的函数的返回值是函数,那么被修饰的函数在替换之后还是函数。
def foo(fn):
# 定义一个嵌套函数
def bar(*args):
print("===1===", args)
n = args[0]
print("===2===", n * (n - 1))
# 查看传给foo函数的fn函数
print(fn.__name__)
fn(n * (n - 1))
print("*" * 15)
return fn(n * (n - 1))
return bar
'''
下面装饰效果相当于:foo(my_test),
my_test将会替换(装饰)成该语句的返回值;
由于foo()函数返回bar函数,因此funB就是bar
'''
@foo
def my_test(a):
print("==my_test函数==", a)
# 打印my_test函数,将看到实际上是bar函数
print(my_test) # <function foo.<locals>.bar at 0x00000000021FABF8>
# 下面代码看上去是调用my_test(),其实是调用bar()函数
my_test(10)
my_test(6, 5)
运行上面程序,可以看到如下输出结果:
<function foo.<locals>.bar at 0x000001C2A5953510>
===1=== (10,)
===2=== 90
my_test
==my_test函数== 90
***************
==my_test函数== 90
===1=== (6, 5)
===2=== 30
my_test
==my_test函数== 30
***************
==my_test函数== 30
网友评论