在 Python 中是否有一种标准化的方法来交换两个变量?
- 2024-12-03 08:45:00
- admin 原创
- 169
问题描述:
在 Python 中,我看到过使用以下语法交换两个变量值:
left, right = right, left
这是否被视为交换两个变量值的标准方法,或者是否存在其他通常用于交换两个变量的方法?
解决方案 1:
Python 从左到右计算表达式的值。请注意,在计算赋值时,先计算右侧的值,然后再计算左侧的值。
Python 文档:评估顺序
对于表达式来说,这意味着以下内容a,b = b,a
:
右边
b,a
被求值,也就是说,在内存中创建一个包含两个元素的元组。这两个元素是标识符b
和指定的对象a
,它们在程序执行过程中遇到该指令之前就已存在。就在创建这个元组之后,还没有对这个元组对象进行任何赋值,不过这没关系,Python 内部知道它在哪里。
然后对左侧进行求值,也就是说,将元组分配给左侧。
由于左侧由两个标识符组成,因此对元组进行解包,以便将第一个标识符
a
分配给元组的第一个元素(即交换前为bb
的对象,因为它的名称为)
,将第二个标识符分配给元组的第二个元素(即交换前为ab
的对象,因为它的标识符为)a
这种机制实际上交换了分配给标识符的对象a
和b
因此,回答你的问题:是的,这是在两个对象上交换两个标识符的标准方法。
顺便说一句,对象不是变量,它们是对象。
解决方案 2:
是的,这是交换两个变量的标准方法。
解决方案 3:
我知道三种交换变量的方法,但这a, b = b, a
是最简单的。
XOR(用于整数)
x = x ^ y
y = y ^ x
x = x ^ y
或者简而言之,
x ^= y
y ^= x
x ^= y
临时变量
w = x
x = y
y = w
del w
元组交换
x, y = y, x
解决方案 4:
我不会说这是标准的交换方式,因为它会导致一些意外的错误。
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
nums[i]
将首先被修改,然后影响第二个变量nums[nums[i] - 1]
。
解决方案 5:
不适用于多维数组,因为这里使用了引用。
import numpy as np
# swaps
data = np.random.random(2)
print(data)
data[0], data[1] = data[1], data[0]
print(data)
# does not swap
data = np.random.random((2, 2))
print(data)
data[0], data[1] = data[1], data[0]
print(data)
另请参阅交换 Numpy 数组的切片
解决方案 6:
该语法是交换变量的标准方法。但是,在处理被修改然后在交换的后续存储元素中使用的元素时,我们需要注意顺序。
使用带有直接索引的数组是可以的。例如:
def swap_indexes(A, i1, i2):
A[i1], A[i2] = A[i2], A[i1]
print('A[i1]=', A[i1], 'A[i2]=', A[i2])
return A
A = [0, 1, 2, 3, 4]
print('For A=', A)
print('swap indexes 1, 3:', swap_indexes(A, 1, 3))
给我们:(
'对于 A=',[0, 1, 2, 3, 4])
('A[i1]=',3,'A[i2]=',1)
('交换索引 1, 3:',[0, 3, 2, 1, 4])
但是,如果我们改变左边第一个元素并将其用作左边第二个元素的索引,则会导致错误的交换。
def good_swap(P, i2):
j = P[i2]
#Below is correct, because P[i2] is modified after it is used in P[P[i2]]
print('Before: P[i2]=', P[i2], 'P[P[i2]]=', P[j])
P[P[i2]], P[i2] = P[i2], P[P[i2]]
print('Good swap: After P[i2]=', P[i2], 'P[P[i2]]=', P[j])
return P
def bad_swap(P, i2):
j = P[i2]
#Below is wrong, because P[i2] is modified and then used in P[P[i2]]
print('Before: P[i2]=', P[i2], 'P[P[i2]]=', P[j])
P[i2], P[P[i2]] = P[P[i2]], P[i2]
print('Bad swap: After P[i2]=', P[i2], 'P[P[i2]]=', P[j])
return P
P = [1, 2, 3, 4, 5]
print('For P=', P)
print('good swap with index 2:', good_swap(P, 2))
print('------')
P = [1, 2, 3, 4, 5]
print('bad swap with index 2:', bad_swap(P, 2))
('对于 P=', [1, 2, 3, 4, 5])
('之前:P[i2]=', 3, 'P[P[i2]]=', 4)
('良好交换:P[i2]=', 4, 'P[P[i2]]=', 3)
('与索引 2 良好交换:', [1, 2, 4, 3, 5])
('之前:P[i2]=', 3, 'P[P[i2]]=', 4)
('错误交换:P[i2]=', 4, 'P[P[i2]]=', 4)
('索引 2 的错误交换:', [1, 2, 4, 4, 3])
错误交换是不正确的,因为 P[i2] 为 3,我们期望 P[P[i2]] 为 P[3]。然而,P[i2] 首先更改为 4,因此后续的 P[P[i2]] 变为 P[4],它覆盖了第 4 个元素而不是第 3 个元素。
上述场景用于排列组合。更简单的好交换和坏交换将是:
#good swap:
P[j], j = j, P[j]
#bad swap:
j, P[j] = P[j], j
解决方案 7:
为了解决eyquem解释的问题,您可以使用copy
模块通过函数返回包含值(反转)副本的元组:
from copy import copy
def swapper(x, y):
return (copy(y), copy(x))
功能与 相同lambda
:
swapper = lambda x, y: (copy(y), copy(x))
然后,将它们分配给所需的名称,如下所示:
x, y = swapper(y, x)
注意:如果您愿意,您可以导入/使用deepcopy
而不是copy
。
解决方案 8:
您可以组合元组和XOR交换:x, y = x ^ x ^ y, x ^ y ^ y
x, y = 10, 20
print('Before swapping: x = %s, y = %s '%(x,y))
x, y = x ^ x ^ y, x ^ y ^ y
print('After swapping: x = %s, y = %s '%(x,y))
或者
x, y = 10, 20
print('Before swapping: x = %s, y = %s '%(x,y))
print('After swapping: x = %s, y = %s '%(x ^ x ^ y, x ^ y ^ y))
使用lambda:
x, y = 10, 20
print('Before swapping: x = %s, y = %s' % (x, y))
swapper = lambda x, y : ((x ^ x ^ y), (x ^ y ^ y))
print('After swapping: x = %s, y = %s ' % swapper(x, y))
输出:
Before swapping: x = 10 , y = 20
After swapping: x = 20 , y = 10