![](/img/trans.png)
[英]python a,b = b,a implementation? How is it different from C++ swap function?
[英]a,b = b,a in python vs std::swap() in C++
我知道a,b = b,a
基本上是为元组(a,b)
分配另一个元组(b,a)
。 这是,基本上,交换的值形成a
到b
和从b
到a
。 因此,导致“交换”。
这是C ++中swap()
函数的功能。
从研究中,我看到C ++的swap()
函数使用第三个临时变量来执行交换。 我无法找到如何在python中实现a,b = b,a
。
a,b = b,a
是如何实现的?
python是否也使用第三个临时变量? 如果没有,它是如何工作的?
两种操作如何在速度方面进行比较? 我猜测如果python也使用第三个变量,执行时间的差异将归因于python的解释。
编辑:所有答案都很棒,但社区似乎认为Sapan是最好的。 还要感谢a_guest,虽然没有发表回答,但他们在评论中给了我们很多信息。 另外:每个人似乎都同意swap()
因为它的C ++而更快。 我不一定同意这一点。 如果以冻结二进制文件运行,Python可以非常快。
对于元组赋值,Python直接使用堆栈结构:
>>> import dis
>>> def abc(a, b):
... a, b = b, a
...
>>> dis.dis(abc)
2 0 LOAD_FAST 1 (b)
3 LOAD_FAST 0 (a)
6 ROT_TWO
7 STORE_FAST 0 (a)
10 STORE_FAST 1 (b)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
在python中,左侧目标列表中的分配是从左到右完成的。
a,b = b是如何实现的?
首先, b, a
创建一个元组。 您可以使用例如验证这一点
>>> tmp = 1, 2
>>> tmp
(1, 2)
然后,赋值使用序列解包,覆盖名称a,b。 因此代码基本上是
>>> tmp = (a, b)
>>> b, a = tmp
两种操作如何在速度方面进行比较?
这取决于你的python实现。 如果您使用CPython(标准版本),那么C ++可能会因为编译和优化而快得多。
在CPython中,交换有时会被优化。 对于小交换(<4个元素),它使用优化的交换
>>> def swap(a, b):
>>> a, b = b, a
>>> dis.dis(swap)
3 0 LOAD_FAST 1 (b)
3 LOAD_FAST 0 (a)
6 ROT_TWO
7 STORE_FAST 0 (a)
10 STORE_FAST 1 (b)
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
>>> def swap(a, b, c):
>>> a, b, c = c, b, a
>>> dis.dis(swap)
3 0 LOAD_FAST 2 (c)
3 LOAD_FAST 1 (b)
6 LOAD_FAST 0 (a)
9 ROT_THREE
10 ROT_TWO
11 STORE_FAST 0 (a)
14 STORE_FAST 1 (b)
17 STORE_FAST 2 (c)
20 LOAD_CONST 0 (None)
23 RETURN_VALUE
对于4个或更多元素的交换,它完全符合我上面所写的,没有优化。
>>> def swap(a, b, c, d):
>>> a, b, c, d = d, c, b, a
>>> dis.dis(swap)
3 0 LOAD_FAST 3 (d)
3 LOAD_FAST 2 (c)
6 LOAD_FAST 1 (b)
9 LOAD_FAST 0 (a)
12 BUILD_TUPLE 4
15 UNPACK_SEQUENCE 4
18 STORE_FAST 0 (a)
21 STORE_FAST 1 (b)
24 STORE_FAST 2 (c)
27 STORE_FAST 3 (d)
30 LOAD_CONST 0 (None)
33 RETURN_VALUE
添加到Sapan的答案:
在C ++中,它可能在概念上使用第三个变量进行交换。 但是你可以在这里看到编译器可以生成与python中显示的相同的程序集:
void foo(int& a, int& b)
{
std::swap(a, b);
}
变成
foo(int&, int&):
mov eax, DWORD PTR [rdi]
mov edx, DWORD PTR [rsi]
mov DWORD PTR [rdi], edx
mov DWORD PTR [rsi], eax
ret
关于std::swap
重要背景,不完全是关于python实现的答案。
C ++ std::swap
不会简单地使用第三个变量交换两个变量。 它将使用内部状态的知识来加速它。
std::array
和std::vector
一些例子: https : //gcc.godbolt.org/z/MERLGZ
在这两种情况下,它都不会使用第三个变量来复制整个对象,但会直接交换两种类型的内部表示。
在array
的情况下,如果数组具有正确的对齐,我们就具有分支。 如果是,那么将使用两个xmm
寄存器交换整个对象,如果不是,它将分别交换每个元素。
在vector
情况下,我们交换两个对象之间的内部指针。
std::swap
另一个重要的事情是std::move
,这是C ++ 11的补充,允许轻松交换通常无法复制的两个变量,如std::unique_ptr
。
现在std::swap
通用版本看起来像:
template<typename Tp>
inline void swap(Tp& a, Tp& b)
{
Tp tmp = std::move(a);
a = std::move(b);
b = std::move(tmp);
}
如果你的类型需要内存分配用于复制并支持移动,那么就不会在那里进行内存分配。
可能大多数C ++所做的事情都不适用于python如何处理它的对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.