When calling super() in a derived class, can I pass in self.__class__?

This question already has an answer here:


No you cannot. The super() call needs to know what class the method is part of, to search the base classes for an overridden method.

If you pass in self.__class__ (or better still, type(self)) then super() is given the wrong starting point to search for methods, and will end up calling its own method again.

See it as a pointer in the list of classes that form the Method Resolution Order sequence. If you pass in type(self) then the pointer will refer to any subclasses instead of the original starting point.

The following code leads to an infinite recursion error:

class Base(object):
    def method(self):
        print 'original'

class Derived(Base):
    def method(self):
        print 'derived'
        super(type(self), self).method()

class Subclass(Derived):
    def method(self):
        print 'subclass of derived'
        super(Subclass, self).method()


>>> Subclass().method()
subclass of derived

<... *many* lines removed ...>

  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
RuntimeError: maximum recursion depth exceeded while calling a Python object

because type(self) is Subclass, not Derived, in Derived.method().

In the example, the MRO for Subclass is [Subclass, Derived, Base], and super() needs to know where to start searching for any overridden methods. By using type(self) you tell it to start at Subclass, so it'll find Derived.method() next, which is where we started.

self.__class__ might not be a subclass, but rather a grandchild-or-younger class, leading to a stack-breaking loop.


 ? How to avoid infinite recursion with super()?
 ? The difference between super().method() versus super(self.__class__,self).method()
 ? How to subclass an OrderedDict?
 ? Django models: managing transactions when commit_manually is deprecated
 ? Django executing backward relation query occurred a maximum recursion depth exceeded error when I use Manager
 ? When running a method from a Python superclass, how can I know the name of the child class that invoked it?
 ? Understanding @property decorator and inheritance
 ? IPython autoreload gives error for repeated calls to Python2 super()
 ? How do I properly inherit from a base class using Super() (Python 2/3)?
 ? How can I interpret this use of Python's super statement