ITPub博客

首页 > 数据库 > 数据库开发技术 > python面向对象编程篇(6):再说说继承问题

python面向对象编程篇(6):再说说继承问题

原创 数据库开发技术 作者:程序员小钟同学 时间:2021-03-15 18:02:50 0 删除 编辑

本文相关描述主要是个人的认知和见解,如有不当之处,还望各位大佬指正。

个人其他博客地址:

简书:https://www.jianshu.com/u/d6960089b087

掘金:https://juejin.cn/user/2963939079225608

小钟同学 | 文 【原创】| QQ:308711822

1、前言

从前面的几篇介绍中可以知道面对对象的几个特性:

  • 封装
  • 继承
  • 多态

再一定的程度上其实可以理解为:我们有了封装---》才有了继承---》有了继承---》才派生出了多态。

继承解决的主要问题点:

  • 代码可复用性

在python里面我们的继承还有一个特性就是,它支持多继承,不像我们的java只支持单一的继承。

但是在python世界多继承的优缺其实主要是看你的应用场景而定,这里再有必要的说一下继承的问题,主要是多继承的问题容易引发,到底说是“真正的老爹”的问题。而且如果“多爸”包含一样的属性的时候,我该继承谁的问题也尤为关键。

2、类的分类类型

首先我们还需要知道一个小知识点就是:在python定义类的实现的时候,不同的版本有不同的叫法,内部实现的调度顺序算法也是不一样。

多数情况下,基本我们的都是基于Py3的版本进行开发了,所以上面的分类其实没多大的影响,纯当补充额外的知识点。

3、多继承下不同的类继承顺序查找顺序(MRO)问题方式

  • 新式类:C3算法类似从左至右的广度优先。(非广度优先,只是部分情况结果刚好和广度优先的结果相同)
  • 经典类:深度优先,即从下往上搜索。

4 、多继承引发的查找顺序(MRO)-到底说是“真正的老爹”的问题

多继承下方法调用的顺序:

4.1如果派生类没有属于自己方法的情况下:

我先继承谁的就是谁(如图 谁先摸到头我就调用谁的方法)

如新式类示例代码:

# -*- coding:utf-8 -*-
class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen,MamaRen):


    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):

    def say(self):
        print("我是女孩子")

class HaiziRen_nan_nv(HaiziRen_nan, HaiziRen_nv):
        pass


haizinannv= HaiziRen_nan_nv()
haizinannv.say()

输出的结果为:

我是男孩子

上面我的HaiziRen_nan_nv集成的是HaiziRen_nan()所以它调用的HaiziRen_nan的say方法。

如果反过来:

class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen,MamaRen):


    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):

    def say(self):
        print("我是女孩子")

class HaiziRen_nan_nv(HaiziRen_nv, HaiziRen_nan):
        pass


haizinannv= HaiziRen_nan_nv()
haizinannv.say()

则输出的结果为:

我是女孩子

4.2如果派生类有属于自己方法的情况下,则调用我自身的方法,不会去父类里查询

class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen,MamaRen):


    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):

    def say(self):
        print("我是女孩子")

class HaiziRen_nan_nv(HaiziRen_nv, HaiziRen_nan):
        pass

        def say(self):
            print("是男是女,我说了才算!")

haizinannv= HaiziRen_nan_nv()
haizinannv.say()

输出的结果为:

是男是女,我说了才算!

4.3 多继承中如何查询这个类的所有的基类的线性顺序表

如上面的4.2代码的示例示例:

class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen,MamaRen):


    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):

    def say(self):
        print("我是女孩子")

class HaiziRen_nan_nv(HaiziRen_nv, HaiziRen_nan):
        pass

        def say(self):
            print("是男是女,我说了才算!")

print(HaiziRen_nan_nv.mro())

输出的.mro()结果为:

[
<class '__main__.HaiziRen_nan_nv'>, 
<class '__main__.HaiziRen_nv'>, 
<class '__main__.HaiziRen_nan'>, 
<class '__main__.BabaRen'>, 
<class '__main__.MamaRen'>, 
<class 'object'>
]

