博客
关于我
Python菱形继承的初始化问题和继承顺序
阅读量:567 次
发布时间:2019-03-09

本文共 3528 字,大约阅读时间需要 11 分钟。

Python菱形继承的初始化问题和继承顺序

Python中,类通过继承的方式,子类可以获得父类的非私有属性和非私有方法,不需要自己再重新实现。

继承可以多层继承,即可以多代继承。也可以多继承,即一个子类可以继承多个父类。

参考:

一、菱形继承简介

在多层继承和多继承同时使用的情况下,就会出现复杂的继承关系,多重多继承。

其中,就会出现菱形继承。如下图所示。

菱形继承也叫钻石继承,在这种结构中,当D类的对象使用一个属性时,首先会在D类中查找是否有该属性和方法,如果没有则会到父类中查找,如果还没有则会继续往父类的父类中查找。

根据这种关系,如果D类中没有找到属性和方法,是去B类中查找还是去C类中查找?

假设是去B类中查找,如果B类中也没有找到,下一步是去C类中还是A类中呢?

这些问题都是菱形继承所带来的问题,接下来我们来看Python中是怎么处理的。

二、菱形继承的初始化问题

class Electrical(object):    def __init__(self, name):        self.name = name        print('Electrical init')class Phone(Electrical):    def __init__(self, name, price):        Electrical.__init__(self, name)        self.price = price        print('Phone init')class Computer(Electrical):    def __init__(self, name, config):        Electrical.__init__(self, name)        self.config = config        print('Computer init')class HuaWei(Phone, Computer):    def __init__(self, name, price, config):        Phone.__init__(self, name, price)        Computer.__init__(self, name, config)        print('HuaWei init')h = HuaWei('huawei', 100, 'i7')

运行结果:

Electrical initPhone initElectrical initComputer initHuaWei init

上面的Phone类和Computer类都继承了Electrical类,HuaWei类既继承了Phone类又继承了Computer类,这就形成了一个菱形的继承关系。

在创建HuaWei类对象时,Electrical类的__init__方法执行了两遍,也就是说在Phone类向上继承时执行了,在Computer类向上继承时也执行了,这显然是不应该发生的。

三、通过super解决初始化问题

class Electrical(object):    def __init__(self, name):        self.name = name        print('Electrical init')class Phone(Electrical):    def __init__(self, price, *args):        super(Phone, self).__init__(*args)        self.price = price        print('Phone init')class Computer(Electrical):    def __init__(self, config, *args):        super(Computer, self).__init__(*args)        self.config = config        print('Computer init')class HuaWei(Phone, Computer):    def __init__(self, name, price, config):        super(HuaWei, self).__init__(name, price, config)        print('HuaWei init')h = HuaWei('huawei', 100, 'i7')

运行结果:

Electrical initComputer initPhone initHuaWei init

通过super方法,我们解决了Electrical初始化两次的问题,现在的继承关系就是正常的了。

注意:在Phone类和Computer类中给super()后的init方法传参数时,应使用*args,因为HuaWei有三个参数,但是Phone类和Computer类都只有两个参数,所以参数个数不正确会报错。

四、菱形继承的继承顺序

class Electrical(object):    def chat(self):        print('Chat with friend in electrical!')    def watch_movie(self):        print('Watch movie in electrical!')    def game(self):        print('Play game in electrical!')class Phone(Electrical):    def game(self):        print('Play game in phone!')class Computer(Electrical):    def watch_movie(self):        print('Watch movie in computer!')    def game(self):        print('Play game in computer!')class HuaWei(Phone, Computer):    passh = HuaWei()h.game()h.watch_movie()h.chat()

运行结果:

Play game in phone!Watch movie in computer!Chat with friend in electrical!

在上面的继承关系中,HuaWei类中一个方法也没有实现,所以类对象调用方法都是要去父类中找。

game()方法在三个类中都实现了,调用了Phone类中的方法,说明最先会去Phone类中查找。

watch_movie()方法在Phone类中也没有实现,调用了Computer类中的方法,说明第二个会去Computer类中查找。

