Python 如何理解又晕又好用的装饰器

发布时间:2019-08-28 09:09:04编辑:auto阅读(1435)

    Python 装饰器这东西对初学者来说是个坑,很容易绕晕,笔者当时初学装饰器时花费了数天时间,看了不同讲师对这块内容的讲解,还是一知半解。  


     不过装饰器在开发中可是很好用的,有必要攻破,希望这篇文章能帮助学习者快速攻破难关。



    初步理解

    # 先来看一个简单函数
    
    def show():
        print ('Mr tu')
    
    show()
    
    # 执行结果 :
    
    Mr tu
    
    
    # 现在我们用装饰器扩展这个函数,在打印 " Mr tu " 之前打印一行 " hello "  
    
    
    def decorate(fun1):
        def wapper():
            print('hello')
            fun1()
        return wapper
    
    
    @decorate
    def show():
        print ('Mr tu')
    
    show()
    
    
    # 执行结果 :
    
    hello
    Mr tu
    
    
    # 现在解释上面的代码。
    
    # 1、首先 def decorate(fun1) 定义一个装饰器函数,在此函数里又定义了一个wapper子函数,子函数可以继承父函数的参数。
    
    # 2、 @'函数名'是Python的一种语法糖 @decorate 等于 decorate(show) 
    
    # 还是晕,不明白?  没关系,看下面代码:
    
    
    def decorate(fun1):
        def wapper():
            print('hello')
            fun1()
        return wapper
    
    
    def show():
        print ('Mr tu')
    
    f1 = decorate(show)
    f1()
    
    # 执行结果 :
    
    hello
    Mr tu
    
    # 换成这种写法,执行效果是一样的,因为这就是 @decorate 的本质。
    
    # 就是将被装饰器装饰的函数show作为参数传给装饰器函数。
    
    # 总结执行过程:
    
    # 1、show函数作为参数传给装饰器函数 decorate ,那么 fun1 = show
    
    # 2、这时执行到装饰器的子函数 wapper,子函数可以继承父函数的参数,所以可以调用 fun1 
    
    # 3、然后wapper函数执行 print 打印一行 "hello" , 再然后  调用fun1() —— 这里其实就是执行了show函数。  因为在装饰器一开始执行的时候就把show函数作为参数赋值给了fun1.
    
    
    # 现在明白了吧,只要这里明白,下面的就很好理解了。



    装饰带参数的函数

    # 一个参数
    
    def decorate(fun1):
        def wapper(arg1):
            print('hello')
            fun1(arg1)
            print('nice to meet you')
        return wapper
    
    @decorate
    def show(arg1):
        print (arg1)
    
        
    show('Mr Alice')
    
    # 执行结果:
    
    hello
    Mr Alice
    nice to meet you
    
    
    # 两个参数
    
    def decorate(fun1):
        def wapper(arg1,arg2):
            print('hello')
            fun1(arg1,arg2)
            print('nice to meet you')
        return wapper
    
    @decorate
    def show(arg1,arg2):
        print (arg1,arg2)
    
    
    show('Mr Alice','Mr Tom')
    
    # 执行结果:
    
    hello
    ('Mr Alice', 'Mr Tom')
    nice to meet you
    
    
    # n个参数
    
    def decorate(fun1):
        def wapper(*args,**kwargs):
            print('hello')
            fun1(*args,**kwargs)
            print('nice to meet you')
        return wapper
    
    @decorate
    def show(*args,**kwargs):
        print (args[0])
        print (args[1])
        print (args[2])
    
    
    show('Mr Alice','Mr Tim','Mr tu')
    
    
    # 执行结果:
    
    hello
    Mr Alice
    Mr Tim
    Mr tu
    nice to meet you


    一个函数被多个装饰器装饰

    def decorate01(fun1):
        def wapper(*args,**kwargs):
            print('hello world')
            print('I am decorate01')
            fun1(*args,**kwargs)
        return wapper
    
    
    def decorate02(fun1):
        def wapper(*args,**kwargs):
            print ('I am decorate02')
            fun1(*args,**kwargs)
            print('nice to meet you')
        return wapper
    
    
    @decorate01
    @decorate02
    def show(*args,**kwargs):
        print (args[0])
        print (args[1])
        print (args[2])
    
    
    show('Mr Alice','Mr Tim','Mr tu')
    
    
    # 执行结果:
    
    hello world
    I am decorate01
    I am decorate02
    Mr Alice
    Mr Tim
    Mr tu
    nice to meet you
    
    
    # 观察print放置的位置不同,对应的输出结果不同。
    
    
    def decorate01(fun1):
        def wapper(*args,**kwargs):
            print('hello world')
            fun1(*args,**kwargs)
            print('I am decorate01')  # 替换到了下面
        return wapper
    
    
    def decorate02(fun1):
        def wapper(*args,**kwargs):
            print ('I am decorate02')
            fun1(*args,**kwargs)
            print('nice to meet you')
        return wapper
    
    
    @decorate01
    @decorate02
    def show(*args,**kwargs):
        print (args[0])
        print (args[1])
        print (args[2])
    
    
    show('Mr Alice','Mr Tim','Mr tu')
    
    
    # 执行结果:
    
    hello world
    I am decorate02
    Mr Alice
    Mr Tim
    Mr tu
    nice to meet you
    I am decorate01


    装饰器功能扩展

    #!/usr/local/python27/bin/python2.7
    
    def before(request,*args,**kwargs):
        print('before')
    
    
    def after(request,*args,**kwargs):
        print('after')
    
    
    def Filter(before_func,after_func):
        def outer(fun1):
            def wapper(request,*args,**kwargs):
    
                before_result = before_func(request,*args,**kwargs)
                if(before_result != None):
                    return before_result;
    
    
                fun1_result = fun1(request,*args,**kwargs)
                if(fun1_result != None):
                    return fun1_result;
    
    
                after_result = after_func(request,*args,**kwargs)
                if(after_result != None):
                    return after_result;
    
            return wapper
        return outer
    
    
    
    @Filter(before,after)
    def show(request,*args,**kwargs):
        print ('Mr tu')
    
        
    show('1')
    
    
    # 执行结果:
    
    before
    Mr tu
    after


    函数若未定义返回值,执行成功返回值默认为 None ,这里的语句 if (before_result != None) 意思就是before函数执行失败时采取什么操作。


关键字