繁体   English   中英

顺序在Python的交换符号中是否重要? (a,b = b,a)

[英]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]

发生这种情况是因为分配是从左到右执行的。 采取的步骤依次为:

  1. 右边所有值的tuple均已构建(当前解释器中未构建实际的tuple ,但这在逻辑上发生)
  2. 分配给左目标(包括确定分配位置所需的所有读取)
  3. 分配进行到正确的目标

基本上,您有一个问题,因为您都以不同的顺序在分配的左侧读写相同的值。

是的,这里的顺序很重要,因为您正在更改从同一列表读取的索引处的列表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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM