Python:关于Python函数实现的信息

时间:2016-03-12 16:58:10

标签: python python-3.x object cpython python-internals

我发现了CPython实现,Python对象的结构和Python字节码。

使用函数,我发现空函数的堆栈大小为1。
为什么呢? 声明什么var占用堆栈空间?


清空功能:

def empty():
    pass

功能信息:

>>> dis.show_code(empty)

Name:                empty
Filename:            <pyshell#27>
Argument count:      0
Kw-only arguments:   0
Stack size:          1
Number of locals:    0
Variable names:
Constants:
    0: None

Names:
Flags:               OPTIMIZED, NEWLOCALS, NOFREE
First line number:   1
Free variables:
Cell variables:



与当地人合作:

def withlocals():
    first = 0
    second = [1, 2, 3]

功能信息:

>>> dis.show_code(withlocals)

Name:                withlocals
Filename:            <pyshell#27>
Argument count:      0
Kw-only arguments:   0
Stack size:          3
Number of locals:    2
Variable names:
    0: first
    1: second

Constants:
    0: None
    1: 0
    2: 1
    3: 2
    4: 3

Names:
Flags:               OPTIMIZED, NEWLOCALS, NOFREE
First line number:   1
Free variables:
Cell variables:

1 个答案:

答案 0 :(得分:5)

stack_size是解释器操作码的堆栈使用的上限。但是,分析在本文结尾处有一些bugs和另一个较大的分析,因此界限不紧。

>>> def empty():
...     pass
... 
>>> import dis
>>> dis.dis(empty)
  2           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE        

空函数返回None。它需要1个堆栈项来加载堆栈顶部的None引用; RETURN_VALUE返回存储在堆栈顶部的值。

本地变量本身不包含在此计数中,这在

中非常明显
>>> def many_vars():
...     a = 1
...     b = 2
...     c = 3
...     d = 4
...     e = 5
...     f = 6
...     g = 7
... 
>>> many_vars.__code__.co_stacksize
1

的情况下
def withlocals():
    first = 0
    second = [1, 2, 3]

堆栈必须足够大才能构建3的列表。如果向列表中添加元素,则堆栈将增加该数量。我已经将每个点的堆栈大小添加到转储中了:

>>> dis.dis(withlocals)
  2           0 LOAD_CONST               1 (0)          1
              3 STORE_FAST               0 (first)      0

  3           6 LOAD_CONST               2 (1)          1
              9 LOAD_CONST               3 (2)          2
             12 LOAD_CONST               4 (3)          3
             15 BUILD_LIST               3              1
             18 STORE_FAST               1 (second)     0
             21 LOAD_CONST               0 (None)       1
             24 RETURN_VALUE                            0

然而,当涉及到元组常量时,分析似乎存在错误:

>>> def a_long_tuple():
...     first = (0, 0, 0, 0, 0, 0, 0)
... 
...
>>> dis.dis(a_long_tuple)
  2           0 LOAD_CONST               2 ((0, 0, 0, 0, 0, 0, 0))
              3 STORE_FAST               0 (first)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        
>>> dis.show_code(a_long_tuple)
Name:              withlocals
Filename:          <stdin>
Argument count:    0
Kw-only arguments: 0
Number of locals:  1
Stack size:        7
Flags:             OPTIMIZED, NEWLOCALS, NOFREE
Constants:
   0: None
   1: 0
   2: (0, 0, 0, 0, 0, 0, 0)
Variable names:
   0: first

代码只有一个元组,这是一个常量,但分析声称它需要在Python 2和3中的堆栈空间为7!

原因是用于构建常量元组的汇编代码最初与构建列表相同,除了最后使用BUILD_TUPLE操作码;但peephole optimizer optimizes从部分汇编输出到LOAD_CONST。但是,co_stacksize是根据原始汇编代码计算的!