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

在Python中,顺序是否重要;s交换符号?(a,b=b,a),python,Python,我一直在解决一个编码面试问题,看起来像: 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] 给定一个字符数组A和一个整数数组p,其中p[i]表示元素在置换中i处的位置。例如,当A=和P=时,A应该变成 我的解决方案如下所示: for i in rang

我一直在解决一个编码面试问题,看起来像:

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]
给定一个字符数组A和一个整数数组p,其中p[i]表示元素在置换中i处的位置。例如,当
A=
P=
时,A应该变成

我的解决方案如下所示:

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[i]
的赋值会影响赋值给
perm[i]
时从
perm[i]
读取的值;在第二种情况下,对
perm[i]
的赋值使用
perm[i]
的旧值来确定赋值的位置,然后将
perm[i]
的新值赋值

这是因为赋值是从左到右执行的;按顺序采取的步骤如下:

  • 右侧所有值的
    元组
    都已构造(当前解释器中未构造实际的
    元组
    ,但这在逻辑上发生)
  • 发生对左目标的分配(包括确定分配位置所需的所有读取)
  • 转让进行到正确的目标

  • 基本上,您有一个问题,因为您在赋值的左侧以不同的顺序读取和写入相同的值。

    是的,顺序在这里很重要,因为您在从同一列表读取的索引处更改列表的内容。如果相同索引处的值发生变化,则按不同顺序分配可能会产生不同的结果

    下面是它编译的字节码:顺序是(读,读,读,写,读,写)

    另一种方法是:顺序是(读,读,读,读,写,写)

    dis.dis('perm[perm[i]],perm[i]=perm[i],perm[perm[i]')) 1 0加载\u名称0(perm) 3负载名称1(i) 从perm读取6个二进制文件 7加载\u名称0(perm) 10加载\u名称0(perm) 13负载_名称1(i) 从perm读取16个二进制文件 从perm读取17个二进制文件 18罗图二号 19加载\u名称0(perm) 22加载\u名称0(perm) 25装货单位名称1(i) 从perm读取28个二进制文件 29存储写入perm 30加载\u名称0(perm) 33负载名称1(i) 36存储写入perm 37负载常数0(无) 40返回值 因此,第一个可以读取在同一行中写入的值,因为它有一个先写后读的值;但是第二个不能,因为它在写任何东西之前完成了所有的读取


    老实说,我认为你永远不应该写这样的代码,因为即使纯粹是运气使然,它能做你想做的事情,它也是一个难题——它应该做什么并不明显,更不用说它做什么了。声明一个变量,比如
    j=perm[i]
    ,然后写入
    perm[i],perm[j]=perm[j],perm[i]
    ,这样代码就可以理解,而且肯定不是神奇的。

    顺序很重要。赋值左侧的值是从左到右赋值的。
    >>> 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