0

このコードを考えると(python)

s = [None]*10
def func():
    for i in range(10):
        def update():
            print i,
        s[i] = update

func()
for i in range(10):
    s[i]()

なぜこの結果は 0,1,2,3,...9 ではなく 10 個の 9 なのですか?

ところで、10 個の関数アドレスである s[0]~s[9] も出力しましたが、それぞれに違いがあります。

4

3 に答える 3

3

に対して多数のクロージャーを作成しましたiが、それらはすべて同じ (最終的な) 値を共有しています。i

このような小さな変更を加える必要があります

>>> s = [None]*10
>>> def func():
...     for i in range(10):
...         def update(i=i):
...             print i,
...         s[i] = update
... 
>>> func()
>>> for i in range(10):
...     s[i]()
... 
0 1 2 3 4 5 6 7 8 9
于 2012-08-15T05:38:23.637 に答える
0

何が起こっているのかはこれと同じです:

>>> a = 5
>>> def foo(): print(a)

>>> foo()
5
>>> a = 10
>>> foo()
10
>>> a = 'fred'
>>> foo()
fred

そしてこれも同じです:

>>> def bar(): return b

>>> bar()
Traceback (most recent call last):
  File "<pyshell#30>", line 1, in <module>
    bar()
  File "<pyshell#29>", line 1, in bar
    def bar(): return b
NameError: global name 'b' is not defined
>>> b = 3
>>> bar()
3

関数内で使用した変数は、関数が書き込まれるときではなく呼び出されるまで解決されません。クロージャと呼ばれる魔法があります。つまり、他の関数内で定義された関数(関数は内部で定義されているため)は、外部関数で定義されたすべての変数にアクセスできますが、関数が呼び出されるまで実際には解決されません。したがって、各関数が呼び出されるまでに、は9になります。updatefuncupdatei

@gnibblerの回答のように、デフォルトの引数値を使用するiと、それぞれupdateが検索する引数(外部変数をシャドウする)に解決されるため、機能します。関数が定義されたときにデフォルトの引数値が評価されるため、これらは変更されません(これは、遅かれ早かれ多くの人が遭遇する可変のデフォルトのバグにもつながります)。

于 2012-08-15T05:59:59.377 に答える
0

@gnibblerのコードはあなたのものを修正します(誰かの答えがあれば彼の答えを受け入れてください)。すべての 9 を出力している理由については、update関数を見てください。あなたは(@gnibblerが述べたように)で定義したiを継続的に返していますfor i in range(10)update元のコードでは、関数の引数を指定してメソッドを呼び出さなかったので、スコープiで定義された を出力するだけです (関数の完了後に 9 になる完全に異なる)。funci

おそらくより明確にするために、iinfuncをまったく別の名前に変更してみてください。結果は同じになります。

于 2012-08-15T05:50:30.407 に答える