3

このエラー メッセージについてはすでに多くの議論がなされていることは知っていますが、次の説明は見つかりませんでした。

def random2(seed):
    x = seed
    def update():
        x = ( x * 16807 ) % 2147483647
        return x
    return update

r = random2(17283945)
print(r())

関数 [UnboundLocalError] を返すと、変数 x のスコープが失われるように見えるため、これは機能しません。Ok。しかし、今ではまったく問題がないことがわかりました

def random(seed):
    x = [seed]
    def update():
        x.append(( x.pop() * 16807 ) % 2147483647 )
        return x[0]
    return update

r = random(17283945)
print(r()) #580971270
print(r()) #1923475628
print(r()) #1783541505

この場合、 x のスコープが有効なままである理由が少しわかりません。(不) 可変性と関係があるようですが、これはまだ私にはあまり意味がありません。

どうもありがとう。

4

3 に答える 3

3

変数名の後に代入演算子 ( =) を付けると、その変数は自動的にローカルであると見なされます。割り当て前に参照しようとしているように見えるため、エラーが発生します。

x2 番目の例では、変数を何にも割り当てておらず、その場で変更しただけです。

于 2013-03-10T10:49:30.130 に答える
2

Python 3を使用している場合は、使用できますnonlocal x

def random2(seed):
    x = seed
    def update():
        nonlocal x
        x = ( x * 16807 ) % 2147483647
        return x
    return update

r = random2(17283945)
print(r())

Python 2 では、リストに対して行ったことを常に行います。

于 2013-03-10T10:49:51.263 に答える
0

@volatility はその理由を説明していますが、参考までに、ジェネレーターを使用してネストされたスコープを回避する同様の関数を作成する方法を次に示します。

def random(seed):
    x = seed
    while True:
        x = ( x * 16807 ) % 2147483647
        yield x

これにより、 like を反復処理すると一連の疑似乱数が得られますfor rand_num in random(100)。for ループを使用せずに、オンデマンドで新しい乱数を取得することもできますrand_gen = random(100); rand_num = next(rand_gen)

乱数ジェネレーターがジェネレーターの自然な使用法であることがわかります。関数はより短く、より明確であり、自然な方法で使用でき (for...inおよびnext)、 が原因で発生する可能性のあるエラーが発生しにくくなりnonlocalます。ジェネレーターと のより良い説明については、この質問を参照してくださいyield

于 2013-03-10T11:22:59.200 に答える