python-3.x - a,b = b,a 为什么这样有错误的结果
问题描述
l = [2,3,1,2,4,5]
l[0],l[l[0]] =l[l[0]],l[0]
print(l)
#wrong result
l = [2,3,1,2,4,5]
l[l[0]],l[0] =l[0],l[l[0]]
print(l)
#correct result
我崩溃了~
第二个是之间的结果
l[0],l[l[0]] =l[l[0]],l[0]
和
l[0] = l[l[0]]
l[l[0]] = l[0]
结果也不一样
解决方案
好吧,让我们抛开你可能不应该做任何如此复杂的事情的事实:-)
该语句将值(a, b) = (c, d)
元组分配给变量元组,并且在完成任何分配之前计算值。
但是,对变量的赋值是有序的,每个变量都在不同的操作中计算和赋值。因此,请检查以下代码(使用b
代替a[something]
以希望使其更清晰):
>>> a = [0, 1] ; b = 0 ; (b, a[b]) = (1, 99) ; print(a)
[0, 99]
你会得到[0, 99]
,因为 to 的分配1
发生在 tob
的分配之前99
,更a[b]
重要的是,在计算出实际引用的对象之前a[b]
。
所以第二个赋值是给a[1 (= changed b)]
变量而不是那个a[0 (= original b)]
,因为b
那时已经改变了。
如果您恢复使用列表元素而不是b
:
>>> a = [0, 1] ; (a[0], a[a[0]]) = (1, 99) ; print(a)
[1, 99]
唯一的区别是它a[0]
也发生了变化,因为这是您用于索引的对象,而不是b
.
你的原因:
l[0] = l[l[0]]
l[l[0]] = l[0]
片段不起作用是因为那甚至还没有接近交换。它是有效的:
a = b
b = a
最终会得到a
并且b
两者都具有最初的值b
。一个更“交换”的版本是:
tmp = b
b = a
a = tmp
这也适用于您的变体使用a[a[0]]
,因为这三行中的每一行都保证在下一行开始之前完全执行。
底线是,虽然元组赋值是 Python 的一个非常强大的特性,但它确实有一些微妙的边缘情况可能会导致悲伤。假设您避开这些情况,它仍然值得使用。
推荐阅读
- algorithm - 递归算法复杂度?
- python - 我可以在一个命令上调用多个消息处理程序吗?
- azure - ADF 按顺序运行 Blob Create 事件
- python - 将图形旋转到经纬度
- excel - 如何在公式中输入动态单元格引用?
- bash - 如何在使用 read 从此处读取文档时保留前导空格?
- javascript - JavaScript 子对象的 URL 查询字符串编码
- javascript - 可以以任何优雅的方式减少带有 2 个变量的 JS 决策而不是使用 IF 语句吗?
- json - 为什么 Angular http 客户端无法识别纯文本响应?
- azure - 具有静态和动态定义磁盘的 VM 的 ARM 模板