Python中是否有交换两个变量的标准化方法?
在Python中,我看到两个变量值使用以下语法交换:Python中是否有交换两个变量的标准化方法?,python,syntax,swap,conventions,Python,Syntax,Swap,Conventions,在Python中,我看到两个变量值使用以下语法交换: left, right = right, left 这被认为是交换两个变量值的标准方法,还是有其他方法,按照惯例,两个变量最常交换?这是交换两个变量的标准方法,是的 Python从左到右计算表达式。注意 在评估作业时,右手边在 左手边 这意味着表达式a,b=b,a: 计算右侧b,a,也就是说,在内存中创建两个元素的元组。这两个元素是由标识符b和a指定的对象,它们在程序执行过程中遇到指令之前存在 在创建这个元组之后,还没有对这个元组对象进
left, right = right, left
这被认为是交换两个变量值的标准方法,还是有其他方法,按照惯例,两个变量最常交换?这是交换两个变量的标准方法,是的 Python从左到右计算表达式。注意 在评估作业时,右手边在 左手边 这意味着表达式
a,b=b,a
:
- 计算右侧
,也就是说,在内存中创建两个元素的元组。这两个元素是由标识符b,a
和b
指定的对象,它们在程序执行过程中遇到指令之前存在a
- 在创建这个元组之后,还没有对这个元组对象进行赋值,但这并不重要,Python内部知道它在哪里
- 然后,计算左侧,也就是说,将元组分配给左侧
- 由于左侧由两个标识符组成,因此对元组进行解包,以便将第一个标识符
分配给元组的第一个元素(该对象在交换之前是b,因为它有名称a
)b
第二个标识符
被分配给元组的第二个元素(这是交换之前a的对象,因为它的标识符是b
)a
a
和b
因此,回答您的问题:是的,这是交换两个对象上的两个标识符的标准方法。顺便说一下,对象不是变量,它们是对象。我知道三种交换变量的方法,但是
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
德尔瓦
元组交换
x,y=y,x
我不会说这是一种标准的交换方式,因为它会导致一些意外错误
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
nums[i]
将首先修改,然后影响第二个变量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)
另请参见要解决所解释的问题,可以使用
copy
模块通过函数返回包含(反转)值副本的元组:
from copy import copy
def swapper(x, y):
return (copy(y), copy(x))
与λ相同的功能
:
swapper = lambda x, y: (copy(y), copy(x))
然后,将这些名称指定给所需的名称,如下所示:
x, y = swapper(y, x)
注意:如果您愿意,您可以导入/使用
deepcopy
而不是copy您可以组合元组和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))
或
使用lambda:
输出:
Before swapping: x = 10 , y = 20
After swapping: x = 20 , y = 10
是最简单也是唯一一个没有混淆的。XOR不交换“变量”。它交换整数变量。(或者其他一些类型正确地实现了XOR运算符)此外,根据Rogalski的回答,元组交换在解释器中得到了优化,因此实际上没有什么反对它的。使用+-运算符可以避免XOR问题,但我觉得最好的方法是a,b=b,acode
x=x+yy=x-yx=x-ycode
如果是关于整数值的问题,你可以用简单的算法来解决。几乎任何编程语言都有这个问题,使用swap(a,b)是不安全的,如果a依赖于b,反之亦然。例如,掉期(a,b)可以扩展为:var c=a
,a=b
,b=c
。然后,最后一个赋值将使用a
的新值来计算b的地址nums[nums[i]-1],nums[i]=nums[i],nums[nums[i]-1]
。将解决问题。@JacksonKelley右侧的评估是安全的。在nums[i]、nums[nums[i]-1]=nums[nums[i]-1]、nums[i]
中:问题是当python执行左侧赋值时,nums[i]
发生了更改,这会导致nums[i]-1]
发生意外的更改。你可以想象一开始你想要nums[1],nums[2]=nums[2],nums[1]
,但是在nums[1]=nums[2]
运行之后,你不再有nums[2]=nums[1]
,而是得到了nums[888]=nums[1]
。这确实是一个特殊的特性(或bug)“@eyquem:它只取决于是否由元组/列表赋值的语言定义。Python确实是这样,大多数旧语言都没有。.HMM MM有交换(A[i],a[k]),为什么我们不能为Python这样的东西。@ NILS,因为在Python中,赋值是一个别名操作,而C++ C++中的赋值是一个替换操作。因此,在Python中,不能替换传递给C++中的函数的参数值(只能对它们进行突变)。有关这些术语的解释,请参见Grogono和Sakkinen的著作。据我所知,以这种方式交换两个变量不会占用额外的内存,只会占用两个变量本身的内存,对吗?@Catbuilts构造元组将占用一些额外内存(可能比交换的三变量版本占用的内存更多),但由于交换的只是内存地址,所以从绝对意义上讲,不会有太多额外的内存(可能是24个额外字节)。@Brilliand:Thks。你有这方面的文件吗。这本书很有趣,我想再读一读。谢谢。@ CasBueStudio我不确定,但它可能有助于阅读C++指针如何工作。而Python尝试自动为你做最好的事情,C++实际上给你所有的选择来做所有的事情。
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