Python中与Matlab的persistent相等

14 浏览
0 Comments

Python中与Matlab的persistent相等

这个问题已经有答案了

可能是重复的问题:

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

我需要记住函数调用之间的变量k prevAvg firstRun。我读到可以通过装饰器来完成,我尝试在函数之前设置@counter实现它,但不确定应该如何实现它。装饰器是唯一的方法吗(没有找到其他方法)?以及如何编写计数器函数来存储我的变量?我对更复杂的递归稍有担心,因为我可能会完全失去装饰器的想法。

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

感谢@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()

代码与Matlab真的很不同,但很好。重要的陷阱是将k=1.0初始化为float而不是k=1初始化为int,因为alpha将为零,因为除法会计算出整数。另一件事,我必须将初始值设为'self.k'而不是'k',否则会出现错误。生成器可能也行,但我喜欢class的解决方案。

0
0 Comments

听起来像是 生成器 的工作!生成器让你可以假装你只是在循环中逐个计算值,但实际上它会暂停执行并在调用 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

0