调用参数堆栈如何在Python中工作?

时间:2016-10-15 20:33:17

标签: python stack callstack

我正在学习python并试图了解堆栈如何在python中运行。我有些疑惑。我知道如何堆栈工作,我已经阅读了很多关于它的文章和教程。我已经阅读了很多关于stackoverflow的线程,它们都很好,但我仍有一些疑问。

到目前为止,我已经读取了堆栈存储并返回了函数的值。它由LIFO负责人工作。

只有堆栈的第一个值将返回并存储在顶部。

所以我的问题是 - 假设有四个变量:

a = 9
b = 2
c = 13
d = 4

它们按顺序存储在堆栈中,函数调用该值,例如:

sum = a + d
sum = b + c

a = 9
d = 4
b = 2
c = 13

他们将从上到下返回。现在我的困惑是 - 如果任何操作需要使用dc,而堆栈从顶部返回值,堆栈将如何获得值dc,如只要它们处于堆叠中间。将堆栈首先返回a然后返回d ??

这就是混乱。

2 个答案:

答案 0 :(得分:0)

如果您对python的工作原理感兴趣,那么有一个标准的CPython库dis。 以下是测试代码的输出:

>>> import dis
>>> def test():
...     a = 9
...     b = 2
...     c = 13
...     d = 14
...     sum1 = a + d
...     sum2 = b + c
... 
>>> dis.dis(test)
  2           0 LOAD_CONST               1 (9)
              3 STORE_FAST               0 (a)

  3           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

  4          12 LOAD_CONST               3 (13)
             15 STORE_FAST               2 (c)

  5          18 LOAD_CONST               4 (14)
             21 STORE_FAST               3 (d)

  6          24 LOAD_FAST                0 (a)
             27 LOAD_FAST                3 (d)
             30 BINARY_ADD          
             31 STORE_FAST               4 (sum1)

  7          34 LOAD_FAST                1 (b)
             37 LOAD_FAST                2 (c)
             40 BINARY_ADD          
             41 STORE_FAST               5 (sum2)
             44 LOAD_CONST               0 (None)
             47 RETURN_VALUE        

如你所见,它与堆栈无关。 即使使用经过调整的代码,它也不会做,例如

>>> def test2(a,b,c,d):
...     sum1 = a + d
...     sum2 = b + c
... 
>>> dis.dis(test2)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_FAST                3 (d)
              6 BINARY_ADD          
              7 STORE_FAST               4 (sum1)

  3          10 LOAD_FAST                1 (b)
             13 LOAD_FAST                2 (c)
             16 BINARY_ADD          
             17 STORE_FAST               5 (sum2)
             20 LOAD_CONST               0 (None)
             23 RETURN_VALUE        

如果您对计算中的堆栈概念感兴趣,您应该切换到一些低级(2.5代语言,如C),或者更深入地学习汇编语言。

阅读各种调用约定也可能是另一个好的起点(例如x86 calling conventions

答案 1 :(得分:0)

虽然堆栈可以作为LIFO使用,但您必须要注意确切堆叠的数据结构。例如,许多编程语言在调用函数时使用堆栈来存储参数和局部变量。但是正在堆叠的东西是整个调用框架,而不是框架中的各个变量。

例如,在C中,我可能在堆栈上有局部变量a,b,c,d“,但这意味着它们存储在距帧开始的已知固定偏移处。可以按任何顺序访问变量,它们不会移动(除了编译器可能正在进行的优化)。

Python让它变得有点复杂。至少在CPython中,底层有一个堆栈框架,但是你看到的局部变量实际上存储在一个函数实例对象上的一个数组中(参见下面的shadowranger注释),该对象组成了函数的本地命名空间。所有变量都可以随时通过dict访问。

在这些情况下,局部变量本身不是LIFO,只要您知道它们在命名空间字典中的偏移或名称,就可以任意访问。