根据Learn Python The Hard Way ex44以及super()
与__init__
的使用说明:
class Child(object):
def __init__(self, stuff):
self.stuff = stuff
super(Child, self).__init__()
这与上面的
进行初始化Child.altered
示例非常相似, 除了我在__init__
之前设置一些变量之前Parent
使用Parent.__init__.
因此实例化Child
也会导致Parent
的实例化。但是这个实例化是什么/在哪里?给出:
c = Child()
where {什么是Parent
对象?
答案 0 :(得分:3)
super(Child, self)
为您提供self
指向的对象作为Child
的父类的实例(Parent
)。
在__init__
的{{1}}方法中,您首先要做一些事情(Child
),然后在您的self.stuff = stuff
上调用__init__
方法Parent
指向的Child
对象!
您没有明确地实例化self
对象,但由于继承,每个Parent
都是 Child
。
@timgeb一个实用的例子,或以这种方式使用super()的理由会有所帮助。
当然,让我们看一个简单的例子。我们假设您正在构建邮政服务申请表。该服务提供多种物品,如包裹,信件或明信片。每个项目共享一些属性。为了简单起见,让我们说他们共享接收者的名字(在现实世界的应用程序中,你可能需要更多属性,例如接收者的完整地址)。
Parent
这似乎工作正常。但是,我们的>>> class MailItem(object):
... def __init__(self, receiver_name):
... self.receiver_name = receiver_name
...
>>> m = MailItem('Pyderman')
>>> m.receiver_name
'Pyderman'
太过不明确了。如果物品是包裹怎么办?然后我们肯定会关心它的重量。另一方面,如果物品是明信片,则重量将无关紧要。让我们为名为MailItem
的包创建一个子类,该类继承自Package
。每个MailItem
对象都是-a 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
对象,而是在我们的新MailItem
对象上调用__init__
MailItem
方法。在此示例中,我们可以通过将Package
的初始化程序中的行self.receiver_name = receiver_name
复制到MailItem
的初始化程序而不是使用Package
来实现相同的目的,但这样做会是重复的代码,反对不要重复自己的原则。
让我们实例化super
以查看正在运行的代码。
Package
正如您所看到的,对象>>> p = Package('Pyderman', 200)
>>> p.receiver_name
'Pyderman'
>>> p.weight
200
确实有p
,因为receiver_name
的初始化程序通过Package
调用MailItem
初始化程序}。
冒着重复自己的风险,让事情变得清晰:
我们只使用super(Package, self).__init__(receiver_name)
创建一个Package
对象,而不是另外的p = Package('Pyderman', 200)
个对象。每个MailItem
对象都是-a Package
,Python会告诉您:
MailItem
当然,每个>>> isinstance(p, MailItem)
True
也是Package
。
Package
但是,并非每个>>> isinstance(p, Package)
True
都是-a MailItem
:
Package
以这种方式思考:每只鳄鱼都是爬行动物,但不是每只爬行动物都是鳄鱼。
答案 1 :(得分:2)
没有实例化,初始化 - 仔细阅读你引用的段落,你会看到它只提到后者。初始化(有时在历史上也称为构造)是将空实例构建为给定类型的可用对象的过程。
Parent.__init__
会产生一个可用的Parent
对象; Child.__init__
构建于此基础上以创建可用的Child
对象。因此,每个Child
对象都是一个有效的Parent
对象。