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]
但是,交换表达式不起作用。很明显,这里有一些我不知道的关于 Python 的东西。它是什么?
解决方案
这是因为首先计算 rhs,然后在值解包期间,对于 lhs 上的每个项目__setitem__
,一个接一个地被调用。这意味着当arr[arr.index(...)]
计算 lhs 时,第一个分配arr[i] = arr[arr.index(...)]
已经发生,因此修改了数组。因此, lhsarr.index(...)
不一定返回与 rhs 对应的相同值。
我们可以使用以下代码段来可视化这一点:
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)
还要检查有关表达式评估顺序的文档。
具体示例的更详细细分
对于您的具体示例,使用最小值的索引,这会导致无操作。这些是按顺序发生的步骤:
- Rhs
arr.index(min(arr[i:]))
被求值(它会是一个东西,我们称之为它m
),然后arr[m]
被求值(我们称之为它a
;这是 的最小元素arr[i:]
)。 - Rhs
arr[j]
被评估(我们称之为b
)。 - 评估Lhs
arr.__setitem__(i, a)
,将索引处的元素设置为i
最小值 (a
)。 - 评估Lhs
arr.__setitem__(arr.index(min(arr[i:])), b)
。由于之前的操作 (3.) 将arr.index(min(arr[i:]))
是i
现在。由于这个原因,索引处的元素i
被设置为b
先前的元素arr[i]
,即它被设置回其先前的值,从而导致无操作。
相反,您可以预先计算索引:
index = arr.index(min(arr[i:]))
a[i], a[index] = a[index], a[i]
推荐阅读
- c - 带有 C 模块和错误 2732 的 C++ DLL 项目
- android - 在隐藏软按钮导航栏上,状态栏在右侧保留未覆盖的空间
- java - 在 Selenium with Java 中,如何取消选中某些复选框?
- r - 使用 type = MPI 的“doParallel”包和直接使用 doMPI 有什么区别?
- docker - Docker:添加卷
- angular - 每个组件引用可以有多个事件吗?
- php - PHP - 如何在同一页面上立即显示上传的图像?
- android - java.lang.IllegalArgumentException:找不到 rx.Single 的调用适配器
- javascript - 图像上传到画布后功能停止工作
- node.js - WebStorm 中的 Node.js