0
class MyClass:
    def __init__(*args):
        print(super())

MyClass()

Why does this code raise RuntimeError: super(): no arguments? This is in Python 3.7.4.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 4
    There has to be a first argument to the method for ["new `super`"](https://www.python.org/dev/peps/pep-3135/) to work correctly, although it doesn't have to be named `self`. – jonrsharpe Feb 26 '20 at 22:32
  • 1
    Is "[because they say so](https://docs.python.org/3/reference/datamodel.html#object.__init__)" enough reason? (I.e., the first argument *must* be a simple variable.) – Jongware Feb 26 '20 at 22:32
  • `print(super(MyClass, args[0]).__init__())` works as expected, no need to explicitly name `self`. – Jared Smith Feb 26 '20 at 22:35

2 Answers2

4

Per PEP 3135, which introduced "new super" (emphasis mine):

The new syntax:

super()

is equivalent to:

super(__class__, <firstarg>)

where __class__ is the class that the method was defined in, and <firstarg> is the first parameter of the method (normally self for instance methods, and cls for class methods).

There must be a specific first parameter for this to work (although it doesn't necessarily have to be called self or cls), it won't use e.g. args[0].


As to why it needs to be a specific parameter, that's due to the implementation; per the comment it uses the "first local variable on the stack". If co->co_argcount == 0, as it is when you only specify *args, you get the no arguments error. This behaviour may not be the same in other implementations than CPython.


Related

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • What is the difference between `self` in `def my_function(self)` and `args[0]` in `def my_function(*args)` ? In the latter case, isn't `args[0]` the `` of the function? And how it is clear from PEP 3135 that `super()` won't work with `args[0]`? – python481516 Feb 27 '20 at 10:05
  • 1
    @python481516 there's no difference between the actual argument values, `self` and `args[0]` in those two cases reference the same object, which is why `super(MyClass, args[0])` would work fine. You just don't get the "automatic" zero-arguments `super` usage without a separate, explicit parameter. – jonrsharpe Feb 27 '20 at 10:08
  • thanks, is it stated anywhere in PEP or other Python documentation that for `super()` to work `__init__` must have **explicit** first parameter or is it just something that developers know from experience? – python481516 Feb 27 '20 at 10:25
  • 1
    @python481516 it's not documented any more explicitly than above, as far as I can find, but every single example in the docs (and that I've ever written) has the explicit `self`/`cls` so avoids the issue that way. I'll add a bit on why the implementation needs that. – jonrsharpe Feb 27 '20 at 10:42
0

Because the first argument of __init__ should be reference to a class instance. If you pass first *args instead some position argument, first argument becomes a tuple:

class MyClass:
    def __init__(self, *args):
        print(self)
        print(args)
        print(super())

MyClass(1,2)

this code will show to the result like this:

<__main__.MyClass object at 0x7f84228ce3c8>  
(1, 2)  
<super: <class 'MyClass'>, <MyClass object>>

Where <__main__.MyClass object at 0x7f84228ce3c8> is reference to the class instance. You can't trick the interpreter by passing first *args(tuple) or **kwargs(dict of named args) instead, because first argument can be just position argument

  • Isn't `def my_function(a, b, c, d, e, ...)` the same as `def my_function(*args)`? And what is the definition of the first argument of the function? In the latter case, is it `args[0]` or `args`? – python481516 Feb 27 '20 at 10:13
  • @python481516 , it's not important how the function gets arguments from outside. What matters is how the function receives its inside. All positional arguments that are not explicitly specified as function parameters will come inside the tuple `args` , including the first one. but python expects the first argument to be a reference to an instance of the current class, not tuple. If first argument is tuple, interpretator raises the error – Александр Feb 27 '20 at 20:32