[英]Does order matter in Python's swap notation? (a, b = b, a)
我一直在解决一个编码面试问题,如下所示:
给定一个字符数组A和一个整数数组P,其中P [i]表示元素在置换中i处的位置。 例如,当A = <a, b, c, d>
并且P = <2, 0, 1, 3>
,A应该变为<b, c, a, d>
我对此的解决方案如下:
for i in range(len(A)):
while perm[i] != i:
A[i], A[perm[i]] = A[perm[i]], A[i]
perm[i], perm[perm[i]] = perm[perm[i]], perm[i]
这给了我无限循环,而下面的一个有效
for i in range(len(A)):
while perm[i] != i:
A[perm[i]], A[i] = A[i], A[perm[i]]
perm[perm[i]], perm[i] = perm[i], perm[perm[i]]
我一直以为Python中swap快捷方式的顺序无关紧要,但是我很困惑为什么上面的那个不起作用而下面的那个很好。
有什么想法吗?
顺序是相当重要的一点 ,你创造它结束了无所谓代码。 在进行任何赋值之前,都会完全计算整个右侧,因此在简单的情况下,这无关紧要。 但比较:
perm[i], perm[perm[i]] = perm[perm[i]], perm[i]
至:
perm[perm[i]], perm[i] = perm[i], perm[perm[i]]
分配给perm[i]
中的第一个影响从读出的值perm[i]
分配给当perm[perm[i]]
; 在第二,分配到perm[perm[i]]
使用的旧值perm[i]
来确定要分配, 然后分配的新值perm[i]
发生这种情况是因为分配是从左到右执行的。 采取的步骤依次为:
tuple
均已构建(当前解释器中未构建实际的tuple
,但这在逻辑上发生) 基本上,您有一个问题,因为您都以不同的顺序在分配的左侧读写相同的值。
是的,这里的顺序很重要,因为您正在更改从同一列表读取的索引处的列表perm
的内容。 如果相同索引处的值正在更改,则以不同顺序进行分配可以得出不同的结果。
这是它编译成的字节码:顺序为(读,读,读,写,读,写)。
>>> dis.dis('perm[i], perm[perm[i]] = perm[perm[i]], perm[i]')
1 0 LOAD_NAME 0 (perm)
3 LOAD_NAME 0 (perm)
6 LOAD_NAME 1 (i)
9 BINARY_SUBSCR # reads from perm
10 BINARY_SUBSCR # reads from perm
11 LOAD_NAME 0 (perm)
14 LOAD_NAME 1 (i)
17 BINARY_SUBSCR # reads from perm
18 ROT_TWO
19 LOAD_NAME 0 (perm)
22 LOAD_NAME 1 (i)
25 STORE_SUBSCR # writes to perm
26 LOAD_NAME 0 (perm)
29 LOAD_NAME 0 (perm)
32 LOAD_NAME 1 (i)
35 BINARY_SUBSCR # reads from perm
36 STORE_SUBSCR # writes to perm
37 LOAD_CONST 0 (None)
40 RETURN_VALUE
这是另一种方式:顺序是(读,读,读,读,读,写,写)。
>>> dis.dis('perm[perm[i]], perm[i] = perm[i], perm[perm[i]]')
1 0 LOAD_NAME 0 (perm)
3 LOAD_NAME 1 (i)
6 BINARY_SUBSCR # reads from perm
7 LOAD_NAME 0 (perm)
10 LOAD_NAME 0 (perm)
13 LOAD_NAME 1 (i)
16 BINARY_SUBSCR # reads from perm
17 BINARY_SUBSCR # reads from perm
18 ROT_TWO
19 LOAD_NAME 0 (perm)
22 LOAD_NAME 0 (perm)
25 LOAD_NAME 1 (i)
28 BINARY_SUBSCR # reads from perm
29 STORE_SUBSCR # writes to perm
30 LOAD_NAME 0 (perm)
33 LOAD_NAME 1 (i)
36 STORE_SUBSCR # writes to perm
37 LOAD_CONST 0 (None)
40 RETURN_VALUE
因此,第一个能够读取在同一行中写入的值,因为它先写入后再读取。 但是第二个则不能,因为它会在写入任何内容之前先进行所有读取。
坦率地说,我认为您永远都不要编写这样的代码,因为即使靠运气它可以满足您的要求,也很令人困惑-不清楚应该做什么,更不用说它可以做什么了。 声明一个变量,例如j = perm[i]
,然后编写perm[i], perm[j] = perm[j], perm[i]
,该代码将是可以理解的,并且绝对不是魔术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.