理解这个Python装饰器代码

时间:2016-12-19 20:57:37

标签: python decorator python-decorators

我在理解这个代码时遇到了问题,这是我从“学习Python”部分装饰器中获得的。

为什么此代码一次返回结果的变量值而不是两次?我们返回结果变量两次,一次在“max_result”中,另一次在“measure”中;这是代码:

from time import sleep, time
from functools import wraps

def measure(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        t = time()
        result = func(*args, **kwargs)
        print(func.__name__, 'took:', time() - t)
        return result
    return wrapper

def max_result(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        if result > 100:
            print('Result is too big ({0}). Max allowed is 100.'
                  .format(result))
        return result
    return wrapper

@measure
@max_result
def cube(n):
    return n ** 3

print(cube(2))
print(cube(5))

这是输出,我们为什么不得到两个8或两个125?

>>> print(cube(2))
cube took: 8.106231689453125e-06
8
>>> print(cube(5))
Result is too big (125). Max allowed is 100.
cube took: 5.91278076171875e-05
125
>>> 

1 个答案:

答案 0 :(得分:4)

装饰器链接。原始CGPoint函数由cube()装饰器包装,该装饰的结果max_result修饰。

所以measure的{​​{1}}的返回值由cube()中的wrapper()获取,该函数的结果由max_result()中的wrapper()获取回到了打电话。

解开所有装饰者会给你:

measure()

所以调用def measure_wrapper(*args, **kwargs): t = time() result = max_result_wrapper(*args, **kwargs) print(func.__name__, 'took:', time() - t) return result def max_result_wrapper(*args, **kwargs): result = original_cube(*args, **kwargs) if result > 100: print('Result is too big ({0}). Max allowed is 100.' .format(result)) return result def original_cube(n): return n ** 3 cube = measure_wrapper 会产生:

  • cube(2),记录measure_wrapper(2)和来电
    • t = time(),直接调用
      • max_result_wrapper(2)
      • 返回original_cube(2)2 ** 3
    • 测试8,这是错误的
    • 返回8 > 100
  • 打印8来电和
  • 的时间
  • 返回max_result_wrapper()