Python 修饰器的一些小细节

2018-12-03 21:39:57 +08:00
 rizon

前贴 /t/513929 中提到了 python 修饰器的一个疑问,经过一番研究终于明白了,总结了一下,然后就发出来了分享一下。与君共勉

"""
带参数修饰器会在初始化时就执行修饰器的代码并将方法体重新赋值给方法名。
"""


def deco1(args):
    """
    方法执行时不会再执行修饰器代码,**因为该代码返回了方法本身**
    等价于:
        def deco1(args):
            print("deco1:",args)
            return lambda fn:fn
        test1=deco1(args='deco1args')(mymethod)
    :param args:
    :return:
    """

    def decorator(fn):
        print('deco1:', args)
        return fn

    return decorator


@deco1("deco1args")
def test1():
    print("test1")


"""
不带参数修饰器在初始化的时候会将方法名赋值给修饰器方法,修饰器方法内部来手动调用被修饰的方法。
"""


def deco2(fn):
    """
    方法每次执行时都会执行修饰器因为 test2 重新赋值为修饰器的函数
    等价于:
        def deco2(fn):
            def inFn():
                print('deco2')
                fn()
            return inFn
        myMethod2 = deco2(lambda: print("call myMethod2"))
    :param fn:
    :return:
    """

    def decorator():
        print('deco2')
        fn()

    return decorator


@deco2
def test2():
    print("test2")


def deco3(fn):
    """
    不会执行 fn 因为 fn 没有被调用
    等价于:
        def deco3(fn):
            def inFn():
                print('deco3')
                return fn
            return inFn
        test3=deco3(test3)

    :return:
    """

    def decorator():
        print('deco3')
        return fn

    return decorator


@deco3
def test3():
    print("test3")


if __name__ == '__main__':
    print("-----开始执行 main 方法-----")

    print("test1 每次调用都不会执行修饰器:")
    test1()
    print("")
    test1()

    print("======")
    print("test2 每次调用都会执行修饰器:")
    test2()
    print("")
    test2()
    print("======")
    print("test3 不会被执行:")
    test3()
    print("test3 的返回值才是 test3 方法,因此要这样执行:")
    test3()()

"""
---------
"""

print("-------等价函数------")


def eqDeco1(args):
    print("deco1:", args)
    return lambda fn: fn


print("deco1 的等价:")

myMethod = eqDeco1(args='deco1args')(lambda: print("call myMethod1"))
myMethod()


def eqDeco2(fn):
    def inFn():
        print('deco2')
        fn()

    return inFn


myMethod2 = eqDeco2(lambda: print("call myMethod2"))
myMethod2()


def eqDeco3(fn):
    def inFn():
        print('deco3')
        return fn

    return inFn


myMethod3 = eqDeco3(lambda: print("call myMethod3"))
myMethod3()
myMethod3()()

执行结果

deco1: deco1args
-----开始执行 main 方法-----
test1 每次调用都不会执行修饰器:
test1

test1
======
test2 每次调用都会执行修饰器:
deco2
test2

deco2
test2
======
test3 不会被执行:
deco3
test3 的返回值才是 test3 方法,因此要这样执行:
deco3
test3
-------等价函数------
deco1 的等价:
deco1: deco1args
call myMethod1
deco2
call myMethod2
deco3
deco3
call myMethod3
1532 次点击
所在节点    Python
1 条回复
shylockhg
2018-12-04 09:21:43 +08:00
嗯 装饰器就是函数重新赋值的语法糖。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/513981

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX