3

このコードでは、ラムダのxはforステートメントのxを参照しています。したがって、y[0]()2を返します。

x = 0
y = [lambda : x for x in range(3)]
y[0]()

ただし、このコードでは、ラムダのxはグローバルxを参照しているため、x[0]()グローバルx自体を返します。

x = [lambda : x for x in range(3)]
x[0]()

ラムダのxが最初のコードではローカルxを参照しているのに、2番目のコードではグローバルxを参照している理由を知りたいです。

4

3 に答える 3

6

あなたはpython2.xを使用していると思います。リスト内包表記では、一時変数'が名前空間に「リーク」します。理由については、Guidoのこのブログ投稿で読むことができます。

Python 2では、リスト内包はループ制御変数を周囲のスコープに「リーク」します...これはリスト内包の元の実装の成果物でした。それは何年もの間Pythonの「汚い小さな秘密」の1つでした。

これはPython3で修正されました。

なぜあなたが物事をと混同しているのかlambdaわかりません。ここでは、この単純なケースでも同じ動作が見られます。

>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']
于 2012-09-12T05:42:01.120 に答える
5

xx両方のコードでグローバルを指します。確かに、両方のコードにはグローバル以外の何物もありません。xここにはローカル変数はなく、グローバル変数のみがあります。

最初の例では、のグローバル値xは2です。これは、リスト内包によって割り当てられた最後の値であるためです。リスト内包表記は、@ wimで説明されているように、変数を囲んでいるスコープにリークします。ここで囲んでいるスコープはグローバルスコープであるため、変数xはグローバルスコープにリークされ、前に設定した値0が上書きされます。

2番目の例では、リスト内包表記を作成しますが、その値を(グローバル)変数xに割り当てます。これにより、すでにxに含まれていたものがすべて上書きされるため、グローバル変数xの値がリストになります。

どちらの場合も、リスト内の関数の1つ(いずれか1つ!)を呼び出すと、現在の値のが返されますx。あなたはここでこれを見ることができます:

>>> y = [lambda : x for x in range(3)]
>>> y[0]()
2
>>> x = 88
>>> y[0]()
88
>>> x = [lambda : x for x in range(3)]
>>> y = x
>>> y[0]()
[<function <lambda> at 0x017789B0>,
 <function <lambda> at 0x01828DB0>,
 <function <lambda> at 0x01828F30>]
>>> x = 88
>>> y[0]()
88
于 2012-09-12T05:58:28.413 に答える
2
>>> x='a'
>>>x = [lambda : x for x in range(3)]

反復が開始されるとすぐに、xに割り当てられ0、から返されrange()ます(そして、「a」への参照は削除されます)。最後の反復では、の値はx2になり、LCが終了するとすぐに、LCがに割り当てられるためxxLCをポイントします。

例:

>>> [x for x in range(3)]
[0, 1, 2]
>>> x     
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]
于 2012-09-12T05:42:50.733 に答える