一个Python函数可以记住它以前的输出吗?

14 浏览
0 Comments

一个Python函数可以记住它以前的输出吗?

这个问题已经有答案

Python 中函数内静态变量的相对应方法是什么?

有没有一种方法让函数记住其先前输出并在下一次调用函数时使用该值? 例如, 假设有一个函数runningTotal,带有一个单一的参数x,第一次调用runningTotal返回x,但在此后的每个调用中返回x + prevOutput,有没有一种方法在Python中编写这样的函数?

我知道可以通过在函数中使用全局变量或将先前值保存到新变量中来轻松实现此目标,但是如果可能的话,我想避免使用这些解决方案。我寻找替代解决方案的原因是这是我正在与其他人合作的程序中的一个函数,我想避免创建更多已经建立的全局变量。

admin 更改状态以发布 2023年5月23日
0
0 Comments

虽然有办法实现你所要求的功能,但这不是一个好主意。正如@JohnColeman指出的那样,可以使用闭包来模拟Python中的静态变量。

但是为什么不创建一个类呢?

class Accumulator:
    total = 0
    @classmethod
    def add(cls, x):
        cls.total += x
        return cls.total
print(Accumulator.add(1))
print(Accumulator.add(2))
print(Accumulator.add(3))

结果:

1
3
6

你还可以像@HeapOverflow建议的那样设置一个生成器来维护状态并向其发送值。

def get_running_total():
    def _running_total():
        value = 0
        while True:
            value += yield value
    # get a generator instance
    generator = _running_total()
    # set it up to wait for input
    next(generator)
    # return the send method on the generator
    return generator.send
# you can get a generator that functions similar to the Accumulator method
running_total = get_running_total()
print(running_total(1))   # prints 1
print(running_total(2))   # prints 3
print(running_total(3))   # prints 6

0
0 Comments

是的,但为了避免过多的黑客攻击或全局变量,我们可能会想要使用一个类。在Python中,一个类可以被视为带有类内名为__call__的魔法函数(方法)的函数。

你的问题可能更好地表述为:在Python中,有一个具有内部状态的函数的最佳方式是什么?

假设我们使用全局变量来定义runningTotal函数:

TOTAL = 0
def runningTotal(inc):
    global TOTAL
    TOTAL += inc
    return TOTAL

答案 那么让我们定义一个类,它的行为与上述函数相同,但没有全局变量:

class StatefulFunction:
    running_total = 0
    def __call__(self, inc):
        self.running_total += inc
        return self.running_total
# create the stateful function variable
runningTotal = StatefulFunction()
# Use the stateful function
runningTotal(1)
# outputs: 1
runningTotal(5)
# outputs: 6

另一种实现相同功能的方法是使用计数器字典。

from collections import Counter
counter = Counter()
counter['runningTotal'] += 1
# in another part of the program
counter['runningTotal'] += 5

输出将为:

print(counter)
Counter({'runningTotal': 6})

0