super的基本使用教程:链接
在java中只支持单继承多接口模式。python支持多继承模式。
在多继承模式中有个难题就是钻石急继承也叫做菱形继承。
钻石基础的实例:
一个父类进行初始化类示,会导致一个类存在多次不同的初始化,出现钻石继承。钻石继承一般通过super来解决。
一般来说,Leaf类初始化时会初始化Medium1类和Medium2类,然后Medium1类初始化时会初始化Base类,Medium2类初始化时也会初始化Base类,所以这就导致Leaf类初始化时对Base类进行了两次初始化操作。python是通过super()来解决这个问题的。
实例:子类在初始化时如何初始化调用父类,两种形式进行调用:
父类名称.init(self,参数1,参数2,…)
super(自雷,self).init(参数1,参数2,…)
通过命令行help(super)直接查看super的使用:
super()就等价于super(class, ),即super(当前class, self)
super(type, obj) -> bound super object; requires isinstance(obj, type) ,其中第一个参数是开始寻找父类的起始点(起始但不包括),第二个参数是需要一个对应第一个type的实例,即满足isinstance(obj,type),这个方法将返回第一个满足继承关系的类,寻找顺序遵从type.__mro__属性顺序(mro将类的树形继承关系变成了一个list)
(mro知识mro链接)
面展示一个例子,类之间的关系图如下所示。
Student类分别继承于Person类和IdCard类,Person类又继承于Human类,当然Human类和IdCard类都会继承于object类(这里就不显示出来了)。
可通过Student.mro()查看Student类的继承关系(变成了list)。
参考链接:链接
#其实多继承这个我没有看懂,看了好几遍,只能去请教我的同事。
# -*- coding: UTF-8 -*-
class Human(object):
def __init__(self, sex):
print("Human init start")
self._sex = sex
print("Human init end")
def __str__(self):
return "Human sex is {}".format(self._sex)
class Person(Human):
def __init__(self, name, age, *args):
print("Person init start")
self._name = name
self._age = age
super().__init__(args[0])
print("Person init end")
class IdCard(object):
def __init__(self, *args):
print("IdCard init start")
self._id_card = args[-1]
print("IdCard init end")
class Student(Person, IdCard):
def __init__(self, grade, *args):
print("Student init start")
self._grade = grade
super().__init__(*args)
print(__class__)
# super(Human, self).__init__(*args) # 从Human开始起查找,但是不包括起点
IdCard.__init__(self, *args) # 这种方法也可以
print("Student init end")
def __str__(self):
s = "sex={}\tname={}\tage={}\tgrade={}\tidCard={}".format(self._sex, self._name, self._age, self._grade, self._id_card)
return s
# mro是method resolution order, 表示了类继承体系中的成员解析顺序
# 将继承的树关系变成了一个list
# [<class '__main__.Student'>, <class '__main__.Person'>, <class '__main__.Human'>, <class '__main__.IdCard'>, <class 'object'>]
print(Student.mro())
s = Student(100, "patrick", 26, "male", "programmer")
print(s)
运行结果:
D:\Anaconda3\python.exe H:/代码整理/exercise/1多继承.py
[<class '__main__.Student'>, <class '__main__.Person'>, <class '__main__.Human'>, <class '__main__.IdCard'>, <class 'object'>]
Student init start
Person init start
Human init start
Human init end
Person init end
<class '__main__.Student'>
IdCard init start
IdCard init end
Student init end
sex=male name=patrick age=26 grade=100 idCard=programmer
Process finished with exit code 0
在设计类时,类的继承关系一定要设计好设计清楚,要不然真是个大坑,特别是多继承条件下!!!
这里需要再次说明的是,__init__方法只是对实例对象做了属性的初始化,并不等同于Java里的new Student(),在python里是通过__new__方法创建对象的,创建对象成功后再调用__init__方法做属性的初始化。