[笔记]Python虚拟机对函数的解释

demo.py:

i = 1

def f():
    j = 2

f()

test.py:

import dis

source = open('./demo.py').read()
co = compile(source, './demo.py', 'exec')
print(co.co_name)
dis.dis(co)

print("\n")
fCode = co.co_consts[1]
print(fCode.co_name)
dis.dis(fCode)

输出:

<module>
  1           0 LOAD_CONST               0 (1)
              3 STORE_NAME               0 (i)

  3           6 LOAD_CONST               1 (<code object f at 0x022F5430, file "./demo.py", line 3>)
              9 MAKE_FUNCTION            0
             12 STORE_NAME               1 (f)

  6          15 LOAD_NAME                1 (f)
             18 CALL_FUNCTION            0
             21 POP_TOP
             22 LOAD_CONST               2 (None)
             25 RETURN_VALUE        

f
  4           0 LOAD_CONST               1 (2)
              3 STORE_FAST               0 (j)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE  

对于def f():这一语句,Python虚拟机先将函数f对应的PyCodeObject入栈,然后再MAKE_FUNCTION。

        case MAKE_FUNCTION:
            v = POP(); /* code object */
            x = PyFunction_New(v, f->f_globals);
            Py_DECREF(v);
            /* XXX Maybe this should be a separate opcode? */
            if (x != NULL && oparg > 0) {
                v = PyTuple_New(oparg);
                if (v == NULL) {
                    Py_DECREF(x);
                    x = NULL;
                    break;
                }
                while (--oparg >= 0) {
                    w = POP();
                    PyTuple_SET_ITEM(v, oparg, w);
                }
                err = PyFunction_SetDefaults(x, v);
                Py_DECREF(v);
            }
            PUSH(x);
            break;

在相应代码中,将对应的PyCodeObject和帧的全局符号表指针传递给PyFunction_New函数,调用之,最后将返回值入栈。

在PyFunction_New函数中,创建一个PyFunctionObject,然后初始化相应的成员信息,返回之。

而对于函数f的调用,首先将函数名入栈,再执行CALL_FUNCTION:

        case CALL_FUNCTION:
        {
            PyObject **sp;
            PCALL(PCALL_ALL);
            sp = stack_pointer;
#ifdef WITH_TSC
            x = call_function(&sp, oparg, &intr0, &intr1);
#else
            x = call_function(&sp, oparg);
#endif
            stack_pointer = sp;
            PUSH(x);
            if (x != NULL)
                continue;
            break;
        }

在这里,将栈顶指针和参数信息传递给函数call_function,然后恢复栈顶指针,将返回值入栈。

最后实际上是创建了一页帧,然后以帧作为活动环境,调用PyEval_EvalFrameEx函数。

        f = PyFrame_New(tstate, co, globals, NULL);
        if (f == NULL)
            return NULL;

        fastlocals = f->f_localsplus;
        stack = (*pp_stack) - n;

        for (i = 0; i < n; i++) {
            Py_INCREF(*stack);
            fastlocals[i] = *stack++;
        }
        retval = PyEval_EvalFrameEx(f,0);

JasonLee     2011.08.27     19:52

时间: 2024-12-06 01:06:41

[笔记]Python虚拟机对函数的解释的相关文章

[笔记]Python虚拟机对创建基本内置对象的执行过程

同样的,有demo.py代码如下: i = 1 s = "Python" d = {"1":1, "2":2} l = [2, 3] 有test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (i)

[笔记]Python虚拟机对if语句的解释

demo.py代码如下: a = 1 if a > 0: pass elif a == 0: pass else: pass test.py代码如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出结果如下: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (a) 2 6 LOAD_NAME 0 (a) 9 LOAD_

[笔记]Python虚拟机如何执行“i = 1”

首先写一个demo.py,里面只有一句: i = 1 接着写一个test.py,内容如下: import dis source = open('./demo.py').read() co = compile(source, './demo.py', 'exec') dis.dis(co) 输出: 1 0 LOAD_CONST 0 (1) 3 STORE_NAME 0 (i) 6 LOAD_CONST 1 (None) 9 RETURN_VALUE 利用Python库提供的dis工具,可以对其反汇

Python入门及进阶笔记 Python 内置函数小结_python

内置函数 常用函数 1.数学相关 •abs(x) abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. 复制代码 代码如下: >>>print abs(-100) 100 >>>print abs(1+2j) 2.2360679775 •divmod(x,y) divmod(x,y)函数完成除法运算,返回商和余数. 复制代码 代码如下: >>> divmod(10,3) (3, 1) >>> divmod(9,3) (

Python虚拟机的初始化概览

今天想跟下Python虚拟机的启动,看看以调试模式跑起python_d.exe是怎么一个过程. 1. d:\Python-2.7.2\Modules\python.c文件是main函数,直接调用Py_Main函数: 2. 在Py_Main函数中,初始化函数为Py_Initialize();,而后者直接调用Py_InitializeEx(1);函数: 3. 在Py_InitializeEx函数中,首先判断是否已经初始化过,如果有则返回,没有就改下标志,开始初始化:第一步也是十分关键的一步,是调用函

scrapy笔记——python的时间转换

  1 import datetime 2 GMT_FORMAT = '%M %H %d %m %w' 3 datetime.datetime.utcnow().strftime(GMT_FORMAT)   1 #按corn格式显示当前时间 2 #minute hour day month dayofweek 3 import datetime 4 CORN_FORMAT = '%M %H %d %m %w' 5 datetime.datetime.utcnow().strftime(CORN_

Python补充03 Python内置函数清单

原文:Python补充03 Python内置函数清单 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.   Python内置(built-in)函数随着python解释器的运行而创建.在Python的程序中,你可以随时调用这些函数,不需要定义.最常见的内置函数是: print("Hello World!") 在Python教程中,我们已经提到下面一些内置函数: 基本数据类型 type() 反过头来看看 dir() help(

Python中zip()函数用法实例教程_python

本文实例讲述了Python中zip()函数的定义及用法,相信对于Python初学者有一定的借鉴价值.详情如下: 一.定义: zip([iterable, ...])zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表).若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同.利用*号操作符,可以将list unzip(解压). 二.用法示例: 读者看看下面的例子,对

跟老齐学Python之重回函数_python

函数的基本结构 Python中的函数基本结构: 复制代码 代码如下: def 函数名([参数列表]):     语句  几点说明:  •函数名的命名规则要符合python中的命名要求.一般用小写字母和单下划线.数字等组合  •def是函数的开始,这个简写来自英文单词define,显然,就是要定义一个什么东西  •函数名后面是圆括号,括号里面,可以有参数列表,也可以没有参数  •千万不要忘记了括号后面的冒号  •语句,相对于def缩进,按照python习惯,缩进四个空格 看简单例子,深入理解上面的