我有一个python文件:
$ cat main.py
def foo():
x = 10
y = 20
return x+y
foo()
python反汇编如下:
$ python -m dis main.py
1 0 LOAD_CONST 0 (<code object foo at 0x109a933b0, file "main.py", line 1>)
3 MAKE_FUNCTION 0
6 STORE_NAME 0 (foo)
6 9 LOAD_NAME 0 (foo)
12 CALL_FUNCTION 0
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
以下是我的问题:
1)反汇编中,1
表示main.py
中的行号,LOAD_CONST
表示可读格式的操作码。在操作码后面的0
的大部分是什么,有时是(foo)
的引用?你知道吗
2)看起来python加载函数名foo
,然后调用操作码CALL_FUNCTION
。从LOAD_CONST
->;STORE_NAME
在堆栈/堆中发生的事情。python在后台记录了什么(请尽量低级别,欢迎指向CPython源代码)?你知道吗
我在https://docs.python.org/2/library/dis.html上看到STORE_NAME
:
STORE_NAME(namei)
Implements
name = TOS
. namei is the index of name in the attribute co_names of the code object. The compiler tries to use STORE_FAST or STORE_GLOBAL if possible.
然而,除了我们正在做类似于foo = Top Of Stack
的事情之外,我并不清楚这一点。那么foo
实际上就是co_name
中作为co_name[namei]
的东西。如果我们进入LOAD_NAME
,它会把一些东西从co_name
带到TOS
。什么是co_name
(堆分配的unordered_map
,dict
)?你知道吗
我觉得我在挖一个越来越深的洞,我想我应该退后一步,看看社区能提供什么,然后再继续。你知道吗
更新:现在我想起来了,因为我们正在做类似于co_name[namei]
和if namei
的事情。co_name
仅仅是一个内存管理的数组吗?你知道吗
Jason harper的评论解释了你的前两个问题。但换一种说法,操作码名称后面的数字是它们的参数,括号中的东西表示这些参数实际指的是什么。事实证明,大多数操作码只接受一个参数,对于您的特定情况,所有参数都被索引为0。你知道吗
在你的另一个问题上,如果有意义的话,LOAD\u NAME实际上是按名称加载。它将函数
foo
推送到TOS上,这样CALL\u函数就知道要调用什么。你知道吗Python将名称存储在名为
co_names
的元组中,并进一步维护locals
字典,即f_locals
(在Python中可通过locals()
访问)。加载名称在co_names
中的特定索引处获取名称,然后在locals
中查找。常量直接存储在另一个元组中,并以数字索引。你知道吗至于代码引用,请参考CPython发行版中的
$PYPATH/Python/ceval.c
,或者直接在GitHub上查看。你知道吗相关问题 更多 >
编程相关推荐