问题:是否有标准化的方法可以在Python中交换两个变量?
在Python中,我已经看到使用此语法交换了两个变量值:
left, right = right, left
这是否被认为是交换两个变量值的标准方法,或者是否有其他一些方式可以按照惯例最通常地交换两个变量?
In Python, I’ve seen two variable values swapped using this syntax:
left, right = right, left
Is this considered the standard way to swap two variable values or is there some other means by which two variables are by convention most usually swapped?
回答 0
Python从左到右计算表达式。请注意,在评估分配时,右侧的评估先于左侧。
http://docs.python.org/3/reference/expressions.html#evaluation-order
这意味着该表达式的以下内容a,b = b,a
:
- 对右侧
b,a
进行求值,即在内存中创建两个元素的元组。这两个元素是由标识符b
和所指定的对象,这些对象a
在程序执行期间对指令进行加密之前就已存在
- 创建该元组后,仍未分配该元组对象,但这没关系,Python内部知道它在哪里
- 然后,评估左侧,即将元组分配给左侧
- 由于左侧是由两个标识符组成的,因此将元组解压缩,以便将第一个标识符
a
分配给元组的第一个元素(这是交换之前为b的对象,因为它具有名称b
)
,并且第二个标识符b
分配给元组的第二个元素(该对象以前是交换之前的a,因为其标识符为a
)
该机制有效地交换了分配给标识符的对象,a
并且b
因此,回答您的问题:是的,这是在两个对象上交换两个标识符的标准方法。
顺便说一下,对象不是变量,而是对象。
Python evaluates expressions from left to right. Notice that while
evaluating an assignment, the right-hand side is evaluated before the
left-hand side.
http://docs.python.org/3/reference/expressions.html#evaluation-order
That means the following for the expression a,b = b,a
:
- the right-hand side
b,a
is evaluated, that is to say a tuple of two elements is created in the memory. The two element are the objects designated by the identifiers b
and a
, that were existing before the instruction is encoutered during an execution of program
- just after the creation of this tuple, no assignement of this tuple object have still been made, but it doesn’t matter, Python internally knows where it is
- then, the left-hand side is evaluated, that is to say the tuple is assigned to the left-hand side
- as the left-hand side is composed of two identifiers, the tuple is unpacked in order that the first identifier
a
be assigned to the first element of the tuple (which is the object that was formely b before the swap because it had name b
)
and the second identifier b
is assigned to the second element of the tuple (which is the object that was formerly a before the swap because its identifiers was a
)
This mechanism has effectively swapped the objects assigned to the identifiers a
and b
So, to answer your question: YES, it’s the standard way to swap two identifiers on two objects.
By the way, the objects are not variables, they are objects.
回答 1
That is the standard way to swap two variables, yes.
回答 2
我知道三种交换变量的方法,但是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
I know three ways to swap variables, but a, b = b, a
is the simplest. There is
XOR (for integers)
x = x ^ y
y = y ^ x
x = x ^ y
Or concisely,
x ^= y
y ^= x
x ^= y
Temporary variable
w = x
x = y
y = w
del w
Tuple swap
x, y = y, x
回答 3
我不会说这是一种标准的交换方式,因为它将导致一些意外错误。
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
nums[i]
将首先被修改,然后影响第二个变量nums[nums[i] - 1]
。
I would not say it is a standard way to swap because it will cause some unexpected errors.
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
nums[i]
will be modified first and then affect the second variable nums[nums[i] - 1]
.
回答 4
不适用于多维数组,因为此处使用了引用。
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数组的切片
Does not work for multidimensional arrays, because references are used here.
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)
See also Swap slices of Numpy arrays
回答 5
为了解决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
。
To get around the problems explained by eyquem, you could use the copy
module to return a tuple containing (reversed) copies of the values, via a function:
from copy import copy
def swapper(x, y):
return (copy(y), copy(x))
Same function as a lambda
:
swapper = lambda x, y: (copy(y), copy(x))
Then, assign those to the desired names, like this:
x, y = swapper(y, x)
NOTE: if you wanted to you could import/use deepcopy
instead of copy
.
回答 6
您可以组合元组和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
You can combine tuple and XOR swaps: 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))
or
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))
Using 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))
Output:
Before swapping: x = 10 , y = 20
After swapping: x = 20 , y = 10