根据 Learn Python The Hard Way ex44以及使用 super() 和 __init__ 的解释:
class Child(object):
def __init__(self, stuff):
self.stuff = stuff
super(Child, self).__init__()
This is pretty much the same as the
Child.alteredexample above, except I'm setting some variables in the__init__before having theParentinitialize with itsParent.__init__.
所以实例化 Child 也会导致 Parent 的实例化。但是这个实例化是什么/在哪里?鉴于:
c = Child()
Parent 对象在哪里/什么?
请您参考如下方法:
super(Child, self) 为您提供 self 指向的对象作为 Child 父类的实例(其中是 Parent)。
在 Child 的 __init__ 方法中,你首先做一些事情(self.stuff = stuff)然后调用 __init__ 方法 在 Parent 的 self 指向的 Child 对象上!
您没有显式实例化 Parent 对象,但由于继承,每个 Child 都是 Parent。
@timgeb a practical usage example, or justification for using super() in this way, would be helpful.
当然,让我们看一个简单的例子。假设您正在构建一个邮政服务应用程序。该服务可递送多种元素,例如包裹、信件或明信片。这些项目中的每一个都共享一些属性。为简单起见,假设它们共享接收者的名称(在现实世界的应用程序中,您可能需要更多属性,例如接收者的完整地址)。
>>> class MailItem(object):
... def __init__(self, receiver_name):
... self.receiver_name = receiver_name
...
>>> m = MailItem('Pyderman')
>>> m.receiver_name
'Pyderman'
这似乎工作正常。但是,我们的 MailItem 太不明确了。如果元素是包裹怎么办?那么我们当然会关心它的重量。另一方面,如果元素是明信片,重量就无关紧要了。让我们为包创建一个名为 Package 的子类,它继承自 MailItem。每个 Package 对象是一个 MailItem,但它会存储有关其重量的额外信息。
>>> class Package(MailItem):
... def __init__(self, receiver_name, weight):
... # treat the package as a MailItem and call the MailItem initializier
... super(Package, self).__init__(receiver_name)
... # store extra information about the weight in some arbitrary unit
... self.weight = weight
当我们实例化一个Package时,我们做的第一件事就是调用MailItem的初始化器,因为每个Package也是一个邮件项目。这不会创建另一个 MailItem 对象,而是在我们新的 Package 对象上调用 MailItem 的 __init__ 方法。在此示例中,我们可以通过将 self.receiver_name = receiver_name 行从 MailItem 的初始化程序复制到 Package 的初始化程序来实现相同的目的> 而不是使用 super,但那将是重复的代码并且违背了 Dont-Repeat-Yourself 原则。
让我们实例化一个 Package 以查看工作中的代码。
>>> p = Package('Pyderman', 200)
>>> p.receiver_name
'Pyderman'
>>> p.weight
200
如您所见,对象 p 确实有一个 receiver_name,因为 Package 的初始化程序调用了 MailItem 初始化器通过
super(Package, self).__init__(receiver_name).
冒着重复的风险,让一件事变得清晰: 我们只使用 p = Package('Pyderman', 200) 创建一个 Package 对象,而不是创建一个额外的 MailItem 对象。每个 Package 对象是一个 MailItem,Python 会告诉你:
>>> isinstance(p, MailItem)
True
当然,每个Package也是一个Package。
>>> isinstance(p, Package)
True
但是,并非每个 MailItem 都是一个 Package:
>>> m = MailItem('Pyderman')
>>> isinstance(m, Package)
False
这样想:每只鳄鱼都是爬行动物,但并非每只爬行动物都是鳄鱼。
