Why doesn't super () work with static methods other than __new__?

I understand what __new__is a static method and super()can be called from it, creating a new object, for example:

>>> class A:
...     def __new__(cls):
...         print('__new__ called')
...         return super().__new__(cls)
...
>>> a = A()
__new__ called

Why superdoes the call not work with other static methods? Why the following happens:

>>> 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
+9
source share
4 answers

super() without arguments in Python 3 is essentially a hack for its argument-based version.

super() , , .. , __class__, ( ).

__new__ (__class__ cls) .

, , , __class__, , .

class A:
  @staticmethod
  def func():
    super().func()  # super(__class__, <missing>).func()


A().func()  # RuntimeError: super(): no arguments

, , , :

class A:
  @staticmethod
  def func(foo):
    super().func()


# This fails because super(B, 1).func() does not make sense.
A().func(1)  # TypeError: super(type, obj): obj must be an instance or subtype of type
# Works! But as there no parent to this class with func() it fails as expected.
A().func(A())  # AttributeError: 'super' object has no attribute 'func'

, - super() :

super(C, C).funcC()

, , __class__ , .


CPython:

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;
        }
        ...
+6

__new__ python ( "dunder" ). , super , staticmethod . __new__ type, , .

, , , , classmethod.

>>> class B:
...     @classmethod
...     def funcB(cls):
...         print('funcB called')
...
>>> class C(B):
...     @classmethod
...     def funcC(cls):
...         print('funcC called')
...         super().funcB()
...
>>> c = C()
>>> c.funcC()
funcC called
funcB called
+1

, __new__ - ( , ), , . classmethod.

staticmethod, , , . , staticmethod.

, super .

, , .

0

, " " " ",

class A:
    @staticmethod
    def a():
        return "in a"
    @classmethod
    def foo(cls):
        print(cls.a())

class B(A):
    @staticmethod
    def a():
        return "in b"

B.foo()
## in b
0

All Articles