可能重复:
函数内的静态变量在Python中的等效项是什么?
我尝试编写一个递归函数。迭代向量,并给出一个值,该值取决于当前值和先前值。在Matlab中,我可以persistent在函数内部声明一个变量,并且在调用该函数后将其值存储在内存中,因此该函数的下一次调用将从先前的值开始。
这是我从简单移动平均线开始的内容:
def AvgFilter(x):
if not firstRun: # checks if runs for first time, i.e. firstRun is empty
k = 1 # setup initial variables if run for first time
prevAvg = 0 # prevAvg - the average calculated during last call
firstRun = 1 # only for initialisation
alpha = (k-1)/k
avg = alpha * prevAvg + (1 - alpha)*x
prevAvg = avg
k = k + 1
return avg
Run Code Online (Sandbox Code Playgroud)
我需要k prevAvg firstRun在函数调用之间记住变量。我读到它可以通过装饰器完成,我确实尝试@counter过在功能之前实现它的设置,但不确定如何实现。装饰器是唯一的方法(没有找到其他东西)吗?以及如何编写计数器函数来存储我的变量?我有点担心,以后再进行更复杂的递归操作时,我会完全被装饰器的想法迷失。
听起来像是发电机的工作!生成器让您假装自己只是在循环中一次计算一个值,但实际上会暂停执行并在调用时返回一个值yield。
def AvgFilter():
k = 1
avg = 0
while True:
alpha = (k-1)/float(k)
x = yield avg # yield/return the old average, and get the new input value
avg = alpha * avg + (1 - alpha)*x
k = k + 1
f = AvgFilter()
print f.next()
print f.send(1)
print f.send(2)
print f.send(20)
print f.send(20)
# 0
# 1.0
# 1.5
# 7.66666666667
# 10.75
Run Code Online (Sandbox Code Playgroud)
感谢 @Thomas Orozco 和 @jtbandes 的回答 经过漫长的几天后,我终于按照我想要的方式工作了。代码和一些测试是:
x = [10,2,30,4,50]
class avgFil2(object):
def __init__(self):
self.avg = 0
self.k = 1.0
def __call__(self, x):
alpha = (self.k-1.0)/self.k
self.avg = alpha * self.avg + (1 - alpha)*x
self.k +=1
return self.avg
def simpleTest(x = x):
average = []
avg = avgFil2() # new variable and creation of instance (all initialisation)
for i in range(len(x)):
print 'input %f' % x[i]
print 'before change avg.avg=%f, k=%f' % (avg.avg, avg.k)
average.append(avg(x[i])) # class is called here, so all changes going on
print 'after change avg.avg=%f, k=%f' % (avg.avg, avg.k)
print 'The output average is %f' % average[i]
simpleTest()
Run Code Online (Sandbox Code Playgroud)
该代码与 Matlab 确实不同,但很好。重要的陷阱是初始化k=1.0为float不k=1初始化int,因为alpha除法计算结果为整数时会为零。另一件事,我必须初始化为“self.k”而不是“k”,否则会给出错误。生成器可能也可以工作,但我喜欢class解决方案。