1

I have two classes

class Something(object): def __init__(self): self.thing = "thing" class SomethingElse(Something): def __init__(self): self.thing = "another" 

as you can see, one inherits from another. When I run super(SomethingElse), no error is thrown. However, when I run super(SomethingElse).__init__(), I was expecting an unbound function call (unbound to a hypothetical SomethingElse instance) and so was expecting that __init__() would complain about not receiving an object for its self parameter, but instead I get this error:

TypeError: super() takes at least 1 argument (0 given) 

What is the meaning of this message?

EDIT: I often see people hand-wave answer a super question, so please don't answer unless you really know how the super delegate is working here, and know about descriptors and how they are used with super.

EDIT: Alex suggested I update my post with more details. I'm getting something different now in both ways I used it for 3.6 (Anaconda). Not sure what is going on. I don't receive what Alex did, but I get:

class Something(object): def __init__(self): self.thing = "thing" class SomethingElse(Something): def __init__(self): super(SomethingElse).__init__() 

The calls (on Anaconda's 3.6):

SomethingElse() <no problem> super(SomethingElse).__init__() Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: super(): no arguments super(SomethingElse).__init__(SomethingElse()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: super() argument 1 must be type, not SomethingElse 

My understanding of super was that, according to https://docs.python.org/3/library/functions.html#super, that super() with just the first argument would leave the super object unbounded to an instance, so that if you called __init__() on the super object, you'd need to pass in an instance as __init__() would be unbounded as well. However, 3.6 complains about how, with super(SomethingElse).__init__(SomethingElse(), SomethingElse isn't a type, which it should be as it inherits from a parent that inherits from object.

on 2.7.13 gives the original error for super(SomethingElse).__init__(), which was TypeError: super() takes at least 1 argument (0 given). For super(SomethingElse).__init__(SomethingElse()) it throws TypeError: super() argument 1 must be type, not SomethingElse

12
  • @Narendra This doesn't help. I've scoured the internet, and have seen that multiple times. Commented Mar 2, 2018 at 17:09
  • 1
    Is this python 2? Commented Mar 2, 2018 at 17:33
  • You should switch to Python version 3.6+ while you are still learning.... pythonclock.org Commented Mar 2, 2018 at 17:49
  • 1
    Can reproduce on 2.7. Can't reproduce on 3.6. Commented Mar 2, 2018 at 18:31
  • 1
    @ben Please update your question to reflect the actual context in which you are invoking super(SomethingElse).__init__() - it will save some time trying to reproduce the error. Side note: I cannot reproduce the error on Python 2.7 - I get TypeError: unbound method __init__() must be called with SomethingElse instance as first argument (got nothing instead) - thank you! Commented Mar 2, 2018 at 19:20

1 Answer 1

3

Calling super with 1 argument produces an "unbound" super object. Those are weird and undocumented and mostly useless, and I won't go into how they were intended to be used, but for the purposes of this answer, we really only need to know one thing about them.

super(SomethingElse).__init__ doesn't go through the usual super proxy logic. You're getting the super instance's own __init__ method, not anything related to SomethingElse.

From there, the rest of the behavior follows. The TypeError: super() takes at least 1 argument (0 given) on Python 2 is because super.__init__ takes at least 1 argument, and you're passing it 0. (You might expect it to say TypeError: super() takes at least 2 arguments (1 given) because it's still getting self - the super object self, not the SomethingElse instance - but due to weird implementation details, methods implemented in C generally don't count self for this kind of error message.)

SomethingElse() succeeds on Python 3 because the super constructor pulls __class__ and self from the usual stack inspection magic.

Calling super(SomethingElse).__init__() manually from outside the class produces RuntimeError: super(): no arguments because super.__init__ tries to do its stack inspection magic and doesn't find __class__ or self.

super(SomethingElse).__init__(SomethingElse()) fails because the first argument to the super constructor is supposed to be a type, not an instance.

Sign up to request clarification or add additional context in comments.

4 Comments

Why does super expect a type during __init__ when I've already given it one in the call super(SomethingElse)? The Python documentation (docs.python.org/3/library/functions.html#super) doesn't suggest that it would lose track of its type.
@ben: Because __init__ expects a type. It doesn't matter whether you already provided one. You're calling the constructor again, and you need to provide all constructor parameters.
If you think that's weird, well, calling the constructor of a constructed object is weird.
Right, but when you call super(SomethingElse, SomethingElse()).__init__(), it doesn't use super's constructor, which is why this is getting confusing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.