12
class Works(type):
    def __new__(cls, *args, **kwargs):
        print([cls,args]) # outputs [<class '__main__.Works'>, ()]
        return super().__new__(cls, args)

class DoesNotWork(type):
    def __new__(*args, **kwargs):
        print([args[0],args[:0]]) # outputs [<class '__main__.doesNotWork'>, ()]
        return super().__new__(args[0], args[:0])

Works() # is fine
DoesNotWork() # gets "RuntimeError: super(): no arguments"

As far as I can see, in both cases super._new__ receives the class literal as first argument, and an empty tuple as the 2nd.

So why does one give an error and the other not?

Luken
  • 321
  • 3
  • 13
  • 1
    You're not using `cls` from `__new__` in your `DoesNotWork`... (also - you really should be using `*args` in `super()` as well to keep signatures correct... – Jon Clements Sep 04 '16 at 00:39
  • Im not explicitly giving `__new__` in `DoesNotWork` a concrete 1st argument, but the arguments `super()` is being passed are identical, so I dont understand the error. Using *args gives me `TypeError: type() takes 1 or 3 arguments` error though thats a seperate question. – Luken Sep 04 '16 at 00:53
  • Is there any particular reason you're using `__new__` and not `__init__` - it looks like you're really trying to use the later... – Jon Clements Sep 04 '16 at 01:15
  • No reason, I just to know why I get an error in one case and not the other. – Luken Sep 04 '16 at 01:19
  • In its other form (in non-classmethods), `super(cls)` is the same as `super(cls, the_first_argument_passed_to_this_function)`. I suspect something similar is happening here - `super()` is trying to default to `super(first_argument_passed_to_this_function)`, but `*args` and `**kwargs` don't count as a arguments (because they're a special case), so it fails. – Aran-Fey Sep 04 '16 at 02:52

1 Answers1

21

The zero-argument form of super requires that the method containing it have an explicit (i.e., non-varargs) first argument. This is suggested by an older version of the docs (emphasis added):

The zero argument form automatically searches the stack frame for the class (__class__) and the first argument.

For some reason this note was removed in later versions of the docs. (It might be worth raising a doc bug, because the docs are quite vague about how zero-argument super works and what is required for it to work.)

See also this Python bug report (which is unresolved, and not clearly accepted as even a bug). The upshot is that zero-argument super is magic, and that magic fails in some cases. As suggested in the bug report, if you want to accept only varargs, you'll need to use the explicit two-argument form of super.

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • 2
    Thanks for providing an answer, Python is so unfinished at times. – mins Jan 13 '19 at 13:35
  • in my case, my class init function has the first parameter with `self` and the `super()` was working. then i added 3-10 lines of code before the call to `super()` and somehow that broke the `super()`. FWIW: my python class is running in a browser via `skulpt`... so my application is not traditional. – Trevor Boyd Smith Apr 08 '21 at 13:30
  • @TrevorBoydSmith: If you want help with that you should ask a separate question. – BrenBarn Apr 08 '21 at 19:44
  • @BrenBarn no i fixed the issue. i was reporting that i got the same issue... but in a different way. – Trevor Boyd Smith Apr 09 '21 at 17:33