将 functools.lru_cache 应用于 lambda
Posted
技术标签:
【中文标题】将 functools.lru_cache 应用于 lambda【英文标题】:Applying `functools.lru_cache` to lambda 【发布时间】:2015-11-08 02:51:02 【问题描述】:所以我在 Python 中为斐波那契数列制作了一个递归 lambda。我使用递归是因为它最容易用 lambda 实现。
fib = lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1
因为使用递归,多次计算相同的斐波那契值,我认为使用缓存装饰器会有所帮助,而且我知道functools.lru_cache
是一个简单的选择。
我知道你不能像普通函数一样将装饰器应用到使用 @functools.lru_cache
的函数到 lambda,但是当我尝试这个时:
fib = functools.lru_cache((lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1), maxsize = None)
我收到一条错误消息,提示 functools.lru_cache
不接受函数对象作为参数。
>>> fib = functools.lru_cache((lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1), maxsize = None)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
fib = functools.lru_cache((lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1), maxsize = None)
TypeError: lru_cache() got multiple values for argument 'maxsize'
我查看了文档,看起来functools.lru_cache
只接受maxsize
和typed
参数,默认分别为128
和False
。
有没有更聪明的方法将装饰器分配给函数,而不是只定义没有 lambda 的函数然后应用装饰器?
【问题讨论】:
【参考方案1】:试试fib = functools.lru_cache()(lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1)
我相信调用lru_cache
会返回一个函数,它接受一个函数并返回一个函数。要提供最大尺寸,请使用 fib = functools.lru_cache(100)(lambda n: fib(n - 1) + fib(n - 2) if n > 1 else 1)
【讨论】:
这是因为lru_cache()
返回一个装饰器,但它本身不是一个;这是一家装饰工厂。
谢谢!起初我不明白为什么它会起作用,但是在我对 shell 和源代码进行了一些摆弄之后,我理解了:函数 lru_cache
返回另一个装饰函数!真聪明!
@Cyphase 为什么他们会做出这样的设计决定??
因为当用作装饰器时看起来很自然(这是这个函数的想法)。以及如何将其他参数传递给函数?
@PythonGuy,hiroprotagonist 说的 :)。【参考方案2】:
一个我能想到的最愚蠢功能的小例子:
from functools import lru_cache
@lru_cache(maxsize=32)
def identity(x):
return x
identity2 = lru_cache(maxsize=32)(lambda x: x)
第一个版本是装饰器版本,您可以在其中看到lru_cache
的第一个agument。从那里很容易看出如何正确获取 lambda 表达式的语法。
【讨论】:
以上是关于将 functools.lru_cache 应用于 lambda的主要内容,如果未能解决你的问题,请参考以下文章
如何用 `functools.lru_cache` 正确装饰`classmethod`?