44.Python 类的继承

1.继承

1.1简述

ps:类是解决对象与对象之间的代码冗余.

继承:是解决类与类之间的代码冗余,将类中重复的代码提取出来将一个新的类(父类),
让需要使用和这个代码的类(子类)去继承父类.

1.2派生

派生:子类继承父类的属性,派生出自己都有的属性.
子类被称为派生类.
父类可以称为基类或超类.
父类中的数据,子类完全继承.

1.3单/多继承

单继承: 继承一个父类
多继承: 继承多个父类

1.4.查看继承关系

查看类继承了哪些类
类名.__base__  查看单继承 , 看多继承只显示一个
类名.__bases__ 查看多继承 , 能看单继承

2.提取父类

提取类与类之间的相同数据,得出一个类,然后去继承这个类.
在类名后的括号内写上继承的名称. eg: 类名(继承谁就写谁的名字)

对象可以得到类的所有属性,子类可以继承父类的所有的属性.
子类中没有定义__init__方法, 但是会从父类中找__init__方法,找到变初始化数据.

2.1实例

# 学校类
class School:
    school = 'XXX'

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

        
# 学生类
class Student(School):
    pass


# 教师类
class Teacher(School):
    pass


stu1 = Student('kid', 18, 'male')
tea1 = Teacher('xx', 30, 'male')
print(stu1.__dict__)
print(tea1.__dict__)
print(stu1.school)
print(tea1.school)
"""
{'name': 'kid', 'age': 18, 'gender': 'male'}
{'name': 'xx', 'age': 30, 'gender': 'male'}
XXX
XXX
"""

image-20211206192139369

image-20211206162222609

2.2查看继承

# 城市类
class City():
    addr = 'xxx'


# 学校类
class School():
    school = 'xxx'
    identity = 'Student'


# 学生类
class Student(School, City):
    pass


# 老师类
class Teacher(School, City):
    pass


# 查看多继承
print(Student.__bases__)  # (<class '__main__.School'>, <class '__main__.City'>)
print(Teacher.__bases__)  # (<class '__main__.School'>, <class '__main__.City'>)
# 城市类
class City():
    addr = 'xxx'


# 学校类
class School():
    school = 'xxx'
    identity = 'Student'


# 学生类
class Student(School, City):
    pass


# 老师类
class Teacher(School):
    pass


# __base__ 看多继承只能看一个  __bases__ 看单继承 只有一个
print(Student.__base__)  # <class '__main__.School'>
print(Teacher.__bases__)  # (<class '__main__.School'>,)

3.新式类/经典类

Python3 :
新式类: 继承object类的子类, 以及该类的子类,子子类。
经典类: 没有继承 object类的子类, 以及该类的子类,子子类。

Python2 :
不区分新式类与经典类.

Python 3 没有任何继承任何类,那么会默认继承object类, 所有都是新式类.
object类: Python内置的类, 存放了一些常用的功能.
# 城市类
class City():
    addr = 'xxx'


# python 3.6 解释器
print(City.__base__)  # <class 'object'>
* Python2 中没有.__base__
# ***  coding=utf8 ***
# 城市类
class City():
    addr = 'xxx'


# python 2.7 解释器
print(City.__bases__)  # ()

4.继承属性查找顺序

4.1单继承

对象先从自己的.__dict__中查找,找不到,再去子类中查找,还没有去父类中找.父类中没有就去object中查找,都没有就会报错.
class A:
    # def a(self):
    #     print('from A ---> a')
    #
    # def b(self):
    #     print('from A ---> b')
    pass

class B(A):
    # def a(self):
    #     print('from B ---> a')
    #
    # def b(self):
    #     print('from B ---> b')
    pass


class C(B):
    # def a(self):
    #     print('from C ---> a')
    #
    # def b(self):
    #     print('from C ---> b')
    pass

class D(C):
    pass


obj = D()
obj.a()  # from A ---> a  AttributeError: 'D' object has no attribute 'a' 报错
obj.b()  # from A ---> b

