标签归档:swap

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

问题:是否有标准化的方法可以在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