2017-08-17 62 views
-1

請幫助我理解爲什麼這會起作用。下面的代碼列出了迭代中的重複項。然而,使用運營商的行爲就像在if..else語句的else ..在列表理解語句中是OR和ELSE類似

j = set() 
my_list = [1, 2, 3 ,3 , 3 ,4, 4] 
j_add = j.add 
twice = set(x for x in my_list if x in j or j_add(x)) 
print list(twice) 

期望線路爲:

twice = set(x for x in my_list if x in j else j_add(x)) 

思想或返回一個布爾值不值

+1

從技術上講,你沒有列表理解,你有一個生成器表達式。 –

+1

不,''或'不是'else'語句。這是測試的一部分。您可以在任何'if'或'while'語句中使用相同的布爾表達式。 '或'**短路**,如果左邊的表達式產生一個真值,它將不執行右邊的表達式。 –

+0

謝謝..目的不是爲了刪除重複內容,而是爲了捕獲它們。上面的代碼在執行時會返回[3,4]。 –

回答

1

or運算符返回最後一次計算的參數,該參數可能是布爾值,也可能不是布爾值。

這種行爲在Documentation解釋說:

注意,無論是and也不or限制值並鍵入他們回到FalseTrue,而是返回最後一個變量。這有時是有用的,例如,如果s是一個字符串,如果該字符串爲空,則應該用默認值替換,則表達式s or 'foo'會生成所需的值。

當然,它有助於記住被解釋爲假,什麼是解釋爲真:

[T]他後面的值是假的:FalseNone,所有的數字爲零類型,空字符串和容器(包括字符串,元組,列表,字典,集合和frozensets)。所有其他值都被解釋爲true。

所以在表達式:

A = B or C 

作爲@MartijnPieters在評論指出,一個or表達短路。如果第一個參數(在這種情況下爲B)被解釋爲true,則整個表達式必須爲真,因此第二個參數(C)永遠不會被評估。因此第一個參數(B)是「最後評估的參數」並返回。但是,如果第一個參數(B)被解釋爲false,則仍必須評估第二個參數(C)以確定表達式的真實性(不發生短路)。在這種情況下,「最後評估的參數」是第二個參數(C),無論表達式評估爲true還是false,都會返回該參數。

有效完成一樣的Conditional Expression

A = B if B else C 

然而,條件表達式只加入到了Python 2.5版本,而布爾操作人員的行爲從一開始就至少存在(或很長一段時間)。大多數經驗豐富的Python程序員很容易識別並習慣於使用A = B or C。條件表達式通常用於更復雜的條件,這些條件不適用於簡單的or(例如在A = B if X else C條件並非基於B的真實性,而是X,可能是從簡單值到複雜表達式的任何內容)。

但是,您需要小心,因爲JaredGoguen在他的回答中指出,在OP示例中將or更改爲else實際上會更改代碼的行爲。該代碼的編寫取決於or運算符的這種特定行爲。您不能用or替換任何使用條件表達式的賦值。額外的重構可能也需要。

1

我可能會在此做一個價值判斷,並說這不是好的代碼,因爲它使用or的短路行爲來產生副作用。

考慮給定的條件:if x in j or j_add(x)

x in jor發生短路時,跳過j_add(x)部分條件,並評估爲True

x not in j,檢查語句j_add(x)的真實性。此方法返回None,這是虛假的,因此or評估爲False

因此,整個條件將評估與x in j相同。然而j_add(x)的副作用是將x添加到j!這種副作用正在被利用,以記錄獨特的成員my_list在一個快速和骯髒的理解。

改變orelse仍然會構建j根據需要,但它會添加不當Nonej_add(x)返回值,以twice