• 【python基础】装饰器


    一、闭包

      1、外层函数嵌套内层函数,在内层函数中使用外层函数的局部变量
      2、局部变量和内层函数统称为闭包
      3、内层函数为闭包函数

      闭包函数访问外层函数的局部变量时,访问的总是该变量的最新值

     1 def outer():
     2     x = 10  # 外层函数的局部变量
     3     def inner():
     4         nonlocal x  # 关键字标记 变量x 是外层函数的局部变量
     5         x += 1
     6         return x
     7     return inner
     8 
     9 r1 = outer()  # r1 --> 函数地址(内层函数)
    10 
    11 print(r1())  # 11
    12 print(r1())  # 12
    13 print(r1())  # 13
    14 
    15 r = outer()
    16 print(r)  # <function outer.<locals>.inner at 0x0000000003C7B9D8>
    17 print(r())  #  11 此时才是调用inner()函数的调用处

    二、装饰器

      闭包的应用,对于已经实现定义好了的函数功能,在不改变原函数的情况下,给其新增功能

     1 def outer(func):  # 外层函数的参数: 函数 --> 指的就是要装饰的函数
     2 
     3     def inner():
     4         print("此处代码在被装饰的函数执行之前执行")
     5         func()
     6         print("此处代码在被装饰的函数执行之后执行")
     7     return inner
     8 
     9 @outer
    10 def func():
    11     print("---嘻嘻哈哈---")
    12 
    13 func()
    14 """
    15     此处代码在被装饰的函数执行之前执行
    16     ---嘻嘻哈哈---
    17     此处代码在被装饰的函数执行之后执行
    18 """
     1 import time
     2 
     3 def get_time(func):  # 装饰器--> 装饰的是函数
     4 
     5     def inner():
     6         before = time.time()  # 函数执行之前的时间戳
     7         func()
     8         after = time.time()  # 函数执行结束之后的时间戳
     9         print("函数执行时间", after - before)  # 返回值为时间戳的差值
    10     return inner
    11 
    12 @get_time
    13 def get_num():
    14     for x in range(100):
    15         print(x)
    16 
    17 get_num()
    18 """
    19 0
    20 1
    21 ...
    22 98
    23 99
    24 函数执行时间 0.0010001659393310547
    25 """

    三、装饰一个带有返回值的函数

     1 def outer(func):
     2 
     3     def inner():
     4         print("调用前执行")
     5         res = func() # 此时接收原函数的返回值
     6         print("调用后执行")
     7         return res
     8     return inner
     9 
    10 @outer
    11 def say():
    12     print("我是一个say函数")
    13 
    14 say()
    15 """
    16     调用前执行
    17     我是一个say函数
    18     调用后执行
    19 """
    20 
    21 @outer
    22 def say2():
    23     return "我是一个say2函数"
    24 
    25 res = say2()
    26 # 被装饰的函数say2()--> 调用的是装饰器的inner()函数 -->  res = inner()
    27 print(res)
    28 """
    29     调用前执行
    30     调用后执行
    31     我是一个say2函数
    32 """

    四、装饰带有参数的函数

     1 def outer(func):
     2 
     3     def inner(x):  # 形参: 被装饰的函数的形参
     4         print("调用前执行")
     5         func(x)
     6         print("调用后执行")
     7     return inner
     8 
     9 @outer
    10 def get_num(a):
    11     print(a * 10)
    12 
    13 get_num(2)  # 被装饰后的函数 --> inner(2)
    14 """
    15     调用前执行
    16     20
    17     调用后执行
    18 """
     1 def outer(func):
     2 
     3     def inner(*args, **kwargs):
     4         print("调用前执行")
     5         func(*args, **kwargs)
     6         print("调用后执行")
     7     return inner
     8 
     9 @outer
    10 def get_num(*args, **kwargs):
    11     print(args)
    12     print(kwargs)
    13 
    14 get_num(1,2,3,4, xixi="haha", 年龄=7.5)
    15 
    16 """
    17     调用前执行
    18     (1, 2, 3, 4)
    19     {'xixi': 'haha', '年龄': 7.5}
    20     调用后执行
    21 """

    五、多个装饰器

     1 def outer1(func):
     2     def inner():
     3         print("装饰1调用前")
     4         func()
     5         print("装饰1调用后")
     6     return inner
     7 
     8 def outer2(func):
     9     def inner():
    10         print("装饰2调用前")
    11         func()
    12         print("装饰2调用后")
    13     return inner
    14 
    15 @outer2
    16 @outer1
    17 def study():
    18     print("xixihaha")
    19 
    20 study()
    21 """
    22 装饰2调用前
    23 装饰1调用前
    24 xixihaha
    25 装饰1调用后
    26 装饰2调用后
    27 """

    六、查看被装饰函数的文档注释

      1、需要导入 from functools import wraps

      2、 装饰内层函数 @wraps(被装饰的函数)

     1 from functools import wraps
     2 
     3 def outer(func):
     4     @wraps(func)  # 解决不能查看文档注释的问题
     5     def inner():
     6         func()
     7     return inner
     8 
     9 @outer
    10 def func():
    11     """
    12     func函数
    13     :return: 无
    14     """
    15     print("xixi")
    16 
    17 print(func.__doc__)
    18 """
    19     func函数
    20     :return: 无
    21 """
  • 相关阅读:
    邂逅明下(巴什博弈+hdu2897)
    抽象接口的过程小结
    线程经常使用操作
    对继承的再次理解
    阿里Java开发手冊之编程规约
    [持续更新]Windows Programming常见Hungarian Notation/Abbreviation大全
    [转]__cdecl与__stdcall
    private继承的作用
    [转]C++中的三种继承public,protected,private
    如何只利用NMAKE+CL+LINK写WIN32程序
  • 原文地址:https://www.cnblogs.com/Tree0108/p/12114925.html
Copyright © 2020-2023  润新知