V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
rizon
V2EX  ›  Python

Python 修饰器的一些小细节

  •  
  •   rizon ·
    othorizon · 2018-12-03 21:39:57 +08:00 · 1509 次点击
    这是一个创建于 2175 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前贴 /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
    
    1 条回复    2018-12-04 09:21:43 +08:00
    shylockhg
        1
    shylockhg  
       2018-12-04 09:21:43 +08:00
    嗯 装饰器就是函数重新赋值的语法糖。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1893 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 16:29 · PVG 00:29 · LAX 08:29 · JFK 11:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.