• python - 闭包与装饰器


    目录

    一、python的闭包

    示例1:闭包

    示例2:形成闭包的条件

    示例3:形成闭包以后,闭包函数会得到一个非空的__closure__属性

    示例4:赋值引用闭包和直接调用外函数的区别

    二、装饰器

    示例1:统计函数执行时间

    示例2:写一个统计函数运行时间的装饰器

    示例3:什么是装饰器

    示例4:用装饰器实现权限控制

    示例5:保留元数据

    示例6:用类实现装饰器

    示例7:装饰类


    一、python的闭包

    示例1:闭包

    1. def outer(x):
    2. a = 300
    3. def inner():
    4. print(f"两数之和{x + a}")
    5. return inner
    6. d = outer(10)
    7. d()

     变量解析原则:

            LEGB 原则

             local当前局部变量  enclosing function 闭包空间  global全局  buildins 内建模块
             理论上来说,函数执行完了以后,变量a会释放
             但是这个时候还有inner函数在引用他们,这个时候就形成了闭包

    示例2:形成闭包的条件

    1. 形成闭包条件:(缺一不可)
    2. 1、必须有一个内嵌函数
    3. 2、内函数必须引用外函数的变量
    4. 3、外函数必须返回内函数

    示例3:形成闭包以后,闭包函数会得到一个非空的__closure__属性

    1. def outer(x):
    2. a = 300
    3. def inner():
    4. print(f"两数之和{x + a}")
    5. return inner
    6. d = outer(10)
    7. d()
    8. # 闭包形成后,闭包函数会得到一个非空的__closure__属性
    9. print(dir(d))
    10. print(d.__closure__)
    11. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/01、闭包.py
    12. 两数之和310
    13. ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    14. (0x0000015CD0A9FE80: int object at 0x0000015CD09993B0>, 0x0000015CD09417F0: int object at 0x0000015CBEE46A50>)
    15. Process finished with exit code 0

    示例4:赋值引用闭包和直接调用外函数的区别

    虽然代码一样,但是每次调用外函数都会重新执行,创建一个新的tmp_list和inner
    匿名变量,都是统一放到匿名空间的,所以地址一样
    1. tmp_list = []
    2. def outer():
    3. tmp_list = []
    4. def inner(name):
    5. tmp_list.append(1)
    6. print(f"{name} -- {tmp_list}")
    7. return inner
    8. d1 = outer()
    9. d2 = outer()
    10. d1("d1")
    11. d2("d2")
    12. # 虽然代码一样,但是每次调用外函数都会重新执行,创建一个新的tmp_list和inner
    13. print(id(d1), id(d2))
    14. # 匿名变量,都是统一放到匿名空间的,所以地址一样
    15. print(id(outer()), id(outer()))
    16. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/01、闭包.py
    17. d1 -- [1]
    18. d2 -- [1]
    19. 2138501753296 2138501753440
    20. 2138501753584 2138501753584

    二、装饰器

    示例1:统计函数执行时间

    时间戳:

            从1970年1月1日的0点0分0秒到现在所经历的秒数

    1. import time
    2. def func1():
    3. time.sleep(2)
    4. print("func1....")
    5. # 时间戳
    6. # 从1970年1月1日的0点0分0秒到现在所经历的秒数
    7. t1 = time.time()
    8. func1()
    9. t2 = time.time()
    10. print(f"函数执行时间{t2 - t1}")
    11. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
    12. func1....
    13. 函数执行时间2.0112464427948

    示例2:写一个统计函数运行时间的装饰器

    @ :修饰符

    1. import time
    2. def runtime(func):
    3. print("this is runtime")
    4. def inner():
    5. start = time.time()
    6. func()
    7. end = time.time()
    8. print(f"函数执行花了{end - start}s")
    9. return inner
    10. @runtime # @修饰符去使用装饰器 # runtime(func2)
    11. def func2():
    12. time.sleep(2)
    13. print("func2....")
    14. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
    15. this is runtime
    16. func2....
    17. 函数执行花了2.0134215354919434s

    示例3:什么是装饰器

    1. 装饰器是一种模式,它的本质是闭包,
    2. 他在不改变函数或者类的源代码的基础上
    3. 为函数或类添加功能
    1.  装饰器有什么用
    2. • 你可以考虑在装饰器中置入通用功能的代码来降低程序复杂度。例如,可以用装饰器来:
    3. • 引入日志
    4. • 增加计时逻辑来检测性能
    5. • 给函数加入事务的能力
    6. • 权限控制

    示例4:用装饰器实现权限控制

    1. # 装饰器实现权限控制
    2. def login_required(func):
    3. def inner(*args, **kwargs):
    4. if username == "root":
    5. print("欢迎")
    6. result = func(*args, **kwargs)
    7. return result
    8. else:
    9. return "权限不够"
    10. return inner
    11. # 可以应用多个装饰器,但是要注意顺序
    12. # 从最上面的装饰器的内涵式开始执行
    13. @login_required
    14. def add(a, b):
    15. time.sleep(2)
    16. return a + b
    17. username = input("请输入用户名:")
    18. result = add(1, 2)
    19. print(result)
    20. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/02、装饰器.py
    21. 请输入用户名:root
    22. 欢迎
    23. 3

    示例5:保留元数据

    1. import time
    2. def runtime(func):
    3. # 保留传递进来的函数的元数据,将它的元数据赋值给inner
    4. @functools.wraps(func)
    5. def inner(*args, **kwargs): # 让装饰器更加通用
    6. start = time.time()
    7. result = func(*args, **kwargs)
    8. end = time.time()
    9. print(f"函数 {func.__name__} 执行花了:{end -start}s")
    10. return result
    11. return inner
    12. #
    13. # a = runtime("name")
    14. # add = a(add)
    15. @runtime # add = runtime(add)
    16. def add(a, b):
    17. print("this is add ")
    18. time.sleep(1)
    19. return a+b
    20. add(1, 2)
    21. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/03、装饰器参数.py
    22. this is add
    23. 函数 add 执行花了:1.0147972106933594s
    1. import functools
    2. import time
    3. def deco(name):
    4. def runtime(func):
    5. #保留传递进来的函数的元数据,将它的元数据赋值给inner
    6. @functools.wraps(func)
    7. def inner(*args, **kwargs): #让装饰器更加通用
    8. start = time.time()
    9. result = func(*args, **kwargs)
    10. end = time.time()
    11. print(f"函数执行花了{end -start}s")
    12. print(f"name is {name}")
    13. return result
    14. return inner
    15. return runtime
    16. # runtime = deco(name="sanle")
    17. #func1 = runtime(func1)
    18. @deco(name="sanle")
    19. def func1():
    20. time.sleep(3)
    21. print("this is func1")
    22. func1()

    示例6:用类实现装饰器

    1. import time
    2. class A:
    3. def __init__(self, func):
    4. self.func = func
    5. def __call__(self, func):
    6. def deco(*args, **kwargs):
    7. start = time.time()
    8. print("this is call")
    9. result = func(*args, **kwargs)
    10. end = time.time()
    11. print(f"函数执行时间{end - start}")
    12. return result
    13. return deco
    14. @A("name")
    15. def func1():
    16. time.sleep(2)
    17. print("i am func1....")
    18. func1()

    示例7:装饰类

    1. def outer(cls):
    2. def inner(*args, **kwargs):
    3. print(f"class name is:{cls.__name__}")
    4. return cls(*args, **kwargs)
    5. return inner
    6. @outer
    7. class A:
    8. def __init__(self, name):
    9. self.name = name
    10. print(type(A))
    11. m = A("sc")
    12. print(m.name)
    13. E:\python\python3.9.1\python.exe E:/tlbb/2022-07-29-闭包和装饰器/05、装饰类.py
    14. <class 'function'>
    15. class name is:A
    16. sc

  • 相关阅读:
    数据库访问-records库
    Redis主从复制/读写分离的配置
    实验十 继承
    1.3 BEV开源数据集介绍
    [附源码]java毕业设计高校新生报到管理系统
    fatedier/frp内网穿透详细安装及使用教程
    set 和 map的区别
    机器学习——Machine Learning
    ansible入门
    flutter中使用缓存
  • 原文地址:https://blog.csdn.net/qq_48391148/article/details/126063851