def f(): class a(): a=5 def f2(): pass Disassembly 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(-2); 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) > 0) { base = PyTuple_GET_ITEM(bases, 0); 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) == 1 && (kwds == NULL || (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) 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) < 0) { Py_DECREF(obj); obj = NULL; } } return obj; }
tp_new函数完成创建一个类的创建细节
再调用tp_ready