我想了解下面的代码。
class Base(object):
def __init__(self):
print(self.__class__.__name__)
def handle(self):
print("Beginning handle Base")
self.template()
def template(self):
print("template of Base")
class Child(Base):
def __init__(self):
super(Child, self).__init__()
def handle(self):
print("Beginning handle Child")
super(Child, self).handle()
def template(self):
print("template of Child")
parent = Base()
child = Child()
我希望以下内容可以打印
'Base'
'Child'
所以这很好,除非我称之为:
parent.handle()
child.handle()
我希望:
"Beginning handle Base"
"template of Base"
"Beginning handle Child"
"Beginning handle Base"
"template of Base"
但我得到了
"Beginning handle Base"
"template of Base"
"Beginning handle Child"
"Beginning handle Base"
"template of Child"
为什么会这样? Base的handle函数中的self.template()不是指base的模板函数吗? super(Child, self).handle()
实际上在做什么?对我来说,似乎它正在调用它的父母的句柄,但是将自己设置为自己......
答案 0 :(得分:4)
super(type[, object-or-type])
返回将方法调用委托给父或者的代理对象 兄弟姐妹类型。这对于访问继承的方法很有用 在课堂上被覆盖的。搜索顺序与此相同 除了跳过类型本身之外,getattr()使用它。
所以在你的情况下超级(儿童,自我).handle()做下一步:
调用handle
的父Child
方法(Base
}并将Child
实例作为self
传递给该方法。
看看你的代码片段中发生了什么:
parent.handle()
// Calling handle of parent, nothing special.
// "Beginning handle Base"
// "template of Base"
child.handle()
// Calling handle of child: "Beginning handle of Child" - logged
// handle method of child calls handle method of parent: "Beginning handle Base" - logged
// handle method of Base calls template method of self which is template method of Child as self passed to super as second parameter.: "template of Child" - logged
这是上面代码片段的正常行为。
答案 1 :(得分:2)
如果未明确使用super
,则会发生正常的动态查找,并始终从真实类开始。 self.template()
中的Base
来电调用template
函数调用正常的动态调度,获取Child
的{{1}},而不是template
s;假设Base
覆盖Child
,它的行为比template
提供的行为更好。如果它没有覆盖,它将获得Base
的版本。
将Base
视为仅为直接在super
结果上进行的调用而抛出链条;否则,它没有参与,并且正常查找发生(super
调用Base
就像其他任何人调用template
一样,完全不同。 <{1}}调用后传递的template
也不例外。
如果出于某种原因,self
想要阻止动态查找(因此孩子们不会在没有遇到太多麻烦的情况下改变方法),它可以做到:
Base
明确指定类,或将Base
更改为def handle(self):
print("Beginning handle Base")
Base.template(self)
以触发template
私有访问(无缝名称修改),例如
__template
即使class
创建了自己的def handle(self):
print("Beginning handle Base")
self.__template()
def __template(self):
print("template of Base")
,Child
对__template
也是私有的,如果使用__template
方法则不会被调用它(但是,Child
之外的任何人都可以毫无困难地称之为。)