繁体   English   中英

在其他函数中多次调用 function

[英]Multiple calls of a function inside other 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))

即使这段代码运行时,它看起来也很低效,因为我多次调用f(x) 如何在不定义f2(x, y)f3(x, y)的情况下解决这个问题? 我想使用类似于

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))

当然,此处显示的代码不起作用。

您可以使用缓存来避免重做计算。 Python 通过functools.lru_cache提供了这种开箱即用的功能:

from functools import lru_cache

@lru_cache()
def f(x):
    ...

这比仅仅使值全局可用更通用,因为它将允许多个计算同时存储值。

如果您的函数是确定性的并且没有副作用,您也可以通过缓存所有中间结果来完全短路嵌套调用的计算:

@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)

请注意,对于每个新输入,昂贵的计算只会执行一次。

您错过了一个nonlocal声明:在DoAll本身中。 (您也可以使用global ,因为此示例中唯一的非本地 scope 是全局 scope。)这将导致y变量在f2f3可见的 scope 中定义。

def DoAll(x):
    nonlocal y
    y = f(x)
    f2 = f2(x)
    f3 = f3(x)
    return f2, f3

然而,这应该开始类似于定义 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))

(这本身就是一个相当尴尬的 class 设计,因为y属性是在临时基础上定义的,但它应该暗示 object 本身的使用提供了其他方法可以访问共享的非共享的“范围” -本地值y 。)

最后, Foo本身基本上提供了一个上下文,其中Foo.f的返回值被缓存以供Foo.f2Foo.f3使用。 有更简洁的方法来实现这样的缓存,所以我将引导您查看Mad Physicist 的答案

暂无
暂无

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

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