python简单内建表达式创建
a = 1
b = []
c = {}
d = 'string'
python实际执行的指令码如下:
1 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (a)
2 4 BUILD_LIST 0
6 STORE_NAME 1 (b)
3 8 BUILD_MAP 0
10 STORE_NAME 2 (c)
4 12 LOAD_CONST 1 ('string')
14 STORE_NAME 3 (d)
16 LOAD_CONST 2 (None)
18 RETURN_VALUE
None
- 每行的具体信息代表如下:源码行号,指令偏移量,指令符号,指令参数,实际参数值。
- 在python的ceval.c中,python使用_PyEval_EvalFrameDefault函数执行栈帧。
- 又由frameobject可知,python使用
for(;;)
循环,判断指令码,执行指令码。 由于是简单内建表达式创建,影响的作用域在f_locals中,现使用表格,代表f_locals的mapping对象。
key value 由于栈在运行过程中一直使用,故同样使用表格表示栈。
栈底
a = 1
a = 1
python执行的字节码为:
1 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (a)
LOAD_CONST
case TARGET(LOAD_CONST): { PREDICTED(LOAD_CONST); PyObject *value = GETITEM(consts, oparg); Py_INCREF(value); PUSH(value); DISPATCH(); }
PyObject *value = GETITEM(consts, oparg)
:宏定义函数,#define GETITEM(v, i) PyTuple_GetItem((v), (i))
,该代码的功能是从consts中取出一个数,压入虚拟机的运行时栈中,其中consts是f->f_code->co_consts,f是当前活跃的栈帧对象。oparg是传入的指令码参数。PUSH(value)
:将consts中的值取出推入运行时栈中。- 目前运行时栈为:
栈底 1 - f_locals为:
key value STORE_NAME
case TARGET(STORE_NAME): { PyObject *name = GETITEM(names, oparg); PyObject *v = POP(); PyObject *ns = f->f_locals; int err; if (ns == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); Py_DECREF(v); goto error; } if (PyDict_CheckExact(ns)) err = PyDict_SetItem(ns, name, v); else err = PyObject_SetItem(ns, name, v); Py_DECREF(v); if (err != 0) goto error; DISPATCH(); }
PyObject *name = GETITEM(names, oparg);
:从符号表中获得符号,oparg为指令码参数,此时为0.PyObject *v = POP();
:栈顶元素弹出。- 检查f->f_locals
PyDict_SetItem(ns, name, v)
:向PyDict即f_locals中设置键和值。- 目前运行时栈为:
栈底 - f_locals为:
key value a 1
b = []
b = []执行的字节码如下:
2 4 BUILD_LIST 0
6 STORE_NAME 1 (b)
BUILD_LIST:
case TARGET(BUILD_LIST): { PyObject *list = PyList_New(oparg); if (list == NULL) goto error; while (--oparg >= 0) { PyObject *item = POP(); PyList_SET_ITEM(list, oparg, item); } PUSH(list); DISPATCH(); }
PyObject *list = PyList_New(oparg);
:创建一个新的list列表。- 如果指令码参数>=0,则弹出运行时栈中oparg个元素,填入list中。
- 将list推入运行时栈。
- 目前运行时栈为:
栈底 list - f_locals为:
key value a 1 STORE_NAME:功能已在a=1时分析,即弹出运行时栈,在names元组中取值,然后存入f_locals中。
- 目前运行时栈为:
栈底 - f_locals为:
key value a 1 b list
c = {}
c = {}执行的字节码如下:
3 8 BUILD_MAP 0
10 STORE_NAME 2 (c)
BUILD_MAP
case TARGET(BUILD_MAP): { Py_ssize_t i; PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); if (map == NULL) goto error; for (i = oparg; i > 0; i--) { int err; PyObject *key = PEEK(2*i); PyObject *value = PEEK(2*i - 1); err = PyDict_SetItem(map, key, value); if (err != 0) { Py_DECREF(map); goto error; } } while (oparg--) { Py_DECREF(POP()); Py_DECREF(POP()); } PUSH(map); DISPATCH(); }
_PyDict_NewPresized((Py_ssize_t)oparg);
:创建一个新字典。- 根据oparg判断是否应当初始化字典。
PEEK
即选取栈中的第几个元素。栈中的元素在while循环中出栈。 - 将map推到栈中
- 目前运行时栈为:
栈底 map - f_locals mapping为:
key value a 1 STORE_NAME
- 执行STORE_NAME后,运行时栈为:
栈底 - f_locals为:
key value a 1 b list c map
d = 'string'
d = 'string',执行的字节码如下:
4 12 LOAD_CONST 1 ('string')
14 STORE_NAME 3 (d)
执行过程同a=1,不再赘述,执行后
运行时栈为:
栈底 f_locals为:
key value a 1 b list c map d 'string'
e = set()
5 16 LOAD_NAME 4 (set)
18 CALL_FUNCTION 0
20 STORE_NAME 5 (e)
LOAD_NAME
case TARGET(LOAD_NAME): { PyObject *name = GETITEM(names, oparg); PyObject *locals = f->f_locals; PyObject *v; if (locals == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals when loading %R", name); goto error; } if (PyDict_CheckExact(locals)) { v = PyDict_GetItemWithError(locals, name); if (v != NULL) { Py_INCREF(v); } else if (_PyErr_Occurred(tstate)) { goto error; } } else { v = PyObject_GetItem(locals, name); if (v == NULL) { if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error; _PyErr_Clear(tstate); } } if (v == NULL) { v = PyDict_GetItemWithError(f->f_globals, name); if (v != NULL) { Py_INCREF(v); } else if (_PyErr_Occurred(tstate)) { goto error; } else { if (PyDict_CheckExact(f->f_builtins)) { v = PyDict_GetItemWithError(f->f_builtins, name); if (v == NULL) { if (!_PyErr_Occurred(tstate)) { format_exc_check_arg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); } goto error; } Py_INCREF(v); } else { v = PyObject_GetItem(f->f_builtins, name); if (v == NULL) { if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { format_exc_check_arg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); } goto error; } } } } PUSH(v); DISPATCH(); }
- 代码先从局部作用域查找变量,如果未找到,就从全局作用域查找代码,如果仍然没有找到,就去内建作用域中查找。
- 将找到的值,推入运行时栈中。
return
栈帧的返回值
16 LOAD_CONST 2 (None)
18 RETURN_VALUE
- LOAD_CONST:加载常量None
RETURN_VALUE:
case TARGET(RETURN_VALUE): { retval = POP(); assert(f->f_iblock == 0); assert(EMPTY()); f->f_state = FRAME_RETURNED; f->f_stackdepth = 0; goto exiting; }
Comments | NOTHING