我发现了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:
答案 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
是根据原始汇编代码计算的!