【问题标题】:How swapping variables is implemented in Python?在 Python 中如何实现交换变量?
【发布时间】:2020-05-23 18:06:53
【问题描述】:

以下代码在 Python 中是如何工作的:

a = input()
b = input()
a, b = b, a  # STATEMENT 1
print(a, b)

语句 1 是在 Python 堆内存空间中创建第三个变量来交换两个数字还是使用某种算法来进行交换?

【问题讨论】:

标签: python algorithm swap cpython


【解决方案1】:

ruohola在提供python代码的翻译字节码方面做得很好。

我在这里复制以供参考:

Python 代码:

a = input()
b = input()
a, b = b, a  # STATEMENT 1
print(a, b)

字节码:

 2           0 LOAD_NAME                0 (input)
             2 CALL_FUNCTION            0
             4 STORE_NAME               1 (a)

 3           6 LOAD_NAME                0 (input)
             8 CALL_FUNCTION            0
            10 STORE_NAME               2 (b)

 4          12 LOAD_NAME                2 (b)
            14 LOAD_NAME                1 (a)
            16 ROT_TWO                  # swapping done here
            18 STORE_NAME               1 (a)
            20 STORE_NAME               2 (b)
            22 LOAD_CONST               0 (None)
            24 RETURN_VALUE

ROT_TWO 操作交换 python 堆栈的前 2 个值。那么到目前为止我们实际上有什么:

Python 通过调用 swap (ROT_TWO) 子例程来交换这两个值。

如果这是您想要走多远并且它回答了您的问题,那很好。 但是,对于那些想要更深入了解此交换 (ROT_TWO) 子例程如何工作的人来说,here is the official CPython implementation

#define TOP()             (stack_pointer[-1])
#define SECOND()          (stack_pointer[-2])
#define SET_TOP(v)        (stack_pointer[-1] = (v))
#define SET_SECOND(v)     (stack_pointer[-2] = (v))
/*..*/
case TARGET(ROT_TWO): {
   PyObject *top = TOP();
   PyObject *second = SECOND();
   SET_TOP(second);
   SET_SECOND(top);
   FAST_DISPATCH();
}

或者换句话说,ROT_TWO 的实现实际上执行了以下步骤(a,b 是堆栈的前 2 个值):

x1 = a
x2 = b
a = x2
b = x1

所以实现使用辅助临时位置x1x2)实际上它使用 2 个辅助内存位置而不是最小的 1 个辅助位置来交换两个值,而不是更多内存- 高效的实现会做:

x = a
a = b
b = x

在当前的计算模型下,swapping two values can be done only in so many different ways 并不会神奇地发生:

  1. 使用辅助临时存储
  2. 使用一系列XOR(或类似的算术)运算

总而言之,Python 在底层确实使用辅助临时位置来交换两个值。

【讨论】:

  • +1 不错的答案!但我想知道你所说的 Python 堆栈是什么意思。不是所有的对象都是在私有堆上创建的吗?堆栈在哪里出现?
  • python机器的虚拟栈,看源码,它是作为虚拟机的栈来实现的。从这个意义上说
  • “虚拟机堆栈”是什么意思?
  • python 字节码由用 C++ (CPython) 实现的虚拟机解释和运行,如链接源代码中所示。此虚拟机具有或模拟堆栈。就是这个意思
【解决方案2】:

这是一个简单的字节码操作,不需要任何中间变量来进行交换。看这个演示:

import dis

code = '''
a = input()
b = input()
a, b = b, a
'''

dis.dis(code)

输出:

 2           0 LOAD_NAME                0 (input)
             2 CALL_FUNCTION            0
             4 STORE_NAME               1 (a)

 3           6 LOAD_NAME                0 (input)
             8 CALL_FUNCTION            0
            10 STORE_NAME               2 (b)

 4          12 LOAD_NAME                2 (b)
            14 LOAD_NAME                1 (a)
            16 ROT_TWO
            18 STORE_NAME               1 (a)
            20 STORE_NAME               2 (b)
            22 LOAD_CONST               0 (None)
            24 RETURN_VALUE

注意:就像整体的字节码一样,这当然只是 CPython 的一个实现细节。

【讨论】:

  • 从技术上讲,ROT_TWO 交换了 python 堆栈 VM 的前 2 个值。 ROT_TWO 实现的代码可以在 CPython 的存储库中找到。从某种意义上说,用于交换的第三个变量的作用是由栈顶扮演的。
  • @NikosM。 Technicaly speaking ROT_TWO swaps the top 2 values of the python stack 我的帖子是否与此冲突..? In a sense the role of the 3rd variable for swapping is played by the top of the stack.这没有任何意义。
  • 不,我的朋友,您的帖子与此不冲突。我只是想指出堆栈的顶部扮演了交换值的第三个变量的角色。就这么简单
  • 事实上我已经为你的帖子投了赞成票,非常棒!但出于好奇,我深入研究了 ROT_TWO 实现,看看它是如何工作的。就这些
  • @NikosM。 Oukkei ??
猜你喜欢
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2021-10-04
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
相关资源
最近更新 更多