在Python中是否有交换两个变量的标准化方法?

在Python中,我看到过使用这种语法交换的两个变量值:

left, right = right, left

这被认为是交换两个变量值的标准方法吗?还是有其他方法可以使两个变量按惯例交换?

288266 次浏览

这是交换两个变量的标准方法。

Python从左到右计算表达式。注意,当 求赋值时,右边在 左手边。< / p >

Python文档:评估顺序 .

这意味着表达式a,b = b,a如下所示:

  • 右边的b,a被求值,也就是说,在内存中创建了一个包含两个元素的元组。这两个元素是由标识符ba指定的对象,它们在程序执行期间遇到指令之前就已经存在了。
  • 就在这个元组创建之后,这个元组对象还没有赋值,但这没关系,Python内部知道它在哪里。
  • 然后,求左边的值,也就是说,元组被赋值给左边。
  • 由于左边由两个标识符组成,元组被解包,以便将第一个标识符a分配给元组的第一个元素(该对象在交换之前是b,因为它的名称为b)
    第二个标识符b被赋给元组的第二个元素(它是交换之前的一个对象,因为它的标识符是a)

这种机制有效地交换了分配给标识符ab的对象

所以,回答你的问题:是的,这是交换两个对象上的两个标识符的标准方式。
顺便说一下,对象不是变量,它们是对象

我知道三种交换变量的方法,但a, b = b, a是最简单的。有

异或(整数)

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

我不会说这是交换的标准方式,因为它会导致一些意想不到的错误。

nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]

nums[i]将首先被修改,然后影响第二个变量nums[nums[i] - 1]

对多维数组无效,因为这里使用了引用。

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数组的片

为了解决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

你可以组合元组XOR交换

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))

使用λ:

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

该语法是交换变量的标准方法。但是,在处理被修改并在交换的后续存储元素中使用的元素时,需要注意顺序。

使用带有直接索引的数组是可以的。例如:

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))

给出:
('For A=', [0,1,2,3,4])
('A[i1]=', 3, 'A[i2]=', 1)
('swap indexes 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))

('For p =', [1,2,3,4,5])
('前:P[i2]=', 3, 'P[P[i2]]=', 4)
(“好交换:P (i2) = ', 4,“P [P (i2)] = ', 3)
('good swap with index 2:', [1,2,4,3,5])

('前:p [i2]=', 3, ' p [p [i2]]=', 4)
(“坏掉期:P (i2) = ', 4,“P [P (i2)] = ', 4)
('bad swap with index 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