类的继承

类的继承

一、什么是面向对象的继承?

  • 继承是一种创建新类的方式,新建的类可称为子类或者派生类,父类可称基类或者超类
  • python支持多继承,其他语言不支持多继承
  • 继承可以使得子类别具有父类别的各种属性和方法。
  • 在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。

继承的优点有哪些?

  • 增加了类的耦合性
  • 减少了重复代码
  • 减少了重复代码

多继承的缺点:

  • 违背了人的思维习惯:继承表达的是一种什么是什么的关系
  • 代码可读性会变差
  • 不推荐使用多继承,应该使用Mixins(变相的多继承)

例子

class Father:
    print('我是你的爸爸,是你的基类')

class Mother:
    print('我是你的妈妈,也是你的基类')

'''
语法:
class 类名(要继承的类名1,要继承的类名2):
    pass
'''

#单继承
class Son1(Father):
    pass

#多继承
class Son2(Father,Mother):
    pass

二、继承的分类

继承:可以分单继承,多继承

在python2x版本中存在两种类.:
  ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
  ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
python3x版本中只有一种类:
python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

object:是一个内置的类,里面包含很多功能-

三、单继承详细介绍

3.1、属性查找顺序

代码示例:

#
class A:
    def f1(self):
        print('f1')
    def f2(self):
        print('f2')
        self.f1()
#继承A类
class B(A):

    def f1(self):
        print('Bf1')
#实例化对象
obj = B()
obj.f2()
#输出
f2
Bf1
image-20200913223339637

3.2、那么怎么让3.1中self.f1调用父类的f1函数而不是调用子类的f1函数呢?

看代码:

class A:

    def f1(self):
        print('f1')

    def f2(self):
        print('f2')
        ######方法一
        A.f1(self)
        #self.f1()

class B(A):

    def f1(self):
        print('Bf1')

obj = B()
obj.f2()

四、多继承详细介绍

4.1、多继承的菱形继承

​ 大多数面向对象语言都不支持多继承,而在Python中,一个子类是可以同时继承多个父类的,这固然可以带来一个子类可以对多个不同父类加以重用的好处,但也有可能引发著名的菱形问题(或称钻石问题,有时候也被称为“死亡钻石”),菱形其实就是对下面这种继承结构的形象比喻

image-20200913230246548

出现这种问题的原因是,当B、C都继承了A(AB都重现改方法),D继承了B、C,可是D没有重写改方法!那么D继承的是B的还是C的呢?

class A(object):
    def test(self):
        print('from A')

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

class C(A):
    def test(self):
        print('from C')
        
方式一:
class D(B,C):
    pass

obj = D()
obj.test() # 结果为:from B

方式二:
class D(C,B):
    pass

obj = D()
obj.test() # 结果为:from C

#这是为什么呢?看方法解析就知道啦!顺序看mro的顺序即可!
print(D.mro())
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
4.2、多继承的属性查找顺序原理

​ 1.子类会先于父类被检查
​ 2.多个父类会根据它们在列表中的顺序被检查
​ 3.如果对下一个类存在两个合法的选择,选择第一个父类

​ 4.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,

​ 5.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去(python2、3的mro算出来的顺序是不一样的)

4.3、深度优先和广度优先
class E:
    def test(self):
        print('from E')


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


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


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


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


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


print(A.mro())
'''
[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class 'object'>]
'''

obj = A()
obj.test() # 结果为:from B
# 可依次注释上述类中的方法test来进行验证

4.4 Pyton Mixins机制

Mixins机制核心

  • 就是在多继承的背景下尽可能的 提升多继承的可读性
  • 让多继承满足人的思维习惯:什么是什么

使用Mixin类实现多重继承要非常小心

  • 首先它必须表示某一种功能,而不是某个物品,python 对于mixin类的命名方式一般以 Mixin, able, ible 为后缀
  • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类,一个类可以继承多个Mixin,为了保证遵循继承的“is-a”原则,只能继承一个标识其归属含义的父类
  • 然后,它不依赖于子类的实现
  • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了)

加上Mixin,规范!

class Vehicle:  # 交通工具
    pass


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


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


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


class Car(Vehicle):  # 汽车
    pass

# ps: 采用某种规范(如命名规范)来解决具体的问题是python惯用的套路

五 、派生与方法重用

方法一:“指名道姓”地调用某一个类的函数

此方法不继承也可以调用其他类的属性

People.init(self,name,age,sex)加上这个即可,想要调用函数,还是得继承

class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def f1(self):
        print(F'{self.name}是沙雕')

class hh():
    def __init__(self,name,age,sex,level,love):
        People.__init__(self,name,age,sex)
        self.level = level
        self.love = love

obj = hh('张三',18,'男',3500,'钱')
print(obj.name)

方法二:super()

  • 调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类中找属性
  • 在python3中直接调用即可,python2-->super(当前类名称,self)
class People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def f1(self):
        print(F'{self.name}是沙雕')

#调用super()会得到一个特殊的对象,该对象会参照当前类的mro,去当前类的父类中找属性
class hh(People):
    def __init__(self,name,age,sex,level,love):
        super().__init__(name,age,sex)
        self.level = level
        self.love = love

obj = hh('张三',18,'男',3500,'钱')
print(obj.name)
原文地址:https://www.cnblogs.com/hsyw/p/13664348.html