当前位置:   article > 正文

流畅的python系列:装饰器_时空无限 csdn

时空无限 csdn

1-1

from dis import dis
import time

def clock(func):
    def clocked(*args):
        t0 = time.perf_counter()
        result = func(*args)
        elasped = time.perf_counter() - t0
        name = func.__name__
        arg_str = ','.join(repr(arg) for arg in args)
        print('[%0.8fs] %s(%s) -> %r' %(elasped,name,arg_str,result))
        return result
    return clocked

@clock
def snooze(seconds):
    time.sleep(seconds)

@clock
def factorial(n):
    if n < 2:
        return 1
    else:
        return n *factorial(n-1)

if __name__=='__main__':
    dis(clock)
    print('*' * 40,'calling snooze(.123)')
    snooze(.123)
    print('*' * 40,'calling factorial(6)')
    print('6!=',factorial(6))
  • 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
  • 30
  • 31

输出

D:\python3.9.7\python.exe D:/my-python-test/liuchangdepython/decorate.py
  5           0 LOAD_CLOSURE             0 (func)
              2 BUILD_TUPLE              1
              4 LOAD_CONST               1 (<code object clocked at 0x0000025028D6B240, file "D:\my-python-test\liuchangdepython\decorate.py", line 5>)
              6 LOAD_CONST               2 ('clock.<locals>.clocked')
              8 MAKE_FUNCTION            8 (closure)
             10 STORE_FAST               1 (clocked)

 13          12 LOAD_FAST                1 (clocked)
             14 RETURN_VALUE

Disassembly of <code object clocked at 0x0000025028D6B240, file "D:\my-python-test\liuchangdepython\decorate.py", line 5>:
  6           0 LOAD_GLOBAL              0 (time)
              2 LOAD_METHOD              1 (perf_counter)
              4 CALL_METHOD              0
              6 STORE_FAST               1 (t0)

  7           8 LOAD_DEREF               0 (func)
             10 LOAD_FAST                0 (args)
             12 CALL_FUNCTION_EX         0
             14 STORE_FAST               2 (result)

  8          16 LOAD_GLOBAL              0 (time)
             18 LOAD_METHOD              1 (perf_counter)
             20 CALL_METHOD              0
             22 LOAD_FAST                1 (t0)
             24 BINARY_SUBTRACT
             26 STORE_FAST               3 (elasped)

  9          28 LOAD_DEREF               0 (func)
             30 LOAD_ATTR                2 (__name__)
             32 STORE_FAST               4 (name)

 10          34 LOAD_CONST               1 (',')
             36 LOAD_METHOD              3 (join)
             38 LOAD_CONST               2 (<code object <genexpr> at 0x0000025028D6B190, file "D:\my-python-test\liuchangdepython\decorate.py", line 10>)
             40 LOAD_CONST               3 ('clock.<locals>.clocked.<locals>.<genexpr>')
             42 MAKE_FUNCTION            0
             44 LOAD_FAST                0 (args)
             46 GET_ITER
             48 CALL_FUNCTION            1
             50 CALL_METHOD              1
             52 STORE_FAST               5 (arg_str)

 11          54 LOAD_GLOBAL              4 (print)
             56 LOAD_CONST               4 ('[%0.8fs] %s(%s) -> %r')
             58 LOAD_FAST                3 (elasped)
             60 LOAD_FAST                4 (name)
             62 LOAD_FAST                5 (arg_str)
             64 LOAD_FAST                2 (result)
             66 BUILD_TUPLE              4
             68 BINARY_MODULO
             70 CALL_FUNCTION            1
             72 POP_TOP

 12          74 LOAD_FAST                2 (result)
             76 RETURN_VALUE

Disassembly of <code object <genexpr> at 0x0000025028D6B190, file "D:\my-python-test\liuchangdepython\decorate.py", line 10>:
 10           0 LOAD_FAST                0 (.0)
        >>    2 FOR_ITER                14 (to 18)
              4 STORE_FAST               1 (arg)
              6 LOAD_GLOBAL              0 (repr)
              8 LOAD_FAST                1 (arg)
             10 CALL_FUNCTION            1
             12 YIELD_VALUE
             14 POP_TOP
             16 JUMP_ABSOLUTE            2
        >>   18 LOAD_CONST               0 (None)
             20 RETURN_VALUE
**************************************** calling snooze(.123)
[0.12288130s] snooze(0.123) -> None
**************************************** calling factorial(6)
[0.00000080s] factorial(1) -> 1
[0.00001210s] factorial(2) -> 2
[0.00001910s] factorial(3) -> 6
[0.00002510s] factorial(4) -> 24
[0.00003130s] factorial(5) -> 120
[0.00003950s] factorial(6) -> 720
6!= 720

Process finished with exit code 0
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

代码解释

❶ 定义内部函数 clocked, 它接受任意个定位参数。
❷ 这行代码可用, 是因为 clocked 的闭包中包含自由变量 func。
❸ 返回内部函数, 取代被装饰的函数。 示例 7-16 演示了 clock 装饰器
的用法。

@clock
def factorial(n):
  • 1
  • 2

等价于

factorial = clock(factorial)
  • 1

在示例中, factorial 会作为 func 参数传给 clock。 然后, clock 函数会返回 clocked 函数, Python 解释器在背后会把 clocked 赋值给 factorial。 其实,查看 factorial 的 name 属性, 会得到
如下结果:

   print(factorial.__name__)
   clocked
  • 1
  • 2

所以, 现在 factorial 保存的是 clocked 函数的引用。 自此之后, 每
次调用 factorial(n), 执行的都是 clocked(n)。 clocked 大致做了
下面几件事。
(1) 记录初始时间 t0。
(2) 调用原来的 factorial 函数, 保存结果。
(3) 计算经过的时间。
(4) 格式化收集的数据, 然后打印出来。
(5) 返回第 2 步保存的结果。
这是装饰器的典型行为: 把被装饰的函数替换成新函数, 二者接受相同
的参数, 而且(通常) 返回被装饰的函数本该返回的值, 同时还会做些
额外操作。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/211362
推荐阅读
相关标签
  

闽ICP备14008679号