Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
了解python备忘录装饰器中的参数处理_Python_Decorator_Memoization - Fatal编程技术网

了解python备忘录装饰器中的参数处理

了解python备忘录装饰器中的参数处理,python,decorator,memoization,Python,Decorator,Memoization,我一直在使用这个优秀的decorator进行记忆,我在网上找到了它(这里以斐波那契序列为例): 现在我想更好地理解一下内部工作原理,通过阅读Python中的装饰器或参数处理,我还没有找到答案 为什么每次调用修饰函数时都不重新初始化缓存字典 如何将*x识别为发送到修饰函数的参数,即函数调用fib(969)中的969?在首次定义修饰函数之后,仅调用修饰函数一次。因此,这两种技术(使用@wrap和bar=wrap(bar))是相同的: >>> def wrap(f): ...

我一直在使用这个优秀的decorator进行记忆,我在网上找到了它(这里以斐波那契序列为例):

现在我想更好地理解一下内部工作原理,通过阅读Python中的装饰器或参数处理,我还没有找到答案

为什么每次调用修饰函数时都不重新初始化缓存字典


如何将*x识别为发送到修饰函数的参数,即函数调用fib(969)中的969?

在首次定义修饰函数之后,仅调用修饰函数一次。因此,这两种技术(使用@wrap和bar=wrap(bar))是相同的:

>>> def wrap(f):
...     print 'making arr'
...     arr = []
...     def inner():
...         arr.append(2)
...         print arr
...         f()
...     return inner
...     
>>> @wrap
... def foo():
...     print 'foo was called'
...     
making arr
>>> foo()
[2]
foo was called
>>> foo()
[2, 2]
foo was called
>>> def bar():
...     print 'bar was called'
...     
>>> bar = wrap(bar)
making arr
>>> bar()
[2]
bar was called
在这两种情况下,很明显,只有在调用wrap(f)时才会创建arr,并且只有在首次声明foo和bar时才会调用wrap

至于向修饰函数传递参数的情况,请记住修饰器将函数作为参数,并返回该函数的修改版本。因此,装饰器通常接受一个参数,即它正在修改的函数。它返回一个新函数,并且decorator可以将它返回的函数定义为使用任意数量的参数(例如,*args)。decorator甚至可以返回一个函数,该函数为它所修饰的方法接受了太多的参数

>>> def wrap_with_arg(f):
...     def wrap(*args):
...         print 'called with %d arguments' % len(args)
...         f(args)
...     return wrap
...     
>>> @wrap_with_arg
... def baz(arg):
...     print 'called with argument %r' % arg
...     
>>> baz(3)
called with 1 arguments
called with argument 3
>>> baz(3, 4)
called with 2 arguments
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 4, in wrap
  File "<input>", line 3, in baz
TypeError: not all arguments converted during string formatting
>>def wrap_与_arg(f):
...     def wrap(*args):
...         使用%d个参数“%len(args)调用了print”
...         f(args)
...     回程包装
...     
>>>@wrap_与_arg
... def baz(arg):
...     使用参数%r“%arg”调用了“打印”
...     
>>>巴兹(3)
用1个参数调用
调用参数3
>>>baz(3,4)
用2个参数调用
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第4行,换行
文件“”,第3行,在baz中
TypeError:在字符串格式化过程中并非所有参数都已转换

当baz最终抛出错误时,请注意在抛出错误之前参数的数量是如何正确打印的。

+1同样,值得一提的是正在创建一个闭包,这就是为什么在函数
defm
已经返回时可以访问
缓存的原因。谢谢,现在我更了解装饰师了!:)
>>> def wrap_with_arg(f):
...     def wrap(*args):
...         print 'called with %d arguments' % len(args)
...         f(args)
...     return wrap
...     
>>> @wrap_with_arg
... def baz(arg):
...     print 'called with argument %r' % arg
...     
>>> baz(3)
called with 1 arguments
called with argument 3
>>> baz(3, 4)
called with 2 arguments
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 4, in wrap
  File "<input>", line 3, in baz
TypeError: not all arguments converted during string formatting