关键字super在Python继承中的实际用途是什么?

关键字super在Python继承中的实际用途是什么?,python,django,Python,Django,我有点理解ChildClass中继承自BaseClass的关键字super是为了防止在ChildClass具有相同方法时重写基类方法。这有什么实际用途 例如: class BaseClass(): def save(*args, **kwargs): print "save from BaseClass" class ChildClass(BaseClass): def save(self, *args, **kwargs): super(Chi

我有点理解
ChildClass
中继承自
BaseClass
的关键字
super
是为了防止在
ChildClass
具有相同方法时重写基类方法。这有什么实际用途

例如:

class BaseClass():
    def save(*args, **kwargs):
        print "save from BaseClass"

class ChildClass(BaseClass):
    def save(self, *args, **kwargs):
        super(ChildClass, self).save(*args, **kwargs)
        print "save from ChildClass"


someObject = ChildClass()
someObject.save()
​
输出:

save from BaseClass
save from ChildClass
我有点理解

您尝试过两次,都不正确:

  • “将同时调用父类方法和子类方法”-否,它在MRO(方法解析顺序)中的下一个类上调用该方法;及
  • “是为了防止在
    ChildClass
    具有相同方法时重写基类方法”-否,子类实现会重写基类,
    super
    允许您访问继承的实现,而无需显式指定类

这有什么实际用途

最简单的情况是,假设我们有一个带有一个初始化参数的基类:

def Base(object):

    def __init__(self, attr1):
        self.attr1 = attr1
还有一个有两个孩子的班级。然后,我们可以通过以下两种方式之一实现子级,或者不调用基类:

def Child(Base):

    def __init__(self, attr1, attr2):
        self.attr1 = attr1 
        self.attr2 = attr2
def Child(Base):

    def __init__(self, attr1, attr2):
        super(Child, self).__init__(attr1)
        self.attr2 = attr2
或者通过调用基类:

def Child(Base):

    def __init__(self, attr1, attr2):
        self.attr1 = attr1 
        self.attr2 = attr2
def Child(Base):

    def __init__(self, attr1, attr2):
        super(Child, self).__init__(attr1)
        self.attr2 = attr2
请注意,这减少了重复,如果我们在
基本
类中更改
attr1
的处理方式(例如,我们将参数分配给“private”属性
\u attr1
并通过
@属性访问它),我们只需更改一次


您还可以将第二个实现为:

def __init__(self, attr1, attr2):
    Base.__init__(self, attr1)
    self.attr2 = attr2

但这同样意味着重复-我们现在必须在
Child
中的两个位置指定名称
Base
,因此如果我们重命名
Base
或更改
Child
的继承,我们必须在两个位置进行更改。

super()
不调用任何东西;您仍然必须显式调用父方法。它允许您访问父类上方法的实现,因此您可以根据需要重用该实现。如果
ChildClass.save()
必须进行一些额外的处理,但您不想复制基类.save()所做的所有工作,该怎么办?这就是
super()
的用武之地,您可以重用原始的
save()
方法,而无需再次执行所有这些工作,但您可以添加到原始行为中,同时向
ChildClass
的用户提供一致的API。我想您要问的是调用父方法的用途是什么,但你可能会问一些完全不同的问题。你读过例如吗?假设
BaseClass.save()
可以存储一些文档,但不通知用户保存状态。因此,您可以
扩展基类
并调用
super.save(…)
(保存文档),然后通知用户保存状态。。。你为什么用
super
前缀打电话?由于您的子方法完全以父方法(
.save(…)
)调用,您需要告诉编译器调用父方法save。如果你不这样做,它会无限地调用自己并抛出一个错误…好的,谢谢你纠正我和你的解释。那样的话,我一点也不明白。这就是为什么我的问题以“有点”