gpt4 book ai didi

python - 内存装饰器无法内存(当不使用装饰器语法时)

转载 作者:太空宇宙 更新时间:2023-11-04 07:45:06 24 4
gpt4 key购买 nike

我有一个简单的内存器装饰器:

def funcmemo(f):
memo = {}
@wraps(f)
def wrapper(*args):
if args in memo:
return memo[args]
else:
temp = f(*args)
print "memoizing: ", args, temp
memo[args] = temp
return temp
return wrapper

现在,当我通过“@”标记使用它时,

@funcmemo
def fib(n):
print "fib called with:", n
if n < 2: return n
return fib(n-2) + fib(n-1)

res = fib(3)
print "result:", res

如打印输出所示,它工作正常:

fib called with: 3
fib called with: 1
memoizing: (1,) 1
fib called with: 2
fib called with: 0
memoizing: (0,) 0
memoizing: (2,) 1
memoizing: (3,) 2
result: 2

但是,当我这样做时:

def fib(n):
print "fib called with:", n
if n < 2: return n
return fib(n-2) + fib(n-1)

memfib = funcmemo(fib)
res = memfib(3)
print "result:", res

显然调用了一个未修饰的 fib,只有最终返回值“到达”缓存(显然导致了巨大的减速):

fib called with: 3
fib called with: 1
fib called with: 2
fib called with: 0
fib called with: 1
memoizing: (3,) 2
result: 2

奇怪的是,这个工作正常:

def fib(n):
print "fib called with:", n
if n < 2: return n
return fib(n-2) + fib(n-1)

fib = funcmemo(fib)
res = fib(3)
print "result:", res

此外,基于类的版本也会发生同样的事情:

class Classmemo(object):
def __init__ (self, f):
self.f = f
self.mem = {}
def __call__ (self, *args):
if args in self.mem:
return self.mem[args]
else:
tmp = self.f(*args)
print "memoizing: ", args, temp
self.mem[args] = tmp
return tmp

使用“匿名”装饰函数时也会出现此问题,例如

res = Classmemo(fib)(3)

我很乐意了解这背后的原因。

最佳答案

这没什么奇怪的。当你做的时候

memofib = funcmemo(fib)

您不会以任何方式更改 fib 指向的函数,而是创建一个新函数 并将名称 memofib 指向它.

因此,当 memofib 被调用时,它会调用名称为 fib 的函数——递归调用自身,而不是 memofib - - 所以不会发生内存。

在你的第二个例子中,你做

fib = funcmemo(fib)

因此它递归地调用自己,并且在所有级别发生内存。

如果您不想像装饰器版本或您的第二个示例那样覆盖名称 fib,您可以更改 fib 以采用函数名称:

def fib(n, fibfunc):
print "fib called with:", n
if n < 2: return n
return fibfunc(n-2, fibfunc) + fibfunc(n-1, fibfunc)

memofib = funcmemo(fib)
res = fib(3, memofib)

你也可以使用 fixed point combinator避免每次都传递 fibfunc:

def Y(f):
def Yf(*args):
return f(Yf)(*args)
return f(Yf)

@Y
def fib(f):
def inner_fib(n):
print "fib called with:", n
if n < 2: return n
return f(n-2) + f(n-1)
return inner_fib

关于python - 内存装饰器无法内存(当不使用装饰器语法时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9819651/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com