Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>How is <code>super()</code> implemented? Here's the code for python3.3:</p> <pre><code>/* 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-&gt;obj); Py_XDECREF(su-&gt;type); Py_XDECREF(su-&gt;obj_type); Py_TYPE(self)-&gt;tp_free(self); } static PyObject * super_repr(PyObject *self) { superobject *su = (superobject *)self; if (su-&gt;obj_type) return PyUnicode_FromFormat( "&lt;super: &lt;class '%s'&gt;, &lt;%s object&gt;&gt;", su-&gt;type ? su-&gt;type-&gt;tp_name : "NULL", su-&gt;obj_type-&gt;tp_name); else return PyUnicode_FromFormat( "&lt;super: &lt;class '%s'&gt;, NULL&gt;", su-&gt;type ? su-&gt;type-&gt;tp_name : "NULL"); } static PyObject * super_getattro(PyObject *self, PyObject *name) { superobject *su = (superobject *)self; int skip = su-&gt;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-&gt;obj. */ skip = (PyUnicode_Check(name) &amp;&amp; PyUnicode_GET_LENGTH(name) == 9 &amp;&amp; PyUnicode_CompareWithASCIIString(name, "__class__") == 0); } if (!skip) { PyObject *mro, *res, *tmp, *dict; PyTypeObject *starttype; descrgetfunc f; Py_ssize_t i, n; starttype = su-&gt;obj_type; mro = starttype-&gt;tp_mro; if (mro == NULL) n = 0; else { assert(PyTuple_Check(mro)); n = PyTuple_GET_SIZE(mro); } for (i = 0; i &lt; n; i++) { if ((PyObject *)(su-&gt;type) == PyTuple_GET_ITEM(mro, i)) break; } i++; res = NULL; /* keep a strong reference to mro because starttype-&gt;tp_mro can be replaced during PyDict_GetItem(dict, name) */ Py_INCREF(mro); for (; i &lt; n; i++) { tmp = PyTuple_GET_ITEM(mro, i); if (PyType_Check(tmp)) dict = ((PyTypeObject *)tmp)-&gt;tp_dict; else continue; res = PyDict_GetItem(dict, name); if (res != NULL) { Py_INCREF(res); f = Py_TYPE(res)-&gt;tp_descr_get; if (f != NULL) { tmp = f(res, /* Only pass 'obj' param if this is instance-mode super (See SF ID #743627) */ (su-&gt;obj == (PyObject *) su-&gt;obj_type ? (PyObject *)NULL : su-&gt;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) &amp;&amp; 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, &amp;PyId___class__); if (class_attr != NULL &amp;&amp; PyType_Check(class_attr) &amp;&amp; (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-&gt;obj != NULL) { /* Not binding to an object, or already bound */ Py_INCREF(self); return self; } if (Py_TYPE(su) != &amp;PySuper_Type) /* If su is an instance of a (strict) subclass of super, call its type */ return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su), su-&gt;type, obj, NULL); else { /* Inline the common case */ PyTypeObject *obj_type = supercheck(su-&gt;type, obj); if (obj_type == NULL) return NULL; newobj = (superobject *)PySuper_Type.tp_new(&amp;PySuper_Type, NULL, NULL); if (newobj == NULL) return NULL; Py_INCREF(su-&gt;type); Py_INCREF(obj); newobj-&gt;type = su-&gt;type; newobj-&gt;obj = obj; newobj-&gt;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", &amp;PyType_Type, &amp;type, &amp;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()-&gt;frame; PyCodeObject *co = f-&gt;f_code; Py_ssize_t i, n; if (co == NULL) { PyErr_SetString(PyExc_SystemError, "super(): no code object"); return -1; } if (co-&gt;co_argcount == 0) { PyErr_SetString(PyExc_SystemError, "super(): no arguments"); return -1; } obj = f-&gt;f_localsplus[0]; if (obj == NULL) { PyErr_SetString(PyExc_SystemError, "super(): arg[0] deleted"); return -1; } if (co-&gt;co_freevars == NULL) n = 0; else { assert(PyTuple_Check(co-&gt;co_freevars)); n = PyTuple_GET_SIZE(co-&gt;co_freevars); } for (i = 0; i &lt; n; i++) { PyObject *name = PyTuple_GET_ITEM(co-&gt;co_freevars, i); assert(PyUnicode_Check(name)); if (!PyUnicode_CompareWithASCIIString(name, "__class__")) { Py_ssize_t index = co-&gt;co_nlocals + PyTuple_GET_SIZE(co-&gt;co_cellvars) + i; PyObject *cell = f-&gt;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)-&gt;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-&gt;type = type; su-&gt;obj = obj; su-&gt;obj_type = obj_type; return 0; } PyDoc_STRVAR(super_doc, "super() -&gt; same as super(__class__, &lt;first argument&gt;)\n" "super(type) -&gt; unbound super object\n" "super(type, obj) -&gt; bound super object; requires isinstance(obj, type)\n" "super(type, type2) -&gt; 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-&gt;obj); Py_VISIT(su-&gt;type); Py_VISIT(su-&gt;obj_type); return 0; } PyTypeObject PySuper_Type = { PyVarObject_HEAD_INIT(&amp;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 */ }; </code></pre> <p>You can see in the <code>super_init</code> at some point there is the check <code>type == NULL</code> and then it raises the error that you see. It is not normal to have <code>NULL</code> s around, so there's probably a bug somewhere in <code>super</code>(and note that <code>super</code> already had bugs in previous releases). At least I'd thought that the cases in which <code>SystemError</code> is raised should be triggered only due to some "internal" failure of the interpreter or some other C code and not from python code.</p> <p>Also, this did not happen only to you, you can find a <a href="http://pgfoundry.org/pipermail/python-general/2009-October/000601.html">post</a> in which this behaviour is considered a bug.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload