简体   繁体   English

Python:带有包装器的装饰器行为

[英]Python: behaviour of decorator with wrapper

I don´t understand why the line "cache = {}" is executed only the first time i call the function multiply(x, y). 我不明白为什么仅在我第一次调用函数multiple(x,y)时才执行“ cache = {}”行。 After that, that line is ignored. 之后,该行将被忽略。 This makes the program work well, but i don´t understand that behaviour. 这使程序运行良好,但是我不了解这种行为。

def memoize(func):

     cache = {}
     print("cache")

     @functools.wraps(func)
     def wrapper(*args):
         if args in cache:
             return cache[args]

         result = func(*args)
         cache[args] = result

         return result

     return wrapper

 @memoize
 def multiply(x, y):
     return x * y

 print(multiply(2, 3))
 print(multiply(2, 3))

The result is: 结果是:

 cache
 6
 6

So the lines "cache = {}" and "print("cache")" were only executed the frist time. 因此,“ cache = {}”和“ print(“ cache”)“行仅在第一时间执行。 Thanks 谢谢

The part of the decorator code which is "executed everytime" is the wrapper function. 装饰器代码的“每次执行”部分是包装函数。 The code outside that wrapper function is executed just when the operator is applied - 包装函数外的代码仅在应用运算符时执行-

This nothing magic or "new" - just see the order things are and what is called when - the only thing out of normal execution order which cold be called just a bit magic is the decoration itself- just remember that: 这什么都不是魔术或“新的”-只看事物的顺序和什么时候被称为-正常执行顺序中唯一不能被称为魔术的东西就是装饰本身-请记住:

 @memoize
 def multiply(x, y):
     return x * y

is just the same thing as: 与以下内容相同:

def multiply(x, y):
     return x * y

multiply = memoize(multiply)

Also, if you are trying to understand decorators, leave the functools.wraps call out of it for now. 另外,如果您想了解装饰器,请functools.wraps不要使用functools.wraps调用。 It is good for production code, and for filling in small details: it disguises your wrapper function as the inner function it decorates (for example, the function wrapper __name__ attribute is set to multiply in this example), but is an unnecessary complication when trying to understand decorators. 这对生产代码和填入小细节都很有好处:它将包装器函数伪装成装饰的内部函数(例如,在此示例中, multiply wrapper __name__属性设置为multiply ),但是在尝试时是不必要的复杂化了解装饰者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM