gpt4 book ai didi

python - Python 上的列表突变

转载 作者:太空宇宙 更新时间:2023-11-03 12:14:31 24 4
gpt4 key购买 nike

我尝试通过交换列表和另一个引用列表之间的公共(public)元素来改变列表,方法是第一个元素。实现如下图:

>>> L = [1,2,3,4,5,6,7,8,9]
>>> A = [3]
>>> L[0], L[L.index(A[0])] = L[L.index(A[0])], L[0] #want to swap 3 with 1
>>> L
[1,2,3,4,5,6,7,8,9,] #List L was not mutated

列表没有像我预期的那样发生变化。但是当我如下所示修改实现时,它起作用了:

>>> L = [1,2,3,4,5,6,7,8,9]
>>> A = [3]
>>> i = L.index(A[0])
>>> L[0], L[i] = L[i], L[0]
>>> L
[3,2,1,4,5,6,7,8,9,] #Now list mutated as desired even though L[i] and L[L.index(A[0])] evaluate to same value.

我的问题是,为什么第一个赋值不能改变列表?我想到了,但我的大脑无法解释。

最佳答案

尽管在 Python 中,在进行多项赋值时,右侧首先被求值,而左侧赋值目标,如果其中有表达式,则被求值分配时一个一个。

如果相反,它们会像您预期的那样首先被评估为分配目标,这当然会奏效。

这记录在 assignment statements section 中:

An assignment statement evaluates the expression list (remember that this can be a single expression or a comma-separated list, the latter yielding a tuple) and assigns the single resulting object to each of the target lists, from left to right.

If the target list is a comma-separated list of targets: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

强调我的。从左到右在这里至关重要。 L[0]L[L.index(3)] 被赋值之前被赋值。

文档然后详细描述了订阅目标(例如 L[0]L[L.index(3)])发生了什么:

If the target is a subscription: The primary expression in the reference is evaluated. It should yield either a mutable sequence object (such as a list) or a mapping object (such as a dictionary). Next, the subscript expression is evaluated.

再次强调我的;下标表达式是单独求值的,并且由于目标列表是从左到右求值的,因此该求值发生在 之前对 L[0] 赋值之后。

反汇编python代码可以看到:

>>> import dis
>>> def f(L):
... L[0], L[2] = L[2], L[0]
...
>>> def g(L):
... L[0], L[L.index(3)] = L[L.index(3)], L[0]
...
>>> dis.dis(f)
2 0 LOAD_FAST 0 (L) # L[2]
3 LOAD_CONST 1 (2)
6 BINARY_SUBSCR
7 LOAD_FAST 0 (L) # L[0]
10 LOAD_CONST 2 (0)
13 BINARY_SUBSCR
14 ROT_TWO
15 LOAD_FAST 0 (L) # Store in L[0]
18 LOAD_CONST 2 (0)
21 STORE_SUBSCR
22 LOAD_FAST 0 (L) # Store in L[2]
25 LOAD_CONST 1 (2)
28 STORE_SUBSCR
29 LOAD_CONST 0 (None)
32 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_FAST 0 (L) # L[L.index(3)]
3 LOAD_FAST 0 (L)
6 LOAD_ATTR 0 (index)
9 LOAD_CONST 1 (3)
12 CALL_FUNCTION 1
15 BINARY_SUBSCR
16 LOAD_FAST 0 (L) # L[0]
19 LOAD_CONST 2 (0)
22 BINARY_SUBSCR
23 ROT_TWO
24 LOAD_FAST 0 (L) # Store in L[0]
27 LOAD_CONST 2 (0)
30 STORE_SUBSCR
31 LOAD_FAST 0 (L) # Store in L[L.index(3)]
34 LOAD_FAST 0 (L)
37 LOAD_ATTR 0 (index)
40 LOAD_CONST 1 (3)
43 CALL_FUNCTION 1
46 STORE_SUBSCR
47 LOAD_CONST 0 (None)
50 RETURN_VALUE

存储操作首先存储L[0] = 3,因此下一次调用L.index(3) 返回0 并且因此 1 被存储在 0 的位置!

以下确实有效:

L[L.index(3)], L[0] = L[0], L[L.index(3)]

因为现在首先完成了 L.index(3) 查找。但是,最好将 .index() 调用的结果存储在一个临时变量中,因为在任何情况下不调用 .index() 两次会更有效率.

关于python - Python 上的列表突变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14798676/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com