Python super() arguments: why not super(obj)?

后端 未结 2 655
陌清茗
陌清茗 2020-12-04 23:57

I am trying to understand when and how to use super() in Python correctly (either 2.7.x or 3.x)

on >>> help(super) the interpreter tells me how

相关标签:
2条回答
  • 2020-12-05 00:45

    The two-argument form is only needed in Python 2. The reason is that self.__class__ always refers to the "leaf" class in the inheritance tree -- that is, the most specific class of the object -- but when you call super you need to tell it which implementation is currently being invoked, so it can invoke the next one in the inheritance tree.

    Suppose you have:

    class A(object):
       def foo(self):
          pass
    
    class B(A):
       def foo(self):
          super(self.__class__, self).foo()
    
    class C(B):
       def foo(self):
          super(self.__class__, self).foo()
    
    c = C()
    

    Note that c.__class__ is C, always. Now think about what happens if you call c.foo().

    When you call super(self.__class__, self) in a method of C, it will be like calling super(C, self), which means "call the version of this method inherited by C". That will call B.foo, which is fine. But when you call super(self.__class__, self) from B, it's still like calling super(C, self), because it's the same self, so self.__class__ is still C. The result is that the call in B will again call B.foo and an infinite recursion occurs.

    Of course, what you really want is to be able to call super(classThatDefinedTheImplementationThatIsCurrentlyExecuting, self), and that is effectively what the Python 3 super() does.

    In Python 3, you can just do super().foo() and it does the right thing. It's not clear to me what you mean about super(self) being a shortcut. In Python 2, it doesn't work for the reason I described above. In Python 3, it would be a "longcut" because you can just use plain super() instead.

    The super(type) and super(type1, type2) uses might still be needed occasionally in Python 3, but those were always more esoteric usages for unusual situations.

    0 讨论(0)
  • 2020-12-05 00:53

    Trying a short answer:

    self.__class__ is always the actual ("sub-most") class of your object instance – not necessarily the wanted class, which implements the function!

    Replace super(self.__class__, self) with super(__class__, self) and you are right within a method definition in Python 3, because Python 3 provides the magic cell variable __class__ for the implementing class.

    And simply super() with zero arguments is already the shortcut for super(__class__, self) in Python 3. See PEP3135.

    Python 2 neither knows __class__ nor the zero-argument shortcut super().

    0 讨论(0)
提交回复
热议问题