面向对象(三)继承和多态
继承
什么是继承
继承就是新建类的一种方式,新建的类我们称为子类或者派生类,被继承的类称为父类或基类。
子类可以使用父类中的属性或方法。
为什么要使用继承
类解决了对象和对象之间的代码冗余问题。
继承解决了类和类之间的代码冗余问题。
如何使用继承
在Python2中的子类存在区别:
新式类:继承了object类的子子孙孙类都是新式类。
经典类:没有继承了object类的子子孙孙类都是经典类。
类的继承
# 定义一个公共的类 class People: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # 定义一个People类的子类 class Student(People): def __init__(self, name, age, gender, course=None): if course is None: course = [] # 可使用父类中的属性或方法 People.__init__(self, name, age, gender) self.course = course def choice_course(self, course): self.course.append(course) print('%s选课%s成功' % (self.name, self.course)) stu = Student('tom', 18, 'male', 'python') print(stu.name) # 结果为tom
属性的查找顺序
单继承下的属性查找顺序
单继承的情况下属性的查找是由子类一路向上查找。
在查找时要注意参数self指的一直是调用方法的属性。
class Foo: def f1(self): print('Foo.f1') # 4.在Foo类中找到f2方法并执行 def f2(self): # 5.输出Foo.f2 print('Foo.f2') # 6.此时的self指的是obj也就是Bar类 self.f1() # 3.在Bar类中找f2方法但没找到 class Bar(Foo): # 7.执行Bar类的f1方法 def f1(self): # 8.输出Bar.f1 print('Bar.f1') # 1.调用Bar类 obj = Bar() # 2.调用f2方法 obj.f2() # 结果: # Foo.f2 # Bar.f1
多继承下的属性查找顺序
经典类:按照深度优先的查找顺序。
在多继承时,经典类会一次性查到底,然后才去第二个父类找。
新式类:按照广度优先的查找顺序。
在多继承时,新式类在查到继承object类的父类时会先不查,直到没有其他父类才会去查询。

class A(object): def test(self): print('from A') class B(A): # def test(self): # print('from B') pass class C(A): # def test(self): # print('from C') pass class D(B): # def test(self): # print('from D') pass class E(C): # def test(self): # print('from E') pass class F(D, E): # def test(self): # print('from F') pass f1 = F() f1.test() # 经典类顺序F->D->B->A->E->C # 新型类顺序F->D->B->E->C->A
super()和mro列表
super()方法提供了除了指名道姓外另一种从父类中调用属性的方式。
# 定义一个公共的类 class People: def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender # 定义一个People类的子类 class Student(People): def __init__(self, name, age, gender, course=None): if course is None: course = [] # 可使用父类中的属性或方法 # People.__init__(self, name, age, gender) # super()方法在Python2中相当于super(People,self) # 可直接将自己传入,不用再写self super().__init__(name, age, gender) self.course = course def choice_course(self, course): self.course.append(course) print('%s选课%s成功' % (self.name, self.course)) stu = Student('tom', 18, 'male', 'python') print(stu.name) # 结果为tom
super()方法的查询顺序是按照mor列表从左到右的顺序进行查找。
因此即使没有明显的继承关系,使用super()方法依然可以找到。
class A: # 4.A中有text开始调用 def test(self): print('from A.test') # 5.super方法调用text,即使A并没有父类,也会按照mor列表顺序去B中找 super().test() class B: # 6.B中有text则调用 def test(self): print('from B') # 3.c中没有先去父类A中找 class C(A, B): pass # 1.实例化c c = C() # 2.查找text c.test() # 结果为 # from A.test # from B print(C.mro()) # 结果为[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>] # 因此super的查找顺序为C->A->B
多态和多态性
多态
多态指的是事物的不同形态。
在现实生活中:水的形态分为液态水、冰、水蒸气。
在电脑中:文件有多种形态:文本文件,可执行文件等。
多态性
多态性是指在不考虑实例类型的情况下使用实例。
好处是能增加文件的灵活性和可扩展性。
import abc # 抽象类: 抽象类只能被继承,不能被实例化 class Animal(metaclass=abc.ABCMeta): # 该方法已经是抽象方法了如果子类没有对应方法会直接报错 @abc.abstractmethod def speak(self): pass class People(Animal): def speak(self): print('嗷嗷嗷') class Pig(Animal): def speak(self): print('哼哼哼') class Dog(Animal): def speak(self): print('汪汪汪') obj = People() obj1 = Pig() obj2 = Dog() # 多态带来的特性:在不用考虑对象数据类型的情况下,直接调用对应的函数 def animal(animal): return animal.speak() animal(obj) animal(obj1) animal(obj2) # 结果: # 嗷嗷嗷 # 哼哼哼 # 汪汪汪
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通