You seem to be confusing the word type with type() . Here they simply refer to the first argument passed to super() .
What the documentation tells you: if you pass two arguments, then the second argument must be an instance of the first argument or must be a subclass. In other words, the value of isinstance(first_argument, second_argument) or issubclass(first_argument, second_argument) must be true. There is no other meaning.
Just like int() or str() or any other built-in type, the type of object returned by calling super() is a type. There are no separate types for different arguments. See C source code for the object .
The super() object implements a __getattribute__ hook , which implements the behavior of a specific attribute. The documentation tells you that the attribute search rules are the same as for getattr() (but with a documented MRO pass), but that does not mean that super() returns an ancestor class.
What actually happens is that super().__getattribute__ accepts the MRO of the second argument (either type(instance).__mro__ , or cls.__mro__ , depending on how isinstance() or issubclass() was true) , find the first argument in this sequence, and then start testing the attributes. Since the MRO is scanned first (type) of the second argument, it needs to be found, so the constraints are what they are.
In Pure Python, this is what super() does (simplified to focus on only two argument behaviors):
def _supercheck(type_, obj): try: if issubclass(obj, type_): return obj except TypeError:
source share