装饰器

Posted xulan0922

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了装饰器相关的知识,希望对你有一定的参考价值。

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

两个原则:

1.不修改被修饰函数的源代码

2.不修改被修饰函数的调用方式

 一个栗子

def test():
    res = 0
    for i in range(50):
        res += i
    print(res)
test()
结果:1225

需求:要想计算上述函数的运行时间,既不修改被修饰函数的源代码,又不修改被修饰函数的调用方式,关键还要能添加进附加功能,如何实现?

如下,初级版本一直接修改了被修饰函数的源代码

import time
def test():
    start_time = time.time()
    res = 0
    for i in range(50):
        time.sleep(0.1)
        res += i
    print(res)
    end_time = time.time()
    print(执行的时间 %s %(end_time - start_time))
test()
结果:1225
执行的时间 5.027297258377075

这么做是不可行的,如果有一百个函数呢,需要去改一百个函数的源代码。

 

Python装饰器的知识要点:

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

我们从这三个知识点,循序渐进,一点点演变,最后完成上述的需求

先看使用高阶函数的版本二:

import time                  //被修饰函数的源代码没有动
def test():
    res = 0
    for i in range(50):
        res += i
    print(res)

def print_time(func):
    start_time = time.time()
    func()
    time.sleep(1)
    end_time = time.time()
    print(执行的时间 %s %(end_time - start_time))

print_time(test)              //被修饰函数的调用方式被修改了
结果:1225
执行的时间 1.0009217262268066

被修饰函数的源代码确实没有修改,但是被修饰函数的调用方式发生了变化,不合格。

再看使用高阶函数的版本三:

import time
def test():
    res = 0
    for i in range(50):
        res += i
    print(res)

def print_time(func):
    start_time = time.time()
    func()
    time.sleep(1)
    end_time = time.time()
    print(执行的时间 %s %(end_time - start_time))
    return func            //这步是关键,把当参数穿进去的函数,再热return回来,为了后面赋值给原本的函数名test,这样就可以不修改被修饰函数的调用方式

test = print_time(test)    //赋值给原本的函数名test
test()                     //被修饰函数的调用方式没有变化
结果:1225
执行的时间 1.0000982284545898
1225

看似符合要求了,但是我们看运行结果,test()被执行了两遍,还是不合格。

所以光靠高阶函数,无法达到目标,现在来看函数嵌套和闭包

函数嵌套是指在一个函数里定义另一个函数,而不是在一个函数里调用另一个函数

闭包:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。它只不过是个“内层”的函数,由一个名字(变量)来指
代,而这个名字(变量)对于“外层”包含它的函数而言,是本地变量。

 技术分享图片

 

以上是关于装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Python面向对象学习之八,装饰器

thymeleaf 片段渲染后重新加载 javascript

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码

代码缺乏装饰?使用ts装饰器来装饰你的代码