为什么此交换表达式不能按预期工作?

时间:2019-03-31 23:03:28

标签: python

这是我尝试使用Python编写的基本选择类型。

arr = [64,12,35,312,45,12,50,80,0,4,6,8,92]
for i in range(len(arr)):
    arr[i], arr[arr.index(min(arr[i:]))] = arr[arr.index(min(arr[i:]))], arr[i]

但是,swap表达式不起作用。很明显,我不了解Python。什么事?

1 个答案:

答案 0 :(得分:2)

这是因为首先计算r.h.s,然后在拆包过程中,对l.h.s x上的每个项目依次调用。这意味着当计算l.h.s y时,第一个赋值__setitem__已经发生,因此修改了数组。因此,l.h.s。 arr[arr.index(...)]不一定返回与r.h.s对应值相同的值。

我们可以使用以下代码段对其进行可视化:

arr[i] = arr[arr.index(...)]

哪个输出:

arr.index(...)

还要检查docs about evaluation order of expressions

具体示例的更详细细分

对于您的特定示例,使用最小值的索引,将导致无操作。这些是按顺序执行的步骤:

  1. R.h.s。对class Test: def __getitem__(self, x): print(f'get {x}') return x def __setitem__(self, x, y): print(f'set {x}={y}') class Index: def __init__(self, x): self.x = x print(self) def __repr__(self): return f'{type(self).__name__}({self.x})' test = Test() test[Index(0)], test[Index(1)] = test[Index(2)], test[Index(3)] 进行评估(将其命名为Index(2) get Index(2) Index(3) get Index(3) Index(0) set Index(0)=Index(2) Index(1) set Index(1)=Index(3) ),然后对arr.index(min(arr[i:]))进行评估(将其命名为m;这是{{ 1}})。
  2. R.h.s。 arr[m]被评估(我们将其命名为a)。
  3. L.h.s。评估arr[i:],将索引arr[j]处的元素设置为最小值(b)。
  4. L.h.s。 arr.__setitem__(i, a)被评估。由于之前的操作(3。),i现在将变为a。因此,将索引arr.__setitem__(arr.index(min(arr[i:])), b)处的元素设置为arr.index(min(arr[i:]))之前的i,即将其设置回其先前的值,从而导致无操作。

相反,您可以预先计算索引:

i