[英]Multiple calls of a function inside other functions
I have the following functions:我有以下功能:
def f(x):
return x
def f2(x):
y = f(x)
return y + x + 1
def f3(x):
y = f(x)
return y + x + 2
def DoAll(x):
i2 = f2(x)
i3 = f3(x)
return i2, i3
print(DolAll(2))
Even when this code runs, it seems very inefficient since I call f(x)
multiple times.即使这段代码运行时,它看起来也很低效,因为我多次调用f(x)
。 How can I solve this problem without defining an f2(x, y)
and f3(x, y)
?如何在不定义f2(x, y)
和f3(x, y)
的情况下解决这个问题? I would like to use something similar to我想使用类似于
def f(x):
return x
def f2(x):
nonlocal y
return y + x + 1
def f3(x):
nonlocal y
return y + x + 2
def DoAll(x):
y = f(x)
f2 = f2(x)
f3 = f3(x)
return f2, f3
print(DolAll(2))
Of course, the code shown here does not work.当然,此处显示的代码不起作用。
You can use caching to avoid redoing the computation.您可以使用缓存来避免重做计算。 Python provides such functionality out-of-the-box with functools.lru_cache
: Python 通过functools.lru_cache
提供了这种开箱即用的功能:
from functools import lru_cache
@lru_cache()
def f(x):
...
This is more general than just making the value globally available, since it will allow multiple computations to stash values simultaneously.这比仅仅使值全局可用更通用,因为它将允许多个计算同时存储值。
If your functions are deterministic and without side-effects, you can short-circuit out the computation of nested calls entirely by caching all the intermediate results too:如果您的函数是确定性的并且没有副作用,您也可以通过缓存所有中间结果来完全短路嵌套调用的计算:
@lru_cache()
def f(x):
print(f'Called f({x})')
return x
@lru_cache()
def f2(x):
print(f'Called f2({x})')
y = f(x)
return y + x + 1
@lru_cache()
def f3(x):
print(f'Called f3({x})')
y = f(x)
return y + x + 2
@lru_cache()
def DoAll(x):
print(f'Called DoAll({x})')
i2 = f2(x)
i3 = f3(x)
return i2, i3
>>> DoAll(1)
Called DoAll(1)
Called f2(1)
Called f(1)
Called f3(1)
(3, 4)
>>> DoAll(2)
Called DoAll(2)
Called f2(2)
Called f(2)
Called f3(2)
(5, 6)
>>> DoAll(1)
(3, 4)
Notice that the expensive computation only gets performed once for each new input.请注意,对于每个新输入,昂贵的计算只会执行一次。
You missed one nonlocal
declaration: in DoAll
itself.您错过了一个nonlocal
声明:在DoAll
本身中。 (You could use global
as well, since the only non-local scope in this example is the global scope.) This would cause the y
variable to be defined in a scope visible to f2
and f3
. (您也可以使用global
,因为此示例中唯一的非本地 scope 是全局 scope。)这将导致y
变量在f2
和f3
可见的 scope 中定义。
def DoAll(x):
nonlocal y
y = f(x)
f2 = f2(x)
f3 = f3(x)
return f2, f3
However, this should start to resemble a crude attempt at defining a class that encapsulates y
for all its methods to share.然而,这应该开始类似于定义 class 的粗略尝试,它封装y
以供其所有方法共享。
class Foo:
def f(self, x):
return x
def f2(self, x):
return self.y + x + 1
def f3(self, x):
return self.y + x + 2
def DoAll(self, x):
self.y = self.f(x)
f2 = self.f2(x)
f3 = self.f3(x)
return f2, f3
foo = Foo()
print(foo.DoAll(2))
(This in itself is a fairly awkward class design, as the y
attribute gets defined on an ad-hoc basis, but it should hint at the use of the object itself providing the "scope" from which other methods can access a shared, non-local value y
.) (这本身就是一个相当尴尬的 class 设计,因为y
属性是在临时基础上定义的,但它应该暗示 object 本身的使用提供了其他方法可以访问共享的非共享的“范围” -本地值y
。)
In the end, Foo
itself is basically providing a context in which the return value of Foo.f
is cached for use by Foo.f2
and Foo.f3
.最后, Foo
本身基本上提供了一个上下文,其中Foo.f
的返回值被缓存以供Foo.f2
和Foo.f3
使用。 There are much cleaner ways to implement such a cache, so I'll direct you to Mad Physicist's answer .有更简洁的方法来实现这样的缓存,所以我将引导您查看Mad Physicist 的答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.