python 装饰器

发布时间:2018-02-26 16:47:14编辑:admin阅读(3710)

    装饰器本质上是一个Python函数,它可以让其他函数在不雲要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。

    它经常用于有切面雲求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。

    装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大畺与函数功能本身无关的雷同代码并继续重用。

    概括的讲,装饰器的作用就是为已经存在的对象添加颉外的功能。


    定义:

    本质是函数,装饰器他函数,为器他函数添加附加功能。


    原则:

    不能修改被装饰函数的源代码

    不能修改被装饰函数的调用方法


    总结:

    装饰器对被装饰的函数,是完全透明的,没有任何影响。


    举个例子:

    下面有一个函数,需要加一个功能,打印程序执行的时间

    import time
    def test1():
        #等待1秒,表示代码逻辑部分,这里直接简写了
        time.sleep(1)
        print('in the test1')

    这个函数已经上线很久了,如果更改源代码,是有风险的。

    这个时候,用装饰器,就可以解决这个问题。

    import time
    def timmer(func):
        def warpper(*args,**kwargs):
            start_time = time.time()
            func()
            stop_time = time.time()
            print('the func run time is %s' %(stop_time - start_time))
        return warpper
    
    @timmer
    def test1():
        time.sleep(1)
        print('in the test1')
    
    test1()

    执行输出

    in the test1

    the func run time is 1.0007095336914062


    首先需要写一个装饰器函数,在被装饰的函数名上一行,加@装饰器函数名,就可以了


    实现装饰器知识储备:

    1.函数即"变量"

    2.高级函数

      a.把一个函数名当作实参传给另外一个函数(不修改被装饰函数的源代码前提下,为其添加功能)

      b.返回值中包含函数名(不修改函数的调用方式)

    3.嵌套函数


    高阶函数+嵌套函数 = 装饰器


    def bar():
        print('in the bar')
    
    def test1(func):
        print(func)
    
    test1(bar)

    执行输出


    得到的结果是一个内存地址。


    def bar():
        print('in the bar')
    
    def test1(func):
        print(func)
        func()
    
    test1(bar)

    执行输出


    in the bar


    func执行,得到一个内存地址,因为它是一个变量,函数即变量

    func()执行,就是把内存地址的内容调取出来,得到in the bar


    import time
    def bar():
        time.sleep(1)
        print('in the bar')
    
    def test1(func):
        start_time = time.time()
        #执行bar()函数
        func()
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
    
    test1(bar)

    执行输出

    in the bar

    the func run time is 1.000032901763916


    test1(bar)执行的时候,把bar函数传进去了

    那么test1函数体内的func就等同于bar函数

    所以程序执行,输出了上面2行的结果。


    上面的代码,貌似实现了装饰器的功能。源代码bar,并没有修改啊,但是违背了第2个原则,修改了函数的调用方法。

    默认bar函数调用时,直接bar()就可以了,现在变成了test1(bar)。



    import time
    def bar():
        time.sleep(1)
        print('in the bar')
    
    def test2(func):
        print(func)
        return func
    
    print(test2(bar))

    执行输出

    function bar at 0x0000017DFD6E3E18

    function bar at 0x0000017DFD6E3E18


    返回的结果是一个内存地址


    把执行方式改一下

    t = test2(bar)
    print(t)

    执行输出

    function bar at 0x0000017DFD6E3E18

    in the bar


    貌似没什么卵用


    再改一下

    t = test2(bar)
    t()

    执行输出

    function bar at 0x0000017DFD6E3E18

    in the bar


    t()相当于执行了bar函数,貌似没啥卵用


    再改一下

    bar = test2(bar)
    bar()

    执行输出

    function bar at 0x0000017DFD6E3E18

    in the bar


    结果和上面是一样的,但是调用方式,发现和原函数调用是一模一样的。

    下面打印一下bar的类型是变量还是函数

    bar = test2(bar)
    print(type(bar))
    bar()

    执行输出

    blob.png

    可以看出,bar赋值之后,变成了函数,为什么呢?因为test2本身就是函数,所以它当然是函数了。

    所以才可以执行bar()


    但是bar()已经不是原来的bar函数了,而是被装饰过的函数。

    因为原来的bar执行,只会输出 in the bar



    函数嵌套

    定义:在一个函数中定义了另外一个函数


    在一个函数体内,用def去声明一个新的函数,而不是去调用它。

    下面是一个嵌套函数

    def foo():
        print('in the foo')
        def bar():
            print('in the bar')
    
        bar()
    
    foo()

    执行输出

    in the foo

    in the bar





关键字