在此代碼中,lambda中的x引用for語句中的x。所以y[0]()
回報2:爲什麼這兩個'x'指的是不同的變量?
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中lambda表示第一段代碼中的本地x,而第二段代碼中則表示全局x。
在此代碼中,lambda中的x引用for語句中的x。所以y[0]()
回報2:爲什麼這兩個'x'指的是不同的變量?
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中lambda表示第一段代碼中的本地x,而第二段代碼中則表示全局x。
x
是指在兩個碼片全球x
。的確,什麼都沒有,但在這兩個代碼段中都是全局的x
。這裏沒有局部變量,只有全局變量。
在第一個示例中,x
的全局值爲2,因爲這是列表理解分配給它的最後一個值。列表解析將它們的變量泄露到@wim所描述的封閉範圍中。由於這裏的封閉範圍是全局範圍,所以變量x
泄漏到全局範圍中,覆蓋您之前設置的值0。
在第二個示例中,您將創建列表理解,然後將其值分配給(全局)變量x。這會覆蓋x中已有的內容,因此全局變量x的值現在成爲列表。
在這兩種情況下,當您調用列表中的某個函數(任何一個!)時,它將返回當前的值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
我想你是在Python 2.x中,在列表理解中,臨時變量'泄漏'到命名空間中。你可以閱讀關於爲什麼在this blog post from Guido。
在Python 2,列表解析「泄漏」循環控制變量 到周圍的範圍。這是原始 執行列表解析的假象;這是多年來Python的「骯髒的 小祕密」之一。
這已被固定在Python 3
我不知道爲什麼你是混亂的東西與lambda
,在這裏你會看到在這個簡單的情況相同的行爲:
>>> x = 'a'
>>> y = [x for x in 'b','c']
>>> x
'c'
>>> x = [x for x in 'b','c']
>>> x
['b', 'c']
個人而言,我更喜歡「泄露'的實現,因爲它在功能上與for循環相同,一旦完成,它也將其控制變量保留在範圍中。 –
意見不同我猜想..我不喜歡它,可以想到沒有有效的'泄漏'用例,我確實被它蜇了一次。我認爲這種行爲被刪除是正確的,因爲我認爲列表理解是一個邏輯單元,控制只是一個自由變量而不是定義,與謂詞演算類似。 – wim
是的,我當然明白並理解爲什麼。 –
>>> x='a'
>>>x = [lambda : x for x in range(3)]
只要迭代開始,x
被分配到0
,從range()
返回(並且引用'a'被移除)。在最後一次迭代中,x
的值變爲2,並且一旦LC退出,LC就被分配到x
,所以現在x
指向LC。
例如:
>>> [x for x in range(3)]
[0, 1, 2]
>>> x
2
>>> x=[x for x in range(3)]
>>> x
[0, 1, 2]
因爲範圍......看到:HTTP://www.saltycrane.com/blog/2008/01/python-variable-scope-notes –