孙子继承自 Parent class - Python
Grandchild inheriting from Parent class - Python
我正在学习有关 Python classes 的所有知识,而且我有很多基础知识要涵盖。
我遇到了一个让我有点困惑的例子。
这些是 parent classes
Class X
Class Y
Class Z
Child class是:
Class A (X,Y)
Class B (Y,Z)
孙子 class 是:
Class M (A,B,Z)
难道Class M
不是通过继承Class B
来继承Class Z
吗,或者为什么会出现这种结构? Class M
会忽略第二次 Class Z
是继承的,不是吗,还是我遗漏了什么?
Class M would just inherit the Class Z attributes twice (redundant) wouldn't it be, or am I missing something?
不,没有 "duplicated" 属性,Python 执行 线性化 他们可以 方法解析顺序 (MRO) 原样,例如,解释 。但是你是对的,这里添加 Z
到列表不会改变任何东西。
他们首先为 parents 构建 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会先检查该属性是否在那个object)[=59的内部字典self.__dict__
中=].否则,Python 将 遍历 MRO 并尝试查找具有该名称的属性。从找到的那一刻起,它就会停止搜索。
最后 super()
是一个 proxy-object,它执行相同的分辨率,但在 class 阶段开始于 MRO。所以在这种情况下,如果你有:
class B:
def foo():
super().bar()
然后你构建一个 object m = M()
并调用 m.foo()
然后 - 如果调用 B
的 foo()
,super().bar
将首先尝试在 Y
中查找 bar
,如果失败,它将在 Z
中查找 bar
,最后在 object
.[=36= 中查找]
属性未继承两次。如果您添加如下属性:
self.qux = 1425
然后它被简单地添加到 object 的内部 self.__dict__
字典中。
然而,明确说明 Z
可能是有益的:如果 B
的设计者不确定 Z
是否是真正的要求。在那种情况下,如果 B
被更改,您肯定知道 Z
仍将在 MRO 中。
除了@Willem 提到的,我想补充一点,你说的是多重继承问题。对于 python,对象实例化与 Java 等其他语言相比有点不同。这里,对象实例化分为两部分:- 对象创建(使用 __new__
方法)和对象初始化(使用 __init__
方法)。此外,子 class 不一定总是具有父 class 的属性。子 class 获取父 class 的属性,仅当从子 class(显式)调用父 class 构造函数时。
>>> 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__
方法,因此它没有 a as 成员变量,尽管它继承自 A class。对于像 Java 这样的语言,情况并非如此,其中有一个固定的属性模板,而 class 将具有。这就是 python 与其他语言的不同之处。
对象拥有的属性,存储在对象的__dict__
成员中,它是对象class中的__getattribute__
魔术方法,根据实现属性查找mro 由 willem 指定。您可以使用 vars() 和 dir() 方法来自省实例。
我正在学习有关 Python classes 的所有知识,而且我有很多基础知识要涵盖。 我遇到了一个让我有点困惑的例子。
这些是 parent classes
Class X
Class Y
Class Z
Child class是:
Class A (X,Y)
Class B (Y,Z)
孙子 class 是:
Class M (A,B,Z)
难道Class M
不是通过继承Class B
来继承Class Z
吗,或者为什么会出现这种结构? Class M
会忽略第二次 Class Z
是继承的,不是吗,还是我遗漏了什么?
Class M would just inherit the Class Z attributes twice (redundant) wouldn't it be, or am I missing something?
不,没有 "duplicated" 属性,Python 执行 线性化 他们可以 方法解析顺序 (MRO) 原样,例如,解释 Z
到列表不会改变任何东西。
他们首先为 parents 构建 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会先检查该属性是否在那个object)[=59的内部字典self.__dict__
中=].否则,Python 将 遍历 MRO 并尝试查找具有该名称的属性。从找到的那一刻起,它就会停止搜索。
最后 super()
是一个 proxy-object,它执行相同的分辨率,但在 class 阶段开始于 MRO。所以在这种情况下,如果你有:
class B:
def foo():
super().bar()
然后你构建一个 object m = M()
并调用 m.foo()
然后 - 如果调用 B
的 foo()
,super().bar
将首先尝试在 Y
中查找 bar
,如果失败,它将在 Z
中查找 bar
,最后在 object
.[=36= 中查找]
属性未继承两次。如果您添加如下属性:
self.qux = 1425
然后它被简单地添加到 object 的内部 self.__dict__
字典中。
然而,明确说明 Z
可能是有益的:如果 B
的设计者不确定 Z
是否是真正的要求。在那种情况下,如果 B
被更改,您肯定知道 Z
仍将在 MRO 中。
除了@Willem 提到的,我想补充一点,你说的是多重继承问题。对于 python,对象实例化与 Java 等其他语言相比有点不同。这里,对象实例化分为两部分:- 对象创建(使用 __new__
方法)和对象初始化(使用 __init__
方法)。此外,子 class 不一定总是具有父 class 的属性。子 class 获取父 class 的属性,仅当从子 class(显式)调用父 class 构造函数时。
>>> 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__
方法,因此它没有 a as 成员变量,尽管它继承自 A class。对于像 Java 这样的语言,情况并非如此,其中有一个固定的属性模板,而 class 将具有。这就是 python 与其他语言的不同之处。
对象拥有的属性,存储在对象的__dict__
成员中,它是对象class中的__getattribute__
魔术方法,根据实现属性查找mro 由 willem 指定。您可以使用 vars() 和 dir() 方法来自省实例。