2017-09-20 80 views
13

爲什麼這個不行(值不交換):爲什麼我不能在一行中交換列表中的兩個項目?

lol = ["test","test2"] 
lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")] 

但這個工程(值被交換):

i1 = lol.index("test") 
i2 = lol.index("test2") 
lol[i1], lol[i2] = lol[i2], lol[i1] 

回答

9

爲什麼第一個例子是不工作的原因是因爲你多次調用.index(),並且每次之後,列表中的值都會發生變化,因此代碼中的索引不代表元素的實際位置。第二個例子的工作原理是因爲您已將第一個索引存儲在兩個變量中,並在交換中使用這兩個變量。

概述第一個例子:

lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")] 

第一部分:lol[lol.index("test")]0

第二部分:lol[lol.index("test2")]1

第三部分:lol[lol.index("test2")]仍然店1

這是當它獲得interes婷。示例的第四部分lol[lol.index("test")]找到test的索引,但是,test從代碼的第三部分分配了1。因此,lol[lol.index("test")]1,而不是0。因此,lol[lol.index("test2")]仍然存儲1

+3

這給人的錯誤印象是,在「A,B = C,D」的陳述中,評估順序是** 1。** A; ** 2。** B; ** 3。** C; ** 4。** A = C; ** 5。** D; ** 6。** B = D。雖然評估順序應該是** 1。** C; ** 2。** D; ** 3。** A; ** 4。** B; ** 5。** A = C; ** 6。** B = D – kaza

1

因爲X,Y="test","test2"X="test";Y="test2"

lol = ["test","test2"] 
lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")] 

首先得到處理的右手邊將得到評估,因此您可以:

lol[lol.index("test")], lol[lol.index("test2")] = "test2", "test" 

這將具有以下行相同的效果:

lol[lol.index("test")]="test2" 
# returns 0 
# lol==["test2","test2"] 
lol[lol.index("test2")]="test" 
# returns 0 
+1

雖然很明顯你可以說RHS是首先評估的。正如有些人可能會認爲這些報表先被拆分,然後再進行評估。 – kaza

+0

@bulbus同意,事實上我認爲第一行相當具有誤導性,因爲它暗示這兩個操作的順序是相同的,當然這不是真的 –

3

說明

這一切都歸結爲正確理解evaluation order如何在這裏工作,特別是案例expr3, expr4 = expr1, expr2

如果我們通過聲明lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")]一步,我們會得到這樣的事情:

r1=evaluate(expr1) --> "test2" 
r2=evaluate(expr2) --> "test" 
evaluate(expr3)=r1 --> lol[0] = "test2" --> lol = ["test2","test2"] 
evaluate(expr4)=r2 --> lol[0] = "test" --> lol = ["test", "test2"] 

另一個片段是小事:

i1 = lol.index("test") 
i2 = lol.index("test2") 
lol[i1], lol[i2] = lol[i2], lol[i1] 

it1) i1 = 0 
it2) i2 = 1 
it3) lol[i1], lol[i2] = "test2", lol[i1] 
it4) lol[i1], lol[i2] = "test2", "test" 
it5) lol[i1] = "test2" 
it6) lol[i2] = "test" 

Oneliner替代

喜歡的東西,這些應該這樣做:

lol = lol[lol.index("test2")], lol[lol.index("test")] 

lol[0], lol[1] = lol[1], lol[0] 

lol[0], lol[1] = lol[lol.index("test2")], lol[lol.index("test")] 

aditional的筆記

如果你真的想知道更多關於如何將這些功能真的解釋,這樣做的一個很好的方法是使用模塊dis,例如:

>>> import dis 
>>> def f(): 
... lst[lst.index(str1)], lst[lst.index(str2)] = lst[lst.index(str2)], lst[lst.index(str1)] 
... 
>>> dis.dis(f) 
    2   0 LOAD_GLOBAL    0 (lst) 
       3 LOAD_GLOBAL    0 (lst) 
       6 LOAD_ATTR    1 (index) 
       9 LOAD_GLOBAL    2 (str2) 
      12 CALL_FUNCTION   1 
      15 BINARY_SUBSCR 
      16 LOAD_GLOBAL    0 (lst) 
      19 LOAD_GLOBAL    0 (lst) 
      22 LOAD_ATTR    1 (index) 
      25 LOAD_GLOBAL    3 (str1) 
      28 CALL_FUNCTION   1 
      31 BINARY_SUBSCR 
      32 ROT_TWO 
      33 LOAD_GLOBAL    0 (lst) 
      36 LOAD_GLOBAL    0 (lst) 
      39 LOAD_ATTR    1 (index) 
      42 LOAD_GLOBAL    3 (str1) 
      45 CALL_FUNCTION   1 
      48 STORE_SUBSCR 
      49 LOAD_GLOBAL    0 (lst) 
      52 LOAD_GLOBAL    0 (lst) 
      55 LOAD_ATTR    1 (index) 
      58 LOAD_GLOBAL    2 (str2) 
      61 CALL_FUNCTION   1 
      64 STORE_SUBSCR 
      65 LOAD_CONST    0 (None) 
      68 RETURN_VALUE 
>>> 
相關問題