我尝试在python中实现XOR swap。
x,y= 10,20
x,y,x = x^y,x^y,x^y
print('%s , %s'%(x,y))
输出:
30 , 30
我不是python的新手,但我无法解释这个输出。应该是20,10
。
引擎盖下发生了什么?
答案 0 :(得分:15)
首先,创建一个由x^y
,x^y
和x^y
组成的元组。然后将元组解压缩到x
,y
和x
,导致两者都绑定到x^y
的结果。
让自己避免头痛,并采用Pythonic方式:
x, y = y, x
答案 1 :(得分:10)
正如其他答案所说,对于x, y = y, x
而言,如果你对创建和解包元组过敏,那么它可以连续x-oring ...它只需要连续,而不是同时就像你正在做的那样!
>>> x = 1234
>>> y = 3421
>>> x ^= y
>>> y ^= x
>>> x ^= y
>>> print x
3421
>>> print y
1234
xor-swap技巧的关键是三个连续 xors,即在之后一个 - 这个片段中的三个单独的^=
语句。当然,它没有任何实际意义,但是,如果你真的热衷于它,它 工作,在Python中像其他地方一样工作; - )。
答案 2 :(得分:3)
您需要转录行的“算法”行。
>>> x, y = 10, 20
>>> x = x ^ y; print x, y
30 20
>>> y = x ^ y; print x, y
30 10
>>> x = x ^ y; print x, y
20 10
>>>
您需要阅读维基百科文章的其余部分,该文章解释了正确的实现阻止了并行操作,并且整个想法几乎没用(至少在现代计算机体系结构上)。
答案 3 :(得分:2)
当你有两个指向可变对象的指针时,XOR交换算法才有意义。 a和b是对不可变整数的两个引用。
编辑(根据请求移动评论并扩展):
Python整数是不可变的。因此,每次使用XOR“修改”一个时,新的存储将被分配(或重新使用,例如用于实习)。这基本上与(例如C)不同,其中swap在不分配新内存的情况下更改值。换句话说,XOR交换不会在C99意义上创建新对象(“执行环境中的数据存储区域,其内容可以表示值”)或Python意义。如上所述here,真正的XOR交换可以“交换变量a和b的值,而不需要为临时变量使用额外的空间。”
或凭经验:
>>> x = 3
>>> y = 5
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x: 3 , id(x): 137452872 y: 5 , id(y): 137452848
>>> x ^= y
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x: 6 , id(x): 137452836 y: 5 , id(y): 137452848
>>> y ^= x
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x: 6 , id(x): 137452836 y: 3 , id(y): 137452872
>>> x ^= y
>>> print "x: ", x, ", id(x): ", id(x), "y: ", y, ", id(y): ", id(y)
x: 5 , id(x): 137452848 y: 3 , id(y): 137452872
在这种情况下,我们看到解释器(2.6.4)似乎是interning the integers,所以x最终得到了原来的内存地址。但重点是交换需要至少一个分配(137452836),并且x和y在整个过程中不保留相同的内存地址。
在C:
int x = 3;
int y = 5;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
x ^= y;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
y ^= x;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
x ^= y;
printf("x: %d, &x: %p, y: %d, &y: %p\n", x, &x, y, &y);
给出:
x: 3, &x: 0xbfd433ec, y: 5, &y: 0xbfd433e8
x: 6, &x: 0xbfd433ec, y: 5, &y: 0xbfd433e8
x: 6, &x: 0xbfd433ec, y: 3, &y: 0xbfd433e8
x: 5, &x: 0xbfd433ec, y: 3, &y: 0xbfd433e8
这是一个真正的XOR交换,因此x和y始终保持相同的内存位置,并且没有临时的。
答案 4 :(得分:1)
您可以使用以下方法轻松完成此交换:
x, y = 10, 20 x, y = y, x print((x,y))
至于你所看到的行为,我很确定这是因为整个RHS被评估,然后同时被分配到LHS,在这种情况下x^y
总是30。
答案 5 :(得分:0)
您可以组合使用-“元组交换”和“ XOR swap”: x,y = x ^ x ^ y,x ^ y ^ y
Python:
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))
输出:
Before swapping: x = 10 , y = 20
After swapping: x = 20 , y = 10