11 函数

函数,是一个动态的过程,在函数被调用时,系统会动态创建一个栈帧,函数对应的表示结构:

    typedef struct {
    PyObject_HEAD
    PyObject *func_code;    /* A code object */
    PyObject *func_globals; /* 函数运行时的global名称空间 */
    PyObject *func_defaults;    /* 函数默认参数 NULL or a tuple */
    PyObject *func_closure; // 用于实现闭包的
    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 */
    } PyFunctionObject;

函数内包含的func_code则对应的是函数的代码,静态的、在编译时就定义好了,而函数则是在运行时,即运行到def语句时构建(func_globals是在这时候才能确定的)

所以,一段代码肯定对应一个code object,但是函数对象可能有多个,例如多次调用该函数,会构建多个func object,这些func object的func_code都指向一个code object。

函数对象的创建

注意,Python在执行到def语句后,接着执行其后的代码,而不是进入到函数体内执行其中的语句(这些语句是在编译时就已经构建好了对应的code object),函数的声明和实现时分离的,分在了不同的code object中。

def语句

对应的机器码有三条:

load_const 0

装载编译好的函数体的code object

make_function

构建函数对象

store_name 0

把构建好的函数对象添加到名称空间内

make_function

pop

把之前装载的函数体的code object取出来

PyFunction_New(v, f->f_globals)

主要是分配函数对象的空间,给函数对象中的func_code, func_globals等赋值。

push

把创建好的函数对象压入运行时栈中,最后通过store_name添加。

函数调用

f()

对应的机器码五条:

load_name 0

获取该函数对象

call_function 0

调用

pop_top
load_const
return_value

返回值

你可能感兴趣的:(11 函数)