Python中PyCodeObject、PyFunctionObject、PyFrameObject的区别与联系
2022/2/21 1:26:21
本文主要是介绍Python中PyCodeObject、PyFunctionObject、PyFrameObject的区别与联系,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
PyCodeObject:代码对象,就是一段代码编译后形成的对象,函数中对应的就是函数体的代码编译结果。
PyFunctionObject :函数对象,它是对PyCodeObject的封装,相当于 PyCodeObject + 函数def定义这一行代码。它在PyCodeObject基础上增加了函数的名称、所属的模块、参数默认值、globals、builtins。
PyFrameObject:函数执行时对应的栈帧,它用于承载PyFunctionObject在执行时所需要的动态信息。包括函数的实参、函数执行时所需的栈、全局变量、局部变量、当前执行到的指令的编号。
PyCodeObject在编译时确定,PyFunctionObject和PyFrameObject都在运行时生成。
其中PyFunctionObject在执行到函数定义指令MAKE_FUNCTION时生成,生成后是静态不变的。也就是说,一个函数一旦定义,其函数名参数默认值、函数绑定的globals和builtins信息不再变化。
PyFrameObject是动态可变的,其包含两层含义:
1)对同一个函数的每一次函数,都会生成一个新的PyFrameObject;
2)每个PyFrameObject在其生命周期内也是不断发生变化的,PyFrameObject承载着函数执行时所需要的所有动态信息。
MAKE_FUNCTION创建PyFunctionObject的过程:
// 创建PyFunctionObject PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { // 获取解释器状态 PyThreadState *tstate = _PyThreadState_GET(); // 获取PyCodeObject PyCodeObject *code_obj = (PyCodeObject *)code; // 获取name和const PyObject *name = code_obj->co_name; if (!qualname) { qualname = name; } PyObject *consts = code_obj->co_consts; // 获取函数所属的__module__ // __module__: Use globals['__name__'] if it exists, or NULL. PyObject *module = _PyDict_GetItemIdWithError(globals, &PyId___name__); // 优先从globals中获取builtins,找不到则从当前栈帧中找,还找不到则以Python解释器中初始化定义的builtins为准 PyObject *builtins = NULL; builtins = _PyEval_BuiltinsFromGlobals(tstate, globals); // borrowed ref // 创建函数对象 PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); // 设置参数 op->func_globals = globals; op->func_builtins = builtins; op->func_name = name; op->func_qualname = qualname; op->func_code = (PyObject*)code_obj; op->func_defaults = NULL; // No default positional arguments op->func_kwdefaults = NULL; // No default keyword arguments op->func_closure = NULL; op->func_dict = NULL; op->func_weakreflist = NULL; op->func_module = module; op->func_annotations = NULL; // Python函数调用的实现对应的C函数 op->vectorcall = _PyFunction_Vectorcall; return (PyObject *)op; }
CALL_FUNCTION执行函数过程:
// python函数调用 PyObject * _PyEval_Vector(PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames) { // 创建栈帧 PyFrameObject *f = _PyEval_MakeFrameVector( tstate, con, locals, args, argcount, kwnames); // 执行栈帧 PyObject *retval = _PyEval_EvalFrame(tstate, f, 0); return retval; } static inline PyObject* _PyEval_EvalFrame(PyThreadState *tstate, PyFrameObject *f, int throwflag) { return tstate->interp->eval_frame(tstate, f, throwflag); } // 执行栈帧的实现 // 解释的eval_frame在解释器初始化时就设置成了_PyEval_EvalFrameDefault PyObject* _Py_HOT_FUNCTION _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag) { // 连接到前一帧 CFrame *prev_cframe = tstate->cframe; // 切换当前帧 tstate->frame = f; PyCodeObject *co = f->f_code; first_instr = (_Py_CODEUNIT *) PyBytes_AS_STRING(co->co_code); next_instr = first_instr + f->f_lasti + 1; for (;;) { _Py_CODEUNIT word = *next_instr; opcode = _Py_OPCODE(word); oparg = _Py_OPARG(word); next_instr++; switch (opcode) { // 执行字节码 } } }
这篇关于Python中PyCodeObject、PyFunctionObject、PyFrameObject的区别与联系的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-21Python编程基础教程
- 2024-11-20Python编程基础与实践
- 2024-11-20Python编程基础与高级应用
- 2024-11-19Python 基础编程教程
- 2024-11-19Python基础入门教程
- 2024-11-17在FastAPI项目中添加一个生产级别的数据库——本地环境搭建指南
- 2024-11-16`PyMuPDF4LLM`:提取PDF数据的神器
- 2024-11-16四种数据科学Web界面框架快速对比:Rio、Reflex、Streamlit和Plotly Dash
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门