在扯函数的运行机制之前,先看看python虚拟机的运行。
py文件会先编译成pyc文件,生成字节码(ceval.c),再执行。
名字空间的概念:类,函数,module都有自己独有的名字空间,python在查找变量值时,会查找的是名字空间里的变量值。
在动态语言里,名字是能够找到其对应东西的唯一途径。
在python里,赋值语句的概念是创建一个对象obj,将这个对象赋值给一个名字,是不是很熟悉。
对的,这也就是为啥python会单独对字符串的dict对象做优化了。
一个对象的名字空间中的所有名字都称为对象的属性,这还牵扯到属性引用。在一个module内部都维护着自己的作用域。
与动态不符的一点是,一个约束是否其作用取决于源程序的文本,也就是说文本的位置决定着这个约束是否起作用。
作用域嵌套:由一个赋值语句引进的名字在这个赋值语句所在的作用域是可见的,而且在其嵌套的每个作用域也可见,
除非它被嵌套于内部,引进同样名字的另一条赋值语句所遮蔽。
python查找变量也是这么查找的LGB,module的作用域-global,函数的是-local,最顶层的作用域-builtin。
再简单聊聊python的一般表达式和条件语句:
1.在python中数值运算不是简单的数值运算,会牵扯到很多对象的检查。如下所示:
w = POP();
v = TOP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
/* cast to avoid undefined behaviour
on overflow */
i = (long)((unsigned long)a + b);
if ((i^a) < 0 && (i^b) < 0)
goto slow_add;
x = PyInt_FromLong(i);
}
else if (PyString_CheckExact(v) &&
PyString_CheckExact(w)) {
x = string_concatenate(v, w, f, next_instr);
/* string_concatenate consumed the ref to v */
goto skip_decref_vx;
}
else {
slow_add:
x = PyNumber_Add(v, w);
}
Py_DECREF(v);
skip_decref_vx:
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) continue;
break;
不简单吧
2.if中的比较操作:
w = POP();
v = TOP();
if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
/* INLINE: cmp(int, int) */
register long a, b;
register int res;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
switch (oparg) {
case PyCmp_LT: res = a < b; break;
case PyCmp_LE: res = a <= b; break;
case PyCmp_EQ: res = a == b; break;
case PyCmp_NE: res = a != b; break;
case PyCmp_GT: res = a > b; break;
case PyCmp_GE: res = a >= b; break;
case PyCmp_IS: res = v == w; break;
case PyCmp_IS_NOT: res = v != w; break;
default: goto slow_compare;
}
x = res ? Py_True : Py_False;
Py_INCREF(x);
}
else {
slow_compare:
x = cmp_outcome(oparg, v, w);
}
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
if (x == NULL) break;
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
continue;
在牵扯到int时,比较的很快,但是其他操作,让我们看看cmp_outcome
static PyObject *
cmp_outcome(int op, register PyObject *v, register PyObject *w)
{
int res = 0;
switch (op) {
case PyCmp_IS:
res = (v == w);
break;
case PyCmp_IS_NOT:
res = (v != w);
break;
case PyCmp_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
break;
case PyCmp_NOT_IN:
res = PySequence_Contains(w, v);
if (res < 0)
return NULL;
res = !res;
break;
case PyCmp_EXC_MATCH:
if (PyTuple_Check(w)) {
Py_ssize_t i, length;
length = PyTuple_Size(w);
for (i = 0; i < length; i += 1) {
PyObject *exc = PyTuple_GET_ITEM(w, i);
if (PyString_Check(exc)) {
int ret_val;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
"catching of string "
"exceptions is deprecated", 1);
if (ret_val < 0)
return NULL;
}
else if (Py_Py3kWarningFlag &&
!PyTuple_Check(exc) &&
!Py3kExceptionClass_Check(exc))
{
int ret_val;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
CANNOT_CATCH_MSG, 1);
if (ret_val < 0)
return NULL;
}
}
}
else {
if (PyString_Check(w)) {
int ret_val;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
"catching of string "
"exceptions is deprecated", 1);
if (ret_val < 0)
return NULL;
}
else if (Py_Py3kWarningFlag &&
!PyTuple_Check(w) &&
!Py3kExceptionClass_Check(w))
{
int ret_val;
ret_val = PyErr_WarnEx(
PyExc_DeprecationWarning,
CANNOT_CATCH_MSG, 1);
if (ret_val < 0)
return NULL;
}
}
res = PyErr_GivenExceptionMatches(v, w);
break;
default:
return PyObject_RichCompare(v, w, op);
}
v = res ? Py_True : Py_False;
Py_INCREF(v);
return v;
}
是不是感觉很复杂,一步步检查,比如tuple,list等集合操作都包括在里面了。
字节码的概念:在python2.7的opcode.h的文件中存储着一百多条字节码,可通过dis包查看