继承

什么是继承

  继承就是新建类的一种方式,新建的类我们称为子类或者派生类;被继承的类我们称为父类或者基类,子类可以使用父类中的属性或者方法

为什么要用继承

  1、类解决了对象与对象之间的代码冗余问题

  2、继承解决的是类与类之间的代码冗余问题

如何使用继承

  1、新式类:继承了object类的子子孙孙类都是新式类

  2、经典类:没有继承了object类的子子孙孙类都是经典类

    注:经典类和新式类只有在python2中有区分,python3中只有新式类

  3、代码演示(学生选课为例)

复制代码
 1 # 父类,公共类
 2 class People():
 3     school = 'SH'
 4 
 5     def __init__(self, name, age, gender):
 6         self.name = name
 7         self.age = age
 8         self.gender = gender
 9 
10 # 学生类
11 class Student(People):
12 
13     def __init__(self, name, age, gender, course=None):
14         if course is None:
15             course = []
16         People.__init__(self, name, age, gender)
17         self.courses = course
18 
19     def choose_course(self, course):
20         self.courses.append(course)
21         print('%s 选课成功 %s' % (self.name, self.courses))
22 
23 
24 stu = Student('tony', 19, 'male')
25 
26 # teacher类
27 class Teacher(People):
28 
29     def __init__(self, name, age, gender, level):
30         self.level = level
31         People.__init__(self, name, age, gender)
32 
33     def score(self, stu_obj, score):
34         stu_obj.score = score  # 给学生打分
35         print('%s给%s打了%s分' % (self.name, stu_obj.name, score))
36 
37 
38 tea = Teacher('tom', 19, 'male', 10)
39 print(tea.name)
40 print(tea.level)
复制代码

单继承下属性查找

  1、代码练习

复制代码
class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        #
        print('Foo.f2')
        self.f1()


class Bar(Foo):
    def f1(self):
        print('Bar.f1')


obj = Bar()  # {}
obj.f2()
# 结果
# Foo.f2
# Bar.f1
复制代码

   2、练习

复制代码
class Foo:
    def __f1(self):  # _Foo__f1()
        print('Foo.f1')

    def f2(self):
        #
        print('Foo.f2')
        self.__f1()  # _Foo__f1()


class Bar(Foo):
    def __f1(self):  # # _Bar__f1()
        print('Bar.f1')


obj = Bar()  # {}
obj.f2()
复制代码

多继承下的属性查找

  1、新式类中是按照广度优先查找

   2、经典类:是按照深度优先查找

    3、练习

复制代码
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()
复制代码

super()和mro()列表

  super()使用

复制代码
class People():
    school = 'SH'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
        
class Teacher(People):

    def __init__(self, name, age, gender, level):
        self.level = level
        super().__init__(name, age, gender)
复制代码

  mro()列表

    练习1

复制代码
class A:
    def test(self):
        print('from A.test')
        super().test()


class B:
    def test(self):
        print('from B')


class C(A, B):
    pass


c = C()
c.test()
复制代码

    练习2

复制代码
class B:
    def test(self):
        print('B---->test')

    def aaa(self):
        print('B---->aaa')

class A:
    def test(self):
        print('A---->test')
        super().aaa()


class C(A, B):
    def aaa(self):
        print('C----->aaa')


c = A()
# c.test()  
print(A.mro())
复制代码

  注:当你使用super()函数时,Python会在MRO列表上继续搜索下一个类。只要每个重定义的方法统一使用super()并只调用它一次,那么控制流最终会遍历完整个MRO列表,每个方法也只会被调用一次(注意注意注意:使用super调用的所有属性,都是从MRO列表当前的位置往后找,千万不要通过看代码去找继承关系,一定要看MRO列表)

继承原理

  python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:

    1.子类会先于父类被检查

    2.多个父类会根据它们在列表中的顺序被检查

    3.如果对下一个类存在两个合法的选择,选择第一个父类

父类限制子类的行为

class Animal():
    def speak(self):
        raise Exception('必须实现speak')
 
class People(Animal):
    def speak(self):
        pass

 

posted @   那就凑个整吧  阅读(58)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示