python class的创建

Posted on 2018-04-28 14:12  王将军之武库  阅读(996)  评论(0编辑  收藏  举报
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

Copyright © 2024 王将军之武库
Powered by .NET 9.0 on Kubernetes