• python中的闭包函数&装饰器


    本文为在霍格沃兹测试开发学社中学习到的一些技术(或者:本文为在霍格沃兹测试开发学社的学习经历分享),写出来分享给大家,希望有志同道合的小伙伴可以一起交流技术,一起进步~

    当我们在python中定义一个函数中,我们可能需要这个函数执行的一些其他属性等等,如下面的例子:

    当我们在执行一个函数时,打印这个函数运行时总共运行了多长的时间

    首先定义该函数:

    1. def hog(name):
    2.     print(f'这个是被包裹的函数{name}')
    3.     time.sleep(1)

    其次打印这个函数的执行总共需要运行的时间是多少

    1. start_time = datetime.now()
    2. print(f'函数执行前的时间是{start_time}')
    3. hog('hog')
    4. end_time = datetime.now()
    5. print(f'函数执行后的时间是{end_time}')
    6. print(f'f函数执行总共用的时间是{end_time-start_time}')

    如果我们再还一个其他的函数,去计算它执行的时间有多少,需要将上面的代码再重复的编写,通过再次封装一个函数,我们将这个功能去实现出来

    在这里,变化的是这个函数,那么我们将这个函数作为一个参数去传入另外一个实现该功能的函数,并在此函数中去定义我们需要计算执行时间的函数

    1. def cal_time(func,name):
    2.     start_time = datetime.now()
    3.     print(f'函数开始执行的时间是:{start_time}')
    4.     func(name)
    5.     end_time = datetime.now()
    6.     print(f'函数结束执行的时间是:{end_time}')
    7.     print(f'函数运行结束使用的时间是:{end_time-start_time}')
    8. #调用这个函数
    9. cal_time(hog,'hog')

    上述代码中我们将实现打印函数执行的时间功能封装成了一个函数,这样其他的函数有计算执行时间的需求时,我们即将这个函数的引用传入即可

    但同时又引入其他的一些问题:

            1.我们在调用函数的时候,调用方式是cal_time(hog,'hog'),代码的可读性比较差,我们在阅读代码时,有时候会不清晰为什么要调用外部的这个函数,容易搞混淆

            2.外函数的实现封装的功能可读性也不够明确

            3,每个函数可能会有不同的参数

    那么基于以上的问题,我们有了以下的解决方式

    在上述的代码方式中,我们在外函数里面又定义了一个内函数,在内函数中实现功能,并且调用需要执行的函数,并将这个内函数的引用返回;且内函数可以传入多种参数,解决了上述的第2个和第3个问题

    1. def close(func):
    2.     def inner(*args,**kwargs):
    3.         start_time = datetime.now()
    4.         print(f'函数执行前的时间是{start_time}')
    5.         func(*args,**kwargs)
    6.         end_time = datetime.now()
    7.         print(f'函数执行后的时间是{end_time}')
    8.         print(f'f函数执行总共用的时间是{end_time-start_time}')
    9.     return inner
    10. close(hog)('hog')

    首先我们来了解下闭包函数的定义:

    一个函数的返回值是另外一个函数,返回的函数调用父函数内部的变量,如果返回的函数在外部被执行,就产生了闭包函数。

    我们定义的上述函数其实就是闭包函数,我们在close函数中定义了一个内函数,并且该外函数的返回值是一个该内函数,而我们在执行close(hog)('hog')时,实际上也是执行内函数,于是上述就是一个闭包函数

    下面就引入了我们的装饰器,而我们装饰器本质上就是一个闭包函数,只是编写的格式不同

    1. def close(func):
    2.     def inner(*args,**kwargs):
    3.         start_time = datetime.now()
    4.         print(f'函数执行前的时间是{start_time}')
    5.         func(*args,**kwargs)
    6.         end_time = datetime.now()
    7.         print(f'函数执行后的时间是{end_time}')
    8.         print(f'f函数执行总共用的时间是{end_time-start_time}')
    9.     return inner
    10. @close
    11. def hog(name):
    12.     print(f'这个是被包裹的函数{name}')
    13.     time.sleep(1)
    14. hog('hog')

    我们在使用装饰器之后,仅使用hog('hog')即可,就可以实现上述函数的调用。

    问题又来了,为什么在被包裹的函数定义前加@close,就可以直接去调用被包裹的函数呢,我们看看调试的信息

    当我们直接使用hog('hog')如下图,可以看到,hog函数的引用被赋值外函数中内函数的引用,那么hog(‘hog’),就相当于是内函数的调用,因此我们直接使用hog('hog')就等价于close(hog)('hog')

    如此,我们的装饰器就完成啦!

    推荐阅读文章链接:接口测试经典面试题:Session、cookie、token有什么区别?_霍格沃兹测试开发学社的博客-CSDN博客

     

  • 相关阅读:
    记一次服务器异常掉电,导致HBase Master is initializing 问题处理
    SQL语言入门,语法,语句分类
    前端开发攻略---合并表格单元格,表格内嵌套表格实现手风琴效果。
    Zip4j使用
    Web开发介绍,制作小网站流程和需要的技术【详解】
    web:[ACTF2020 新生赛]Exec
    网络资料搬运(2)
    uwsgi的一些课外知识:uwsgi、uWSGI、WSGI、web服务器、应用服务器、socket
    路由器,集线器,交换机,网桥,光猫有啥区别?
    Docker网络模型
  • 原文地址:https://blog.csdn.net/miqingzhiwen/article/details/127672639