我想知道Python 3中的新super是如何实现的。
我做了一个小例子之后,这个问题就浮现在脑海中,我得到了一个奇怪的错误。我正在使用Pyutilib组件体系结构(PCA),并且已经制作了自定义元类来驱动另一个类的创建:
from pyutilib.component.core import implements, SingletonPlugin, PluginMeta, Interface class IPass(Interface): pass class __MetaPlugin(PluginMeta): def __new__(cls, name, baseClasses, classdict): print(cls, name, baseClasses, classdict) if baseClasses: baseClasses += (SingletonPlugin,) return PluginMeta.__new__(cls, name, baseClasses, classdict) class Pass(metaclass=__MetaPlugin): implements(IPass) def __init__(self, inputs=[], outputs=[]): self.inputs = [] self.outputs = [] class A(Pass): def __init__(self): print(self.__class__) # <class '__main__.A'> print(self.__class__.__class__) # <class '__main__.__MetaPlugin'> print(PluginMeta.__class__) # <class 'type'> super().__init__() # SystemError: super(): empty __class__ cell #Pass.__init__(self) - this works a = A()
我收到以下错误:
super().__init__() SystemError: super(): empty __class__ cell
我wonderign究竟超(一样),它引发的错误super().__init__(),而所有的self.__class__,self.__class__.__class__并PluginMeta.__class__存在。另外的“老方法”-Pass.__init__(self)正在工作。
super().__init__()
self.__class__
self.__class__.__class__
PluginMeta.__class__
Pass.__init__(self)
如何super()执行?这是python3.3的代码:
super()
/* Cooperative 'super' */ typedef struct { PyObject_HEAD PyTypeObject *type; PyObject *obj; PyTypeObject *obj_type; } superobject; static PyMemberDef super_members[] = { {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY, "the class invoking super()"}, {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY, "the instance invoking super(); may be None"}, {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY, "the type of the instance invoking super(); may be None"}, {0} }; static void super_dealloc(PyObject *self) { superobject *su = (superobject *)self; _PyObject_GC_UNTRACK(self); Py_XDECREF(su->obj); Py_XDECREF(su->type); Py_XDECREF(su->obj_type); Py_TYPE(self)->tp_free(self); } static PyObject * super_repr(PyObject *self) { superobject *su = (superobject *)self; if (su->obj_type) return PyUnicode_FromFormat( "<super: <class '%s'>, <%s object>>", su->type ? su->type->tp_name : "NULL", su->obj_type->tp_name); else return PyUnicode_FromFormat( "<super: <class '%s'>, NULL>", su->type ? su->type->tp_name : "NULL"); } static PyObject * super_getattro(PyObject *self, PyObject *name) { superobject *su = (superobject *)self; int skip = su->obj_type == NULL; if (!skip) { /* We want __class__ to return the class of the super object (i.e. super, or a subclass), not the class of su->obj. */ skip = (PyUnicode_Check(name) && PyUnicode_GET_LENGTH(name) == 9 && PyUnicode_CompareWithASCIIString(name, "__class__") == 0); } if (!skip) { PyObject *mro, *res, *tmp, *dict; PyTypeObject *starttype; descrgetfunc f; Py_ssize_t i, n; starttype = su->obj_type; mro = starttype->tp_mro; if (mro == NULL) n = 0; else { assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); } for (i = 0; i < n; i++) { if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i)) break; } i++; res = NULL; /* keep a strong reference to mro because starttype->tp_mro can be replaced during PyDict_GetItem(dict, name) */ Py_INCREF(mro); for (; i < n; i++) { tmp = PyTuple_GET_ITEM(mro, i); if (PyType_Check(tmp)) dict = ((PyTypeObject *)tmp)->tp_dict; else continue; res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); f = Py_TYPE(res)->tp_descr_get; if (f != NULL) { tmp = f(res, /* Only pass 'obj' param if this is instance-mode super (See SF ID #743627) */ (su->obj == (PyObject *) su->obj_type ? (PyObject *)NULL : su->obj), (PyObject *)starttype); Py_DECREF(res); res = tmp; } Py_DECREF(mro); return res; } } Py_DECREF(mro); } return PyObject_GenericGetAttr(self, name); } static PyTypeObject * supercheck(PyTypeObject *type, PyObject *obj) { /* Check that a super() call makes sense. Return a type object. obj can be a class, or an instance of one: - If it is a class, it must be a subclass of 'type'. This case is used for class methods; the return value is obj. - If it is an instance, it must be an instance of 'type'. This is the normal case; the return value is obj.__class__. But... when obj is an instance, we want to allow for the case where Py_TYPE(obj) is not a subclass of type, but obj.__class__ is! This will allow using super() with a proxy for obj. */ /* Check for first bullet above (special case) */ if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) { Py_INCREF(obj); return (PyTypeObject *)obj; } /* Normal case */ if (PyType_IsSubtype(Py_TYPE(obj), type)) { Py_INCREF(Py_TYPE(obj)); return Py_TYPE(obj); } else { /* Try the slow way */ PyObject *class_attr; class_attr = _PyObject_GetAttrId(obj, &PyId___class__); if (class_attr != NULL && PyType_Check(class_attr) && (PyTypeObject *)class_attr != Py_TYPE(obj)) { int ok = PyType_IsSubtype( (PyTypeObject *)class_attr, type); if (ok) return (PyTypeObject *)class_attr; } if (class_attr == NULL) PyErr_Clear(); else Py_DECREF(class_attr); } PyErr_SetString(PyExc_TypeError, "super(type, obj): " "obj must be an instance or subtype of type"); return NULL; } static PyObject * super_descr_get(PyObject *self, PyObject *obj, PyObject *type) { superobject *su = (superobject *)self; superobject *newobj; if (obj == NULL || obj == Py_None || su->obj != NULL) { /* Not binding to an object, or already bound */ Py_INCREF(self); return self; } if (Py_TYPE(su) != &PySuper_Type) /* If su is an instance of a (strict) subclass of super, call its type */ return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su), su->type, obj, NULL); else { /* Inline the common case */ PyTypeObject *obj_type = supercheck(su->type, obj); if (obj_type == NULL) return NULL; newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type, NULL, NULL); if (newobj == NULL) return NULL; Py_INCREF(su->type); Py_INCREF(obj); newobj->type = su->type; newobj->obj = obj; newobj->obj_type = obj_type; return (PyObject *)newobj; } } static int super_init(PyObject *self, PyObject *args, PyObject *kwds) { superobject *su = (superobject *)self; PyTypeObject *type = NULL; PyObject *obj = NULL; PyTypeObject *obj_type = NULL; if (!_PyArg_NoKeywords("super", kwds)) return -1; if (!PyArg_ParseTuple(args, "|O!O:super", &PyType_Type, &type, &obj)) return -1; if (type == NULL) { /* Call super(), without args -- fill in from __class__ and first local variable on the stack. */ PyFrameObject *f = PyThreadState_GET()->frame; PyCodeObject *co = f->f_code; Py_ssize_t i, n; if (co == NULL) { PyErr_SetString(PyExc_SystemError, "super(): no code object"); return -1; } if (co->co_argcount == 0) { PyErr_SetString(PyExc_SystemError, "super(): no arguments"); return -1; } obj = f->f_localsplus[0]; if (obj == NULL) { PyErr_SetString(PyExc_SystemError, "super(): arg[0] deleted"); return -1; } if (co->co_freevars == NULL) n = 0; else { assert(PyTuple_Check(co->co_freevars)); n = PyTuple_GET_SIZE(co->co_freevars); } for (i = 0; i < n; i++) { PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i); assert(PyUnicode_Check(name)); if (!PyUnicode_CompareWithASCIIString(name, "__class__")) { Py_ssize_t index = co->co_nlocals + PyTuple_GET_SIZE(co->co_cellvars) + i; PyObject *cell = f->f_localsplus[index]; if (cell == NULL || !PyCell_Check(cell)) { PyErr_SetString(PyExc_SystemError, "super(): bad __class__ cell"); return -1; } type = (PyTypeObject *) PyCell_GET(cell); if (type == NULL) { PyErr_SetString(PyExc_SystemError, "super(): empty __class__ cell"); return -1; } if (!PyType_Check(type)) { PyErr_Format(PyExc_SystemError, "super(): __class__ is not a type (%s)", Py_TYPE(type)->tp_name); return -1; } break; } } if (type == NULL) { PyErr_SetString(PyExc_SystemError, "super(): __class__ cell not found"); return -1; } } if (obj == Py_None) obj = NULL; if (obj != NULL) { obj_type = supercheck(type, obj); if (obj_type == NULL) return -1; Py_INCREF(obj); } Py_INCREF(type); su->type = type; su->obj = obj; su->obj_type = obj_type; return 0; } PyDoc_STRVAR(super_doc, "super() -> same as super(__class__, <first argument>)\n" "super(type) -> unbound super object\n" "super(type, obj) -> bound super object; requires isinstance(obj, type)\n" "super(type, type2) -> bound super object; requires issubclass(type2, type)\n" "Typical use to call a cooperative superclass method:\n" "class C(B):\n" " def meth(self, arg):\n" " super().meth(arg)\n" "This works for class methods too:\n" "class C(B):\n" " @classmethod\n" " def cmeth(cls, arg):\n" " super().cmeth(arg)\n"); static int super_traverse(PyObject *self, visitproc visit, void *arg) { superobject *su = (superobject *)self; Py_VISIT(su->obj); Py_VISIT(su->type); Py_VISIT(su->obj_type); return 0; } PyTypeObject PySuper_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "super", /* tp_name */ sizeof(superobject), /* tp_basicsize */ 0, /* tp_itemsize */ /* methods */ super_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_reserved */ super_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ super_getattro, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ super_doc, /* tp_doc */ super_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ 0, /* tp_methods */ super_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ super_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ super_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ PyObject_GC_Del, /* tp_free */ };
您可以在某处看到super_init检查type == NULL,然后它引发您看到的错误。NULL周围不正常,因此其中可能存在一个错误super(并且请注意,super先前版本中已经存在错误)。至少我认为SystemError应该仅在解释器或其他C代码的某些“内部”失败而不是python代码引起的情况下触发引发这种情况的情况。
super_init
type == NULL
NULL
super
SystemError
另外,这不仅发生在您身上,您还可以在其中找到将此行为视为错误的帖子。