【发布时间】:2019-07-14 05:24:53
【问题描述】:
CPython 源代码的Include/funcobject.h 以下一条注释开头:
函数对象和代码对象不应相互混淆 其他:
函数对象是通过执行'def'来创建的 陈述。他们在
__code__属性中引用了一个代码对象, 这是一个纯粹的句法对象,即只不过是一个编译的 一些源代码行的版本。每个源有一个代码对象 代码“片段”,但每个代码对象可以被零引用或 许多函数对象仅取决于“def”的次数 到目前为止,源中的语句已执行。
我不太明白。
我在这里写下我的部分理解。可能有人完成它。
-
编译阶段。
我们有源文件Test.py:
def a_func(): pass解释器对其进行解析并创建两个代码对象 - 一个用于
Test.py,一个用于a_func。Test.py代码对象有这样的co_code字段(反汇编):3 0 LOAD_CONST 0 (<code object a_func at 0x7f8975622b70, file "test.py", line 3>) 2 LOAD_CONST 1 ('a_func') 4 MAKE_FUNCTION 0 6 STORE_NAME 0 (a_func) 8 LOAD_CONST 2 (None) 10 RETURN_VALUE在这个阶段没有创建函数对象。
-
执行阶段。
函数对象是通过执行'def'语句创建的。
当虚拟机到达
MAKE_FUNCTION指令时,它会创建函数对象:typedef struct { PyObject_HEAD PyObject *func_code; /* A code object, the __code__ attribute */ PyObject *func_globals; /* A dictionary (other mappings won't do) */ PyObject *func_defaults; /* NULL or a tuple */ PyObject *func_kwdefaults; /* NULL or a dict */ PyObject *func_closure; /* NULL or a tuple of cell objects */ PyObject *func_doc; /* The __doc__ attribute, can be anything */ PyObject *func_name; /* The __name__ attribute, a string object */ PyObject *func_dict; /* The __dict__ attribute, a dict or NULL */ PyObject *func_weakreflist; /* List of weak references */ PyObject *func_module; /* The __module__ attribute, can be anything */ PyObject *func_annotations; /* Annotations, a dict or NULL */ PyObject *func_qualname; /* The qualified name */ } PyFunctionObject;他们在
__code__属性中引用了一个代码对象,这是一个纯粹的句法对象,即只是一些源代码行的编译版本。
并将
a_func代码对象放入PyObject *func_code字段。现在,注释“函数对象和代码对象不一样”的消息很清楚。每个源代码“片段”有一个代码对象,但每个代码对象可以被零个或多个函数对象引用,这取决于到目前为止源代码中的“def”语句执行了多少次。
我看不懂的部分用强字体强调。
【问题讨论】: