簡體   English   中英

為什么不能在一行中交換列表中的兩個項目?

[英]Why can't I swap two items in a list in one line?

為什么這不起作用(不交換值):

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]

第一個示例不起作用的原因是因為您多次調用.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

這是當它變得有趣的時候。 示例的第四部分lol[lol.index("test")]查找test的索引,但是從代碼的第三段中為test分配了1 因此, lol[lol.index("test")]1 ,而不是0 因此, lol[lol.index("test2")]仍然存儲1

說明

歸結為正確理解評估順序在這里的工作原理,尤其是在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")]

附加說明

如果您真的想更多地了解這些函數是如何真正解釋的,那么一種很好的方法是使用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
>>>

因為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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM