python --@函数装饰器详解

2019-08-01  本文已影响0人  有事没事扯扯淡

当程序使用“@函数”(比如函数 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,这意味着程序要完成两步操作:

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

[参考链接]
http://c.biancheng.net/view/2270.html

上一篇下一篇

猜你喜欢

热点阅读