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

Jum*_*ays 4 python cpython object python-3.x python-internals

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

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


空功能:

def empty():
    pass
Run Code Online (Sandbox Code Playgroud)

功能信息:

>>> 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:
Run Code Online (Sandbox Code Playgroud)



与当地人的作用:

def withlocals():
    first = 0
    second = [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

功能信息:

>>> 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:
Run Code Online (Sandbox Code Playgroud)

Ant*_*ala 5

stack_size是解释器操作码的堆栈使用的上限.然而,分析有一些错误,另一个,在这篇文章末尾有一个较大的错误,所以限制不紧张.

>>> def empty():
...     pass
... 
>>> import dis
>>> dis.dis(empty)
  2           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

空函数返回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
Run Code Online (Sandbox Code Playgroud)

如果是

def withlocals():
    first = 0
    second = [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

堆栈必须足够大才能构建列表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
Run Code Online (Sandbox Code Playgroud)

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

>>> 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
Run Code Online (Sandbox Code Playgroud)

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

原因是用于构建常量元组的汇编代码最初与构建列表相同,除了BUILD_TUPLE最后的操作码; 但是窥视孔优化器将其优化LOAD_CONST部分汇编输出.但是,它co_stacksize是根据原始汇编代码计算的!