【发布时间】:2010-10-28 14:09:51
【问题描述】:
考虑一下 - 基类 A,类 B 继承自 A,类 C 继承自 B。在初始化程序中调用父类初始化程序的通用方法是什么?如果这听起来仍然太模糊,这里有一些代码。
class A(object):
def __init__(self):
print "Initialiser A was called"
class B(A):
def __init__(self):
super(B,self).__init__()
print "Initialiser B was called"
class C(B):
def __init__(self):
super(C,self).__init__()
print "Initialiser C was called"
c = C()
这就是我现在的做法。但它似乎仍然有点过于非泛型 - 你仍然必须手动传递正确的类型。
现在,我尝试使用self.__class__ 作为 super() 的第一个参数,但是,显然它不起作用 - 如果你把它放在 C 的初始化器中 - 很公平,B 的初始化器会被调用。如果你在 B 中做同样的事情,“self”仍然指向 C 的一个实例,所以你最终会再次调用 B 的初始化程序(这会以无限递归结束)。
暂时不需要考虑钻石继承,我只是对解决这个特定问题感兴趣。
【问题讨论】:
-
“但它似乎还是有点太不通用了——你仍然必须手动传递一个正确的类型。”??您将类名传递给 super()。你永远不需要知道超类或其他任何东西。这是如何非通用的?它会产生什么问题?你能举个例子吗?
-
如果满了,我还没准备好回答这个问题。但是无论如何,如果类被重命名怎么办?如果我想编写一个装饰器函数来自动化这种链接怎么办?现在我明白了,这是不可能的,但在提出这个问题时我并不知道。
-
@shylent,如果我理解你的问题,你的描述是可能的。如果您了解 mro,则可以使用 super() 使父引用完全通用。谷歌“python super is super”,观看视频。
-
@shylent 实际上,再次阅读您的问题我相信您正在经历的无限递归并不是您认为的那样。我相信 mro 订单会让你调用一个你不打算调用的构造函数。不久前,我自己也处理过同样的事情。无论你传递给 super 的第一个参数什么,super 都会调用 mro 中的第一个构造函数,而不是你传入的类型。例如,如果你在 C 的构造函数中调用 super(self.__class__, self),你会仍然调用 B 的构造函数,因为它是 mro 中的第一个父级。
标签: python oop inheritance constructor