首页 技术 正文
技术 2022年11月21日
0 收藏 858 点赞 2,585 浏览 3024 个字
def f():
class a():
a=5
def f2():
passDisassembly of f:
14 0 LOAD_CONST 1 ('a')
3 LOAD_CONST 3 (())
6 LOAD_CONST 2 (<code object a at 0133DB18, file "<module1>", line 14>)
9 MAKE_FUNCTION 0
12 CALL_FUNCTION 0
15 BUILD_CLASS
16 STORE_FAST 0 (a)
19 LOAD_CONST 0 (None)
22 RETURN_VALUE

在python opcod.h在 #define BUILD_CLASS    89    ceval.h创建类的伪指令:

case BUILD_CLASS:
u = TOP();
v = SECOND();
w = THIRD();
STACKADJ(-);
x = build_class(u, v, w);#调用到此函数
SET_TOP(x);
Py_DECREF(u);
Py_DECREF(v);
Py_DECREF(w);
break;
build_class(PyObject *methods, PyObject *bases, PyObject *name)
{
PyObject *metaclass = NULL, *result, *base; if (PyDict_Check(methods))
metaclass = PyDict_GetItemString(methods, "__metaclass__");#在词典中找元类
if (metaclass != NULL)
Py_INCREF(metaclass);
else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > ) {
base = PyTuple_GET_ITEM(bases, );
metaclass = PyObject_GetAttrString(base, "__class__");
if (metaclass == NULL) {
PyErr_Clear();
metaclass = (PyObject *)base->ob_type;
Py_INCREF(metaclass);
}
}
else {
PyObject *g = PyEval_GetGlobals();
if (g != NULL && PyDict_Check(g))
metaclass = PyDict_GetItemString(g, "__metaclass__");
if (metaclass == NULL)
metaclass = (PyObject *) &PyClass_Type;
Py_INCREF(metaclass);
}
result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
NULL);
Py_DECREF(metaclass);
if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
/* A type error here likely means that the user passed
in a base that was not a class (such the random module
instead of the random.random type). Help them out with
by augmenting the error message with more information.*/ PyObject *ptype, *pvalue, *ptraceback; PyErr_Fetch(&ptype, &pvalue, &ptraceback);
if (PyString_Check(pvalue)) {
PyObject *newmsg;
newmsg = PyString_FromFormat(
"Error when calling the metaclass bases\n"
" %s",
PyString_AS_STRING(pvalue));
if (newmsg != NULL) {
Py_DECREF(pvalue);
pvalue = newmsg;
}
}
PyErr_Restore(ptype, pvalue, ptraceback);
}
return result;
}
#一般类继承自object,object的__class__属性是type,所有创建类时会调用到type的tp_call
PyObject *
PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
{
ternaryfunc call; if ((call = func->ob_type->tp_call) != NULL) {
PyObject *result;
if (Py_EnterRecursiveCall(" while calling a Python object"))
return NULL;
result = (*call)(func, arg, kw);
Py_LeaveRecursiveCall();
if (result == NULL && !PyErr_Occurred())
PyErr_SetString(
PyExc_SystemError,
"NULL result without error in PyObject_Call");
return result;
}
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
func->ob_type->tp_name);
return NULL;
}
#ty_call又会调用到tp_new()函数
type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *obj; if (type->tp_new == NULL) {
PyErr_Format(PyExc_TypeError,
"cannot create '%.100s' instances",
type->tp_name);
return NULL;
} obj = type->tp_new(type, args, kwds);
if (obj != NULL) {
/* Ugly exception: when the call was type(something),
don't call tp_init on the result. */
if (type == &PyType_Type &&
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == &&
(kwds == NULL ||
(PyDict_Check(kwds) && PyDict_Size(kwds) == )))
return obj;
/* If the returned object is not an instance of type,
it won't be initialized. */
if (!PyType_IsSubtype(obj->ob_type, type))
return obj;
type = obj->ob_type;
if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) &&
type->tp_init != NULL &&
type->tp_init(obj, args, kwds) < ) {
Py_DECREF(obj);
obj = NULL;
}
}
return obj;
}

tp_new函数完成创建一个类的创建细节

再调用tp_ready

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,104
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,580
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,428
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,835
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,918