image-20211206194640903

4.2多继承查找

经典类:多继承情况下,会按照深度优先查找
新式类:多继承情况下,会按照广度优先查找

4.3菱形问题

一个类可以继承多个父类.

* 菱形问题
基类A 被父类B  父类C继承
子类继承 父类B 父类C
class A:
    pass


class B(A):
    pass


class C(A):
    pass


class D(B, C):
    pass

img

Python 解决方案:
每定义一个类,Python都会计算出一个所有基类的线性MRO列表,
继承的查找顺序按列表的顺序从左往右查找.

Python3中新式类 内置mro方法.
查询某个类的继承查找顺序,就以那个类为起点展开这个列表.
使用:
类名.__mor__
类名.mro()
Python2没有.mro() 方法

子类会优先父类被检测到(子子类>子类>父类>基类),多个父类会依据它们在列表中的顺序查找.
class A:
    pass


class B(A):
    pass


class C(A):
    pass


class D(B, C):
    pass
    
    
print(D.mro())
print(D.__mro__)

"""
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 列表
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) 元组
"""

4.3深度优先

经典类:按深度优先的方式查找,条分支找到底,
找完一条之后,再查另一条分支.

Python2       B(E)   E(G)               分支直接查到G()
A(B, C, D)    C(F)   F(G)      G()      G()没有就放回其他分支...G()则不咋再查找
              D(G)                      
# Python2
class G:
    def text(self):
        print 1
    pass


class F(G):
    def text(self):
        print 2
    pass


class E(G):
    # def text(self):
    #     print 3
    pass


class B(E):
    # def text(self):
    #     print 4
    pass


class C(F):
    def text(self):
        print 5
    pass


class D(G):
    def text(self):
        print 6
    pass


class A(B, C, D):
    # def text(self):
    #     print 7
    pass


obj = A()
obj.text()

4.4广度优先

新式类按广度优先方式查找.

广度优点按mro列表的顺序镜像查找.
检索第一条分支的之后不会访问到底, 
之后在检索第二条分支,
当分支都被检测完之后,在查找所有分支的同一个基类.

Python3       B(E)   E(G)               分支直接查到E()
A(B, C, D)    C(F)   F(G)      G()      E()没有就放回其他分支...
              D(G)                      最后在找G()     
# python2.7下测试
class G():
    # def test(self):          # 4
    #     print('from G')
    pass

class F(G):
    # def test(self):          # 3
    #     print('from F')
    pass

class E(G):
    # def test(self):          # 2
    #     print('from E')
    pass

class B(E):
    # def test(self):
    #     print('from B')      # 1
    pass

class C(F):
    # def test(self):          # 5
    #     print('from C')
    pass

class D(G):                  
    def test(self):             # 6
         print('from D')
    
class A(B, C, D):
    pass

obj = A()
obj.test()
# Python 3.8
print(A.mro())
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]

5.Pyton Mixins机制

多继承的正确打开方式:mixins机制
mixins机制核心:就是在多继承的背景下尽可能地提升多继承的可读性

Mixins机制机制指的是子类混合了不同类的属性和功能,而这些属性和功能统一命名规范。区分主类和辅类。
继承辅类的位置在主类的左边.(辅类1, 辅类2,主类)
辅类命名以Mixin,able,ible结尾。

主类只有一个,辅类可以有很多个.
主类中:
功能可以用很多个
辅类中:
一个辅类可能只有一个功能
# 交通工具
class Vehicle:
    def run(self):
        pass


# 飞行功能 辅类
class FlyMixin():
    def fly(self):
        '''
        飞行功能相应的代码
        '''
        print("I am flying")


class CivilAircraft(FlyMixin,  Vehicle):  # 民航飞机
    pass


class Helicopter(FlyMixin, Vehicle):  # 直升飞机
    pass


class Car(Vehicle):  # 汽车并不会飞,如果不设置辅类,汽车也能飞了
    pass

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/121754828
今日推荐