Class 通过带有两个参数的 super 继承
Class inheritance via super with two arguments
在下面的代码中,我用数字替换了 args 以演示 类 是继承的。
class Animal:
def __init__(self, animalName):
print(animalName, 'is an animal.');
class Mammal(Animal):
def __init__(self, mammalName):
print(mammalName, 'is a mammal.')
super().__init__(mammalName)
class CannotFly(Mammal):
def __init__(self, mammalThatCantFly):
print('2', "cannot fly.")
super().__init__('2')
class CannotSwim(Mammal):
def __init__(self, mammalThatCantSwim):
print('1', "cannot swim.")
super().__init__('1')
# Cat inherits CannotSwim and CannotFly
class Cat(CannotSwim, CannotFly):
def __init__(self):
print('I am a cat.');
super().__init__('Cat')
cat = Cat()
returns
I am a cat.
1 cannot swim.
2 cannot fly.
2 is a mammal.
2 is an animal.
为什么不是下面的?
I am a cat.
1 cannot swim.
1 is a mammal.
1 is an animal.
2 cannot fly.
2 is a mammal.
2 is an animal.
实际上有两个调用流,不是吗?
看看这个postWhat does 'super' do in Python? - difference between super().__init__() and explicit superclass __init__()
现在它说的是实例的 mro 中的每个 class 都会调用 __init__
。
您可以通过执行 print(Cat.__mro__)
来打印它,这将打印出
(<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>)
如您所见,存在调用顺序。现在,为什么使用“2”而不是“1”,请参阅 hussic
评论中的答案
您可以看到 Cat
的方法解析顺序 (MRO):
>>> Cat.mro()
[<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>]
由于 C3 linearization algorithm,每个 class 在 MRO 中出现 一次 。简而言之,这使用一些简单的规则从继承图中构造了 MRO:
- 图中每个 class 出现一次。
- 每个 class 在其任何 parent class 之前。
- 当一个 class 有两个 parent 时,将保留 parent 的 left-to-right 顺序。
(“线性化”,因为它产生了继承图中节点的线性排序。)
super()
命名错误;更好的名字应该是谎言 nextclass
,因为它 而不是 使用当前 class 的 parent 列表,但是 MRO self
参数。当您呼叫 Cat
时,您会看到以下呼叫。
Cat.__init__
Cat.__init__
使用 super
调用 CannotSwim.__init__
CannotSwim.__init__
使用 super
调用 CannotFly.__init__
CannotFly.__init__
使用 super
调用 Mammal.__init__
Mammal.__init__
使用 super
调用 Animal.__init__
Animal.__init__
使用 super
调用 object.__init__
object.__init__
不使用 super
(它“拥有”__init__
),所以链到此结束。
特别注意 #3:CannotSwim
会导致使用继承图中的“兄弟”,而不是它自己的 parent。
在下面的代码中,我用数字替换了 args 以演示 类 是继承的。
class Animal:
def __init__(self, animalName):
print(animalName, 'is an animal.');
class Mammal(Animal):
def __init__(self, mammalName):
print(mammalName, 'is a mammal.')
super().__init__(mammalName)
class CannotFly(Mammal):
def __init__(self, mammalThatCantFly):
print('2', "cannot fly.")
super().__init__('2')
class CannotSwim(Mammal):
def __init__(self, mammalThatCantSwim):
print('1', "cannot swim.")
super().__init__('1')
# Cat inherits CannotSwim and CannotFly
class Cat(CannotSwim, CannotFly):
def __init__(self):
print('I am a cat.');
super().__init__('Cat')
cat = Cat()
returns
I am a cat.
1 cannot swim.
2 cannot fly.
2 is a mammal.
2 is an animal.
为什么不是下面的?
I am a cat.
1 cannot swim.
1 is a mammal.
1 is an animal.
2 cannot fly.
2 is a mammal.
2 is an animal.
实际上有两个调用流,不是吗?
看看这个postWhat does 'super' do in Python? - difference between super().__init__() and explicit superclass __init__()
现在它说的是实例的 mro 中的每个 class 都会调用 __init__
。
您可以通过执行 print(Cat.__mro__)
来打印它,这将打印出
(<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>)
如您所见,存在调用顺序。现在,为什么使用“2”而不是“1”,请参阅 hussic
评论中的答案您可以看到 Cat
的方法解析顺序 (MRO):
>>> Cat.mro()
[<class '__main__.Cat'>, <class '__main__.CannotSwim'>, <class '__main__.CannotFly'>, <class '__main__.Mammal'>, <class '__main__.Animal'>, <class 'object'>]
由于 C3 linearization algorithm,每个 class 在 MRO 中出现 一次 。简而言之,这使用一些简单的规则从继承图中构造了 MRO:
- 图中每个 class 出现一次。
- 每个 class 在其任何 parent class 之前。
- 当一个 class 有两个 parent 时,将保留 parent 的 left-to-right 顺序。
(“线性化”,因为它产生了继承图中节点的线性排序。)
super()
命名错误;更好的名字应该是谎言 nextclass
,因为它 而不是 使用当前 class 的 parent 列表,但是 MRO self
参数。当您呼叫 Cat
时,您会看到以下呼叫。
Cat.__init__
Cat.__init__
使用super
调用CannotSwim.__init__
CannotSwim.__init__
使用super
调用CannotFly.__init__
CannotFly.__init__
使用super
调用Mammal.__init__
Mammal.__init__
使用super
调用Animal.__init__
Animal.__init__
使用super
调用object.__init__
object.__init__
不使用 super
(它“拥有”__init__
),所以链到此结束。
特别注意 #3:CannotSwim
会导致使用继承图中的“兄弟”,而不是它自己的 parent。