从上到下的顺序依次为:HaiziRen_nan_nv-->HaiziRen_nv-->HaiziRen_nan......

多继承问题总结:

  • 子承父业的时候:子调用相关属性和方法的时候,先从自己的字典里查询,如果没有,再根据我第一个优先继承的那个人去它的字典里面查,这就也就是说所谓的根据基类的线性顺序表去定位。

如:

class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen, MamaRen):

    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):
    pass


class HaiziRen_nan_nv(HaiziRen_nv, HaiziRen_nan):
    pass


haizinannv = HaiziRen_nan_nv()
haizinannv.say()

输出的结果是:

我是男孩子

再两个都没有的情况,最终我只能找到HaiziRen_nan里面有:叫用它的方法了!

  • 子承父业的时候:子属性和方法,不影响父类的属性和方法,各自独立更生:
  • 子承父业的时候:子可以啃老(调用父类的属性和方法),老的不能吃子的,有点M憋屈的感觉(父类不能调用子类的属性和方法):

5 、instance和type的区别

两个都是用于类型的判断,但主要区别在于:是否包含继承关系的判断。

  • type 不包含继承关系的判断

  • instance 包含继承关系的判断

class BabaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老爸")


class MamaRen():

    def __init__(self):
        pass

    def say(self):
        print("我是老妈")


class HaiziRen_nan(BabaRen, MamaRen):

    def say(self):
        print("我是男孩子")


class HaiziRen_nv(BabaRen, MamaRen):
    pass


class HaiziRen_nan_nv(HaiziRen_nv, HaiziRen_nan):
    pass


haizinannv = HaiziRen_nan_nv()
haizinannv.say()
print(isinstance(haizinannv,HaiziRen_nan_nv))
print(isinstance(haizinannv,HaiziRen_nan))
print("===========")
print(type(haizinannv) is HaiziRen_nan_nv)
print(type(haizinannv) is HaiziRen_nan)

输出的结果:

我是男孩子
True
True
===========
True
False

6 、多继承之下引出的--混入Mixin模式

子承父业的继承模式,可以让子类瞬间拥有了父类的相关属性和方法。再结合多继承的情况,我们好像可以可以未为所欲为的组装我们的功能了。

逼的贝利亚奥特曼的进阶之路:



class Aote():

    def __init__(self):
        print("我是奥特之父")


class Dijia(Aote):

    def __init__(self):
        pass
        print("我是---迪迦---奥特曼")


class Saiwen(Aote):

    def __init__(self):
        pass
        print("我是---赛文---奥特曼")


class Jiguang():

    def jineng_fashejiguang_1(self):
        print("技能1:惯性冲击,借用从高空下冲的力量去撞击敌人,冲击时双手与大气摩擦产生强大的冲击力")

    def jineng_fashejiguang_2(self):
        print("技能2:冲击光拳,将能量聚集在手上,再使出全力打向敌人,威力惊人")

class DaoTou():

    def dadaoyiba_1(self):
        print("技能:奥特念力")

    def dadaoyiba_2(self):
        print("技能:头镖")

class Sgenjian():
    def shenjian(self):
        print("拥有一把削铁如泥的宝剑!!!!")

# 贝利亚奥特曼融合迪迦到特曼
class Beiliya(Dijia,Jiguang,DaoTou,Sgenjian):
    pass


a =  Beiliya()
a.jineng_fashejiguang_1()
a.jineng_fashejiguang_2()
a.shenjian()

贝利亚奥特曼融合了迪迦奥特曼还有组装上了其他技能!!!!然后变的超神了!!!

总结MixIn混入模式,可以多继承的方式,进行相关组合多个子类的功能的实现。

主要是为了框架便捷的快速的进行代码重用而设计的一种模式。通过这种模式扩展子类的功能,避免设计多层级的复杂的继承关系。有点类似吸星大法一样,看谁的技能强,就把它给吸收了就行!!!

End

纯属个人实践中相关经验阐述总结,如有纰漏,还希望大佬们多多提点!小钟同学 | 文  【原创】| QQ:308711822


原文作者:程序员小钟同学;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2021-02-20

  • 博文量
    224
  • 访问量
    111698