为什么我不能在一行中交换列表中的两个项目?

tin*_*usf 15 python swap list

为什么这不起作用(值不交换):

lol = ["test","test2"]
lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")]
Run Code Online (Sandbox Code Playgroud)

但这有效(值被交换):

i1 = lol.index("test")
i2 = lol.index("test2")
lol[i1], lol[i2] = lol[i2], lol[i1]
Run Code Online (Sandbox Code Playgroud)

Aja*_*234 10

第一个示例不起作用的原因是因为您.index()多次调用,并且在每次之后,列表中的值都在变化,因此代码中找到的索引不能代表元素的实际位置.第二个示例有效,因为您已将第一个索引存储在两个变量中,并在交换中使用它们.

第一个例子概述:

lol[lol.index("test")], lol[lol.index("test2")] = lol[lol.index("test2")], lol[lol.index("test")] 
Run Code Online (Sandbox Code Playgroud)

第一部分: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.

  • 这给人一种错误的印象,即在"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. (5认同)

BPL*_*BPL 5

解释

这一切都归结为正确理解评估顺序在这里是如何工作的,尤其是 case 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"]
Run Code Online (Sandbox Code Playgroud)

另一个片段是微不足道的:

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"
Run Code Online (Sandbox Code Playgroud)

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")]
Run Code Online (Sandbox Code Playgroud)

附加说明

如果你真的想了解更多关于这些函数是如何真正解释的,一个很好的方法是使用模块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
>>>
Run Code Online (Sandbox Code Playgroud)