当一个子类用init调用super()时,超类的对象在哪里/是什么?

2024-06-28 20:33:22 发布

您现在位置:Python中文网/ 问答频道 /正文

根据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.altered example above, except I'm setting some variables in the __init__ before having the Parent initialize with its Parent.__init__.

所以实例化Child也会导致Parent的实例化。但是这个实例化是什么/在哪里?给出:

c = Child()

Parent对象在哪里/是什么?你知道吗


Tags: the实例selfchildobjectinitlearnway
2条回答

不是实例化,初始化-仔细阅读你引用的文章,你会看到它只提到后者。初始化(有时历史上也称为构造)是将空实例构建到给定类型的可用对象中的过程。你知道吗

Parent.__init__生成可用的Parent对象;Child.__init__在此基础上创建可用的Child对象。因此,通过扩展,每个Child对象也是有效的Parent对象。你知道吗

super(Child, self)self指向的对象作为Child(即Parent)父类的实例。你知道吗

__init__Child方法中,首先要做一些事情(self.stuff = stuff),然后在self所指向的Child对象上调用__init__Parent方法!你知道吗

您没有显式地实例化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对象都是-aMailItem,但它将存储有关其权重的额外信息。你知道吗

>>> 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。这不会创建另一个MailItem对象,而是在新的Package对象上调用__init__MailItem方法。在本例中,我们可以通过将self.receiver_name = receiver_name行从MailItem的初始值设定项复制到Package的初始值设定项而不是使用super来实现相同的效果,但这将是重复的代码,并且违背了don Repeat Yourself原则。你知道吗

让我们实例化一个Package来查看工作中的代码。你知道吗

>>> p = Package('Pyderman', 200)
>>> p.receiver_name
'Pyderman'
>>> p.weight
200

如您所见,对象p确实有一个receiver_name,因为Package的初始值设定项通过
super(Package, self).__init__(receiver_name)调用MailItem初始值设定项。你知道吗

冒着重复我自己的风险,说清楚一件事: 我们只使用p = Package('Pyderman', 200)创建一个Package对象,而不是额外的MailItem对象。每个Package对象都是-aMailItem,Python会告诉您:

>>> isinstance(p, MailItem)
True

当然,每个Package也是一个Package。你知道吗

>>> isinstance(p, Package)
True

然而,并非每个MailItem都是-aPackage

>>> m = MailItem('Pyderman')
>>> isinstance(m, Package)
False

这样想吧:每只鳄鱼都是爬行动物,但不是每只爬行动物都是鳄鱼。你知道吗

相关问题 更多 >