python 高阶函数:Decorato

发布时间:2019-07-12 10:00:01编辑:auto阅读(1542)

    装饰器:原函数基础 ------> 动态添加功能


    一、不带参数的decorator

    #decorator封装

    def log(func):
        def wrapper(*args, **kw):
            print 'call %s():' %func.__name__
            return func(*args, **kw)
        return wrapper


    #此函数一定要放在 def log(func): 之后

    @log   
    def now():
        print "haha"

       
    now()

    log.PNG


    log(now())
    log.PNG


    print "now_name:%s"%now.__name__

    log1.PNG


    简单的图解:(待以后深入理解后再详细补)

    log图解.png


    二、带参数的docurator

    #!/usr/bin/python

    #docurator封装

    def log(text):
        def decorator(func):
            def wrapper(*args, **kw):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator


    @log('execute')
    def now():
        print "haha"    


    print "now_name:%s"%now.__name__ 

    log1.PNG


    now()

    log2.PNG


    print log('execute')
    print log(now)
    print log('execute')(now)

    log3.PNG


    三、完整的decorator的写法:Python内置的functools.wraps  

    import functools  #导入functools模块

    def log(text):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print('%s %s():' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator

    @log('execute')
    def now():
        print "haha"
       
    print "now_name:%s"%now.__name__  

    log4.PNG

    now()

    log2.PNG

    print log('execute')
    print log(now)
    print log('execute')(now)

    log5.PNG



    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    日期:2018/8/18

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    补充:

    1. 多个装饰器的执行顺序是无序的,但执行过程是有序的。

    2. 装饰器执行过程是:遇到外接函数就跳转到另一个装饰器中执行,若再另一个装饰器中遇到同样的外接函数,则继续执行


    证明1:多个装饰器的执行顺序是无序的

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import time
    
    
    def extend(func):
        def wrapper(*args, **kwargs):
            print "Begin AAAAAA"
            func(*args, **kwargs)
            print("A:%s"%(func.__name__))
            print(reduce(lambda x,y:x+y, args), kwargs)
            print "End AAAAA"
        return wrapper
    
    
    def extend1(func):
        def wrapper(*args, **kwargs):
            print "Begin BBBBB"
            func(*args, **kwargs)
            print("B:%s"%(func.__name__))
            print(map(lambda x:x*2, args), kwargs)
            print "End BBBBB"    
        return wrapper
    
    @extend      
    @extend1
    def get_time1(*args,**kwargs):
        begin_time = time.time()
        for n in range(3,4):
            time.sleep(1)
        end_time = time.time()
        print("run %d "% (end_time - begin_time))
        #print(reduce(lambda x,y:x+y, args), kwargs)
    
        
    if __name__ == "__main__":
    
        get_time1(1,2,3,4,5,6,ma=1,du=2)

    执行结果:先从第一个装饰器标志@extend开始

    Begin AAAAAA
    Begin BBBBB
    run 1 
    B:get_time1
    ([2, 4, 6, 8, 10, 12], {'du': 2, 'ma': 1})
    End BBBBB
    A:wrapper
    (21, {'du': 2, 'ma': 1})
    End AAAAA


    另一个例子:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    def dec1(func):  
        print("1111")  
        def wrapper(*args, **kwargs):  
            print("2222")  
            func()  
            print("3333")  
        return wrapper  
    
    def dec2(func):  
        print("aaaa")  
        def wrapper(*args, **kwargs):  
            print("bbbb")  
            func()  
            print("cccc")  
        return wrapper  
    
    @dec1  
    @dec2  
    def test():  
        print("test test")  
    
    test()

    运行结果:从第二个装饰器标志@dec2开始

    aaaa
    1111
    2222
    bbbb
    test test
    cccc
    3333


    通过比较,多个解释器的执行顺序是无序的。若大家觉得证明不够严谨,可自己多添几个试试。


    证明2:装饰器的执行过程是有序的

    图1:

    装饰器原函数1.png


    图2:

    装饰器原函数倒装1.png




    没看懂?没关系,进行步骤解析:

    装饰器原函数结果解析1.png



    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    2018/8/20

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    补充:一个讲的很好的BLOG:  https://blog.csdn.net/xiangxianghehe/article/details/77170585


关键字