为什么使用super()?

使用Base有区别吗__init__和super()__初始__?

class Base(object):
    def __init__(self):
        print "Base created"
        
class ChildA(Base):
    def __init__(self):
        Base.__init__(self)
        
class ChildB(Base):
    def __init__(self):
        super(ChildB, self).__init__()
        
ChildA() 
ChildB()

当前回答

主要区别在于ChildA__init__将无条件调用Base__init__而ChildB__init__将在任何类中调用__init__,该类恰好是自己祖先行中的ChildB祖先(这可能与您的预期不同)。

如果添加使用多重继承的ClassC:

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base
  pass

ChildC()
help(ChildC) # shows that the Method Resolution Order is ChildC->ChildB->Mixin->Base

则Base不再是ChildB for ChildC实例的父级。现在super(ChildB,self)将指向Mixin,如果self是ChildC实例。

您已在ChildB和Base之间插入Mixin。你可以利用super()

因此,如果您设计的类可以在合作多重继承场景中使用,那么使用super是因为您不知道谁将在运行时成为祖先。

超级考虑的超级帖子和pycon 2015附带的视频很好地解释了这一点。

其他回答

已经注意到,在Python 3.0+中,您可以使用

super().__init__()

这是一种简洁的方法,不需要显式引用父类OR类名,这很方便。我只想补充一点,对于Python 2.7或更低版本,有些人通过编写self来实现不区分名称的行为__class__而不是类名,即。

super(self.__class__, self).__init__()  # DON'T DO THIS!

然而,这中断了对从类继承的任何类的调用,其中self__class__可以返回子类。例如:

class Polygon(object):
    def __init__(self, id):
        self.id = id

class Rectangle(Polygon):
    def __init__(self, id, width, height):
        super(self.__class__, self).__init__(id)
        self.shape = (width, height)

class Square(Rectangle):
    pass

这里我有一个类Square,它是矩形的子类。假设我不想为Square编写单独的构造函数,因为Rectangle的构造函数已经足够好了,但无论出于什么原因,我都希望实现一个Square,这样我就可以重新实现一些其他方法。

当我使用mSquare=Square('a',10,10)创建Square时,Python调用Rectangle的构造函数,因为我没有给Square自己的构造函数。然而,在Rectangle的构造函数中,调用super(self.__class__,self)将返回mSquare的超类,因此它再次调用Rectangle构造函数。正如@S_C所提到的,无限循环就是这样发生的。在本例中,当我运行super(…).__init__()时,我正在调用Rectangle的构造函数,但由于我没有给它任何参数,所以会得到一个错误。

超级没有副作用

Base = ChildB

Base()

按预期工作

Base = ChildA

Base()

进入无限递归。

只是抬头。。。对于Python 2.7,我相信自从super()在2.2版中引入以来,只有当父类之一继承了最终继承对象的类(新型类)时,才能调用super(。

就个人而言,对于python 2.7代码,我将继续使用BaseClassName__init__(self,args),直到我真正获得使用super()的优势。

主要区别在于ChildA__init__将无条件调用Base__init__而ChildB__init__将在任何类中调用__init__,该类恰好是自己祖先行中的ChildB祖先(这可能与您的预期不同)。

如果添加使用多重继承的ClassC:

class Mixin(Base):
  def __init__(self):
    print "Mixin stuff"
    super(Mixin, self).__init__()

class ChildC(ChildB, Mixin):  # Mixin is now between ChildB and Base
  pass

ChildC()
help(ChildC) # shows that the Method Resolution Order is ChildC->ChildB->Mixin->Base

则Base不再是ChildB for ChildC实例的父级。现在super(ChildB,self)将指向Mixin,如果self是ChildC实例。

您已在ChildB和Base之间插入Mixin。你可以利用super()

因此,如果您设计的类可以在合作多重继承场景中使用,那么使用super是因为您不知道谁将在运行时成为祖先。

超级考虑的超级帖子和pycon 2015附带的视频很好地解释了这一点。

super()允许您避免显式引用基类,这可能很好。但主要的优势来自多重继承,在这里可以发生各种有趣的事情。如果还没有,请查看super上的标准文档。

注意,Python 3.0中的语法发生了变化:您可以只说super()__init__()而不是super(ChildB,self)__init__(),它比IMO好得多。标准文档还引用了一个使用super()的指南,这是非常解释性的。