• Python笔记 之 闭包及装饰器


    闭包

    定义

    在函数内部定义一个内嵌函数,内嵌函数引用外部函数的变量并且作为外部函数的返回值返回。

    满足条件

    创建一个闭包需要满足以下几点:

    • 必须有一个内嵌函数;
    • 内嵌函数必须引用外部函数中的变量;
    • 外部函数的返回值必须是内嵌函数。
    • 示例
    def user(name):  
       def introduce():  
          print('大家好,我叫{}'.format(name))  
       return introduce    
      
    user1 = user('杨过')  
    user1()  # 大家好,我叫杨过
    
    user2 = user('小龙女')  
    user2() # 大家好,我叫小龙女
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    闭包的作用

    闭包的最大特点是可以将函数的变量与内嵌函数进行绑定,并返回绑定变量后的内嵌函数,此时即便生成闭包的环境已经释放,内嵌函数仍然存在。

    from concurrent.futures import ThreadPoolExecutor 
      
    pool = ThreadPoolExecutor(10)  # 定义10个线程的线程池  
      
      
    def func1(i):  
       '''定义执行函数,返回值为i'''  
       print(str(i).center(5, '-'))  
       return i  
      
      
    def outer(i):  
       '''定义闭包'''  
       def func2(func):  
          '''会调函数打印函数执行结果及将传入参数格式化'''  
          print(func.result(), str(i).center(5, '*'))  
       return func2  
      
      
    def run():  
       for i in range(30):  
          f = pool.submit(func1, i)  
          cb = outer(i)  
          f.add_done_callback(cb)  
       pool.shutdown(wait=True)  
      
      
    if __name__ == '__main__':  
       run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    装饰器

    定义

    实质上也是一个闭包,闭包传递的是变量,而装饰器传递的是函数,也就是说,装饰器是一个传递函数的闭包。

    示例

    打印【0,num】并计算函数执行时间

    import time  
    def decorator(func):  
       def runtime(num):  
          time_begin = time.time()  
          func(num)  
          print('函数{}执行耗时{}秒。'.format(func.__name__, round(time.time() - time_begin, 4)))  
       return runtime  
      
    @decorator  
    def run(num):  
       for i in range(num):  
          print(i)  
    run(100)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意事项

    import time  
    def decorator(func):  
       """装饰器"""  
       def runtime(num):  
          time_start = time.time()  
          sum = func(num)  
          print('函数{}运行时长:{}秒。'.format(func.__name__, round(time.time() - time_start, 6)))  
          return sum  
       return runtime  
    @decorator  
    def run(num):  
       sum = 0  
       for i in range(num):  
          sum += i  
       return sum  
    print(run(10000000))
    # 函数run运行时长:0.530971秒。
    # 49999995000000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 装饰器可以定义多个内嵌函数,但是只能返回一个
    • 返回的内嵌函数参数和被修饰的函数参数一致
    • 对装饰器的使用通过@装饰器名称实现

    装饰器的作用

    在不改变原函数的情况下,对已有函数进行额外的功能扩展,示例就展示了在不改变函数run的情况下输出run运行时间。

    带参数的装饰器

    在装饰器外再包含一层即可实现带参数的装饰器。

    import time  
    def decorator(num):  
       """带参数的装饰器"""  
       def outer(func):  
          def runtime(*args):  
             print('Before:')  
             time_start = time.time()  
             sum = func(*args)  
             print('{}.函数{}运行时长:{}秒。'.format(num,func.__name__, round(time.time() - time_start, 6)))  
             return sum + args[0]  
          return runtime  
       return outer  
    @decorator(100)  
    def run(*args):  
       sum = 0  
       for i in range(args[0]):  
          sum += i  
       return sum  
    print(run(100))
    # Before:
    # 100.函数run运行时长:0.0秒。
    # 5050
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    Python中关于类属性、类方法和静态方法的【综合案例】— 设计一个Game类
    多线程合集(三)---异步的那些事之自定义AsyncTaskMethodBuilder
    Power BI前端设计:深度探索与实战技巧
    产业互联网,正在进入到深水区,人们对于产业互联网的认识才能够全面
    SystemVerilog-(按)位运算符
    基于hexo框架快速从0到1搭建个人博客----文章写作(四)
    SpringBoot+JWT实现单点登录解决方案
    Go语言Slice(切片)
    【必读】从零开始,一步步教你安装nginx,搭建个人博客网站!
    webp格式转换成png的方法
  • 原文地址:https://blog.csdn.net/weixin_50648794/article/details/126460554