chat()方法在Phone类和Computer类中都没有实现,调用了Electrical类中的方法,说明最后会去Electrical类中查找。

注意:在继承时,如果小括号()中先写Computer再写Phone,则两个类的继承顺序就会调换。

由此,我们可以得出菱形继承的继承顺序了。如下图所示。

五、__mro__方法查看继承顺序

根据上面的案例,我们已经知道了菱形继承中的继承顺序了。

这种继承顺序是遵循广度优先算法的。也就是说,多层多继承时,先在父级中按先后顺序查找,然后在到父级的父级中查找。

这样,继承顺序已经很清晰了,不过,这还需要我们人工来识别继承顺序。如果继承关系非常复杂,像一张网一样,我们再去人工识别继承顺序将会非常困难,并且容易出错。

在Python中,已经定义了一个魔法方法来帮助我们查看类的继承顺序,这个方法就是__mro__方法。

print(HuaWei.__mro__)

运行结果:

(
,
,
,
,
)

mro是 Method Resolution Order (方法解析顺序)的简写,我们可以直接打印类的__mro__方法来获取类的继承顺序。

注意:__mro__只能通过类对象来使用,不能通过实例对象来使用。

 

 

转载地址:http://myppz.baihongyu.com/

你可能感兴趣的文章
NIFI大数据进阶_Json内容转换为Hive支持的文本格式_实际操作_02---大数据之Nifi工作笔记0032
查看>>
NIFI大数据进阶_Json内容转换为Hive支持的文本格式_操作方法说明_01_EvaluteJsonPath处理器---大数据之Nifi工作笔记0031
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka消费者处理器_来消费kafka数据---大数据之Nifi工作笔记0037
查看>>
NIFI大数据进阶_Kafka使用相关说明_实际操作Kafka生产者---大数据之Nifi工作笔记0036
查看>>
NIFI大数据进阶_NIFI的模板和组的使用-介绍和实际操作_创建组_嵌套组_模板创建下载_导入---大数据之Nifi工作笔记0022
查看>>
NIFI大数据进阶_NIFI监控功能实际操作_Summary查看系统和处理器运行情况_viewDataProvenance查看_---大数据之Nifi工作笔记0026
查看>>
NIFI大数据进阶_NIFI监控的强大功能介绍_处理器面板_进程组面板_summary监控_data_provenance事件源---大数据之Nifi工作笔记0025
查看>>
NIFI大数据进阶_NIFI集群知识点_认识NIFI集群以及集群的组成部分---大数据之Nifi工作笔记0014
查看>>
NIFI大数据进阶_NIFI集群知识点_集群的断开_重连_退役_卸载_总结---大数据之Nifi工作笔记0018
查看>>
NIFI大数据进阶_使用NIFI表达式语言_来获取自定义属性中的数据_NIFI表达式使用体验---大数据之Nifi工作笔记0024
查看>>
NIFI大数据进阶_内嵌ZK模式集群1_搭建过程说明---大数据之Nifi工作笔记0015
查看>>
NIFI大数据进阶_内嵌ZK模式集群2_实际操作搭建NIFI内嵌模式集群---大数据之Nifi工作笔记0016
查看>>
NIFI大数据进阶_外部ZK模式集群1_实际操作搭建NIFI外部ZK模式集群---大数据之Nifi工作笔记0017
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_实际操作_03---大数据之Nifi工作笔记0035
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_01---大数据之Nifi工作笔记0033
查看>>
NIFI大数据进阶_实时同步MySql的数据到Hive中去_可增量同步_实时监控MySql数据库变化_操作方法说明_02---大数据之Nifi工作笔记0034
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_01_实际操作---大数据之Nifi工作笔记0029
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_02_实际操作_splitjson处理器_puthdfs处理器_querydatabasetable处理器---大数据之Nifi工作笔记0030
查看>>
NIFI大数据进阶_离线同步MySql数据到HDFS_说明操作步骤---大数据之Nifi工作笔记0028
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>