目录
class Horse:
def __init__(self, name):
self.name = name
def show_info(self):
return "马的名字{0}".format(self.name)
def run(self):
print("马跑了.....")
class Donkey:
def __init__(self, name):
self.name = name
def show_info(self):
return f"驴的名字{self.name}"
def run(self):
print("驴跑了.....")
def roll(self):
print("驴打滚......")
# 继承的优先级是从左到右,私有变量无法继承
class Musle(Horse, Donkey):
def __init__(self, name, age):
super().__init__(name)
self.age = age
m = Musle("小驴", 3)
m.run()
m.roll()
print(m.show_info())
代码解释
1. 类的定义
-
Horse
类__init__
方法:这是构造函数,当创建Horse
类的实例时,会接收一个参数name
,并将其赋值给实例变量self.name
,用于表示马的名字。show_info
方法:使用str.format()
方法返回一个格式化的字符串,其中包含马的名字。run
方法:打印一条信息,表示马正在奔跑。
-
Donkey
类__init__
方法:同样是构造函数,接收一个参数name
,并将其赋值给实例变量self.name
,用于表示驴的名字。show_info
方法:使用 f - 字符串返回一个包含驴名字的字符串。run
方法:打印一条信息,表示驴正在奔跑。roll
方法:打印一条信息,表示驴正在打滚。
-
Musle
类- 继承关系:
Musle
类继承自Horse
和Donkey
,这是多继承的体现。在 Python 中,多继承时,继承顺序从左到右,即Horse
的优先级高于Donkey
。 __init__
方法:调用super().__init__(name)
来调用父类的构造函数。由于继承顺序,这里调用的是Horse
类的__init__
方法来初始化name
属性。同时,为Musle
类的实例添加了一个新的属性self.age
,用于表示骡子的年龄。
- 继承关系:
2. 实例化与方法调用
m = Musle("小驴", 3)
:创建Musle
类的一个实例m
,名字为"小驴"
,年龄为3
。m.run()
:Musle
类本身没有定义run
方法,Python 会按照继承顺序查找。由于Horse
类在Donkey
类之前,所以会调用Horse
类的run
方法,输出马跑了.....
。m.roll()
:Horse
类中没有roll
方法,Python 会继续在Donkey
类中查找,因此调用Donkey
类的roll
方法,输出驴打滚......
。print(m.show_info())
:Musle
类没有定义show_info
方法,按照继承顺序,会调用Horse
类的show_info
方法,输出马的名字小驴
。
同类案例及结果输出
class Bird:
def __init__(self, name):
self.name = name
def show_info(self):
return f"鸟的名字是 {self.name}"
def fly(self):
print(f"{self.name} 在空中飞翔")
class Fish:
def __init__(self, name):
self.name = name
def show_info(self):
return f"鱼的名字是 {self.name}"
def swim(self):
print(f"{self.name} 在水里游动")
class FlyingFish(Bird, Fish):
def __init__(self, name, color):
super().__init__(name)
self.color = color
# 创建实例
ff = FlyingFish("小飞", "银色")
# 调用方法
ff.fly()
ff.swim()
print(ff.show_info())
输出结果
小飞 在空中飞翔
小飞 在水里游动
鸟的名字是 小飞
案例解释
Bird
类:定义了鸟的基本属性和行为,包括名字和飞翔的能力。Fish
类:定义了鱼的基本属性和行为,包括名字和游泳的能力。FlyingFish
类:继承自Bird
和Fish
,表示飞鱼。在__init__
方法中,调用super().__init__(name)
初始化名字,并添加了color
属性。- 方法调用:
ff.fly()
:调用Bird
类的fly
方法,输出小飞 在空中飞翔
。ff.swim()
:Bird
类中没有swim
方法,调用Fish
类的swim
方法,输出小飞 在水里游动
。print(ff.show_info())
:按照继承顺序,调用Bird
类的show_info
方法,输出鸟的名字是 小飞
。
多继承
在 Python 中,当一个类继承多个父类且父类中有相同方法时,主要涉及多继承和方法解析顺序(MRO)的概念,以下是具体介绍:
多继承的基本语法
在 Python 中,一个类可以继承自多个父类,语法如下:
class Parent1:
def method(self):
print("Parent1's method")
class Parent2:
def method(self):
print("Parent2's method")
class Child(Parent1, Parent2):
pass
这里Child
类继承了Parent1
和Parent2
两个父类。
方法解析顺序(MRO)
当多个父类中有相同方法时,Python 使用 C3 线性化算法来确定方法解析顺序。MRO 遵循以下原则:
- 本地优先:在同一个层次中,优先查找当前类的定义,如果当前类中定义了该方法,则调用当前类的方法。
- 深度优先:从左到右依次遍历父类,并对每个父类递归地应用同样的规则。
例如:
class A:
def method(self):
print("method in class A")
class B(A):
def method(self):
print("method in class B")
class C(A):
def method(self):
print("method in class C")
class D(B, C):
pass
d = D()
d.method()
输出结果是method in class B
,因为在 MRO 中,D
类的查找顺序是D -> B -> C -> A
,所以优先调用了B
类中的方法。
super () 函数的使用
在多继承中,可以使用super()
函数来调用父类的方法,它会按照 MRO 顺序来调用父类的方法。例如:
class Parent1:
def method(self):
print("Parent1's method")
class Parent2:
def method(self):
print("Parent2's method")
class Child(Parent1, Parent2):
def method(self):
print("Child's method")
super().method()
c = Child()
c.method()
这里Child
类重写了method
方法,并在其中使用super().method()
调用了父类的method
方法,会根据 MRO 顺序调用Parent1
类的method
方法。
注意事项
- 检查 MRO:可以使用
类名.mro()
方法来查看类的 MRO 顺序,帮助理解方法调用的优先级。 - 避免复杂继承:虽然 Python 支持多继承,但过度使用多继承可能会使代码难以理解和维护,尽量保持继承关系简单清晰。
- 谨慎处理菱形继承:如果存在菱形继承(即一个类通过不同路径继承同一个类),确保所有父类的方法命名清晰,并合理使用
super()
函数来避免冲突。
多继承
在Python中,当子类继承多个父类且这些父类中存在同名方法时,方法解析顺序(MRO)决定了具体调用哪个方法。以下是详细解释和示例:
1. 方法解析顺序(MRO)
Python使用 C3线性化算法 确定继承顺序,其核心规则是:
-
子类优先于父类。
-
继承列表中靠左的父类优先于靠右的父类。
-
同一父类在继承链中只出现一次。
可以通过 类名.__mro__
或 类名.mro()
查看类的继承顺序。
2. 同名方法的继承规则
当多个父类有同名方法时,继承顺序由子类定义时父类的排列顺序决定:
-
左侧父类的方法优先调用。
-
若父类之间存在继承关系(如共同祖先),则按广度优先原则处理。
示例 1:简单多重继承
class A:
def method(self):
print("A的method")
class B:
def method(self):
print("B的method")
class C(A, B): # 继承顺序:A在左,B在右
pass
obj = C()
obj.method() # 输出:A的method(左侧父类优先)
print(C.__mro__) # 输出:(C, A, B, object)
示例 2:调整继承顺序
class C(B, A): # 继承顺序:B在左,A在右
pass
obj = C()
obj.method() # 输出:B的method
print(C.__mro__) # 输出:(C, B, A, object)
3. 父类存在共同祖先
若父类继承自同一个基类,Python会合并继承链,避免重复访问。
示例:共同祖先的 MRO
class D:
def method(self):
print("D的method")
class A(D):
def method(self):
print("A的method")
class B(D):
def method(self):
print("B的method")
class C(A, B): # 继承顺序:A -> B -> D
pass
obj = C()
obj.method() # 输出:A的method
print(C.__mro__) # 输出:(C, A, B, D, object)
4. 协作式多重继承与 super()
super()
根据 MRO 顺序依次调用父类方法,常用于实现协作式继承。
示例:super()
的链式调用
class A:
def method(self):
print("A的method")
super().method() # 调用下一个类的方法
class B:
def method(self):
print("B的method")
super().method()
class C(A, B):
def method(self):
print("C的method")
super().method()
obj = C()
obj.method()
输出:
C的method
A的method
B的method
MRO顺序:C -> A -> B -> object
-
C
的super()
调用A
的method
。 -
A
的super()
调用B
的method
。 -
B
的super()
调用object
的方法(无输出)。
5. 总结
场景 | 规则 |
---|---|
简单多重继承 | 左侧父类的方法优先调用。 |
父类有共同祖先 | 按广度优先原则合并继承链,避免重复访问。 |
使用 super() | 按 MRO 顺序依次调用父类方法,实现协作式继承。 |
强制调用指定父类方法 | 直接通过父类名调用,如 ParentClass.method(self) 。 |
6. 最佳实践
-
明确继承顺序:通过合理排列父类顺序,控制同名方法的调用优先级。
-
避免菱形继承:减少复杂继承结构,优先使用组合替代多重继承。
-
利用
super()
:在需要协作式继承时,使用super()
保持代码灵活性。
# 强制调用右侧父类的方法(不推荐,破坏封装)
class C(A, B):
def call_b_method(self):
B.method(self) # 直接指定调用B的方法
obj = C()
obj.call_b_method() # 输出:B的method
通过理解 MRO 和 super()
的行为,可以更好地设计和管理复杂的类继承关系。