5

重複の可能性:
関数内の静的変数に相当する 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方法がわかりません。デコレータは唯一の方法ですか (他に何も見つかりませんでした)? 私の変数を格納するためにカウンター関数を書く方法は?後でより複雑な再帰を使用すると、デコレータのアイデアで完全に失われるのではないかと少し心配しています。

4

3 に答える 3

5

発電機の仕事のように聞こえます!ジェネレーターを使用すると、ループ内で一度に1つずつ値を計算しているように見せかけることができますが、実際には実行を一時停止し、を呼び出すと値を返します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
于 2012-10-06T22:13:41.830 に答える
2

次のことができます。

  • オブジェクトを使用してそれらの変数をオブジェクトに格納し、関数呼び出し間で同じオブジェクトを再利用します。
  • グローバル変数の使用(強くお勧めしません!)
  • ジェネレーターの使用(jtbandesの回答を参照)

次に例を示します。

class AvgFilter(object):
    def __init__(self):
        self.k = 1
        self.avg = 0

    def run(x):
        alpha = float(self.k-1) / self.k  
        self.avg = alpha * self.avg + (1 - alpha)*x
        self.k +=1
        return self.avg
于 2012-10-06T22:15:31.257 に答える
2

@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 とは異なりますが、優れています。重要なトラップは、除算が整数に評価されるとゼロになるため、 notに初期化k=1.0することです。別のこととして、それ以外の場合はエラーが発生していたため、「k」ではなく「self.k」に初期化する必要がありました。ジェネレーターもおそらく機能しますが、私はソリューションが好きです。floatk=1intalphaclass

于 2012-10-09T15:50:57.177 に答える