I understand that __new__
is a static method and super()
can be called from it create a new object, like so:
>>> class A:
... def __new__(cls):
... print('__new__ called')
... return super().__new__(cls)
...
>>> a = A()
__new__ called
Why doesn't the super
call work with other static methods? Why does the following fail?
>>> class B:
... @staticmethod
... def funcB():
... print('funcB called')
...
>>> class C(B):
... @staticmethod
... def funcC():
... print('funcC called')
... super().funcB()
...
>>> c = C()
>>> c.funcC()
funcC called
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in funcC
RuntimeError: super(): no arguments
Where the "super" keyword in Java is used as a reference to the object of the superclass. This implies that to use "super" the method should be invoked by an object, which static methods are not. Therefore, you cannot use the "super" keyword from a static method.
Yes, you can call the methods of the superclass from static methods of the subclass (using the object of subclass or the object of the superclass).
Both this and super are non static and can not be used in static context, which means you can not use this and super keyword inside main method in Java.
Static method definitions are unchanged even after any inheritance, which means that it can be overridden, similar to other class methods.
super()
with no arguments in Python 3 is basically a hack over its argument based version.
When super()
gets no arguments it fetches the first argument i.e the class using a special cell variable named __class__
and for second argument it will get the first local variable from the stack(which is going to be function's first argument).
In case of __new__
it can get both(__class__
and cls
) and works fine.
But in this case for example there's no second variable available apart from __class__
hence it fails.
class A:
@staticmethod
def func():
super().func() # super(__class__, <missing>).func()
A().func() # RuntimeError: super(): no arguments
Now if we change it to accept an argument then things change:
class A:
@staticmethod
def func(foo):
super().func()
# This fails because super(B, 1).func() doesn't make sense.
A().func(1) # TypeError: super(type, obj): obj must be an instance or subtype of type
# Works! But as there's no parent to this class with func() it fails as expected.
A().func(A()) # AttributeError: 'super' object has no attribute 'func'
Hence the only solution is to make the things explicit with super()
in your case:
super(C, C).funcC()
In general I am not sure why the implementation in case of staticmethod can't make an exception and use __class__
for both the arguments to make it work.
Related CPython code:
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;
PyCodeObject *co;
Py_ssize_t i, n;
f = PyThreadState_GET()->frame;
if (f == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no current frame");
return -1;
}
co = f->f_code;
if (co == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no code object");
return -1;
}
if (co->co_argcount == 0) {
PyErr_SetString(PyExc_RuntimeError,
"super(): no arguments");
return -1;
}
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With