[英]Grandchild inheriting from Parent class - Python
我正在学习所有关于Python类的知识,并且我有很多理由可以覆盖。 我遇到了一个让我有点困惑的例子。
这些是父类
Class X
Class Y
Class Z
儿童班是:
Class A (X,Y)
Class B (Y,Z)
孙子课是:
Class M (A,B,Z)
Class M
Class Z
是否通过继承Class B
Class M
继承Class Z
Class B
或者这种结构的原因是什么? Class M
会忽略第二次Class Z
继承不会,或者我错过了什么?
M类只会继承Z类属性两次 (冗余)不会,或者我错过了什么?
不,没有“重复”属性,Python执行线性化,他们可以按照方法解决顺序(MRO) ,例如, 这里解释。 然而,你是正确的,在这里添加Z
到列表不会改变任何东西。
他们首先为父母建造MRO,所以:
MRO(X) = (X,object)
MRO(Y) = (Y,object)
MRO(Z) = (Z,object)
MRO(A) = (A,X,Y,object)
MRO(B) = (B,Y,Z,object)
然后他们通过合并为M
构建MRO:
MRO(M) = (M,)+merge((A,X,Y,object),(B,Y,Z,object),(Z,object))
= (M,A,X,B,Y,Z,object)
现在,每次调用方法时,Python都会首先检查属性是否在该对象的内部字典self.__dict__
中 。 如果没有,Python将遍历MRO并尝试查找具有该名称的属性。 从找到它的那一刻起,它就会停止搜索。
最后, super()
是一个代理对象,它执行相同的分辨率,但是在类的阶段在MRO中启动。 所以在这种情况下,如果你有:
class B:
def foo():
super().bar()
你构造一个对象m = M()
并调用m.foo()
然后 - 如果调用B
的foo()
, super().bar
将首先尝试在Y
找到一个bar
,如果失败,它将在Z
查找一个bar
,最后在object
查找。
属性不会继承两次。 如果添加如下属性:
self.qux = 1425
然后它被简单地添加到该对象的内部self.__dict__
字典中。
然而,明确地陈述Z
可能是有益的:如果B
的设计者不确定Z
是否是真正的要求。 在这种情况下,如果B
被改变,你肯定知道Z
仍然会在MRO中。
除了@Willem提到的,我想补充一点,你在谈论多重继承问题。 对于python,与Java等其他语言相比,对象实例化有点不同。 这里,对象实例分为两部分: - 对象创建(使用__new__
方法)和对象初始化(使用__init__
方法)。 而且,子类不一定总是具有父类的属性。 只有从子类(显式)调用父类构造函数时,Child类才会获取父类的属性。
>>> class A(object):
def __init__(self):
self.a = 23
>>> class B(A):
def __init__(self):
self.b = 33
>>> class C(A):
def __init__(self):
self.c = 44
super(C, self).__init__()
>>> a = A()
>>> b = B()
>>> c = C()
>>> print (a.a) 23
>>> print (b.a) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'B' object has no attribute 'a'
>>> print (c.a) 23
在上面的代码剪辑中,B没有调用A的__init__
方法,因此它没有as成员变量,尽管它继承自A类。 同样的事情不是像Java这样的语言,其中有一个固定的属性模板,一个类将具有。 这就是python与其他语言的不同之处。
对象具有的属性存储在对象的__dict__
成员中,它是对象类中的__getattribute__
魔术方法,它根据willem指定的mro实现属性查找。 您可以使用vars()和dir()方法来实例内省。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.