继承特性
一、什么是继承
-
继承是一种新建类的方式,继承了一个类,类中的属性和方法就在子类中,类主要分为:父类/基类,子类/派生类
-
新式类
-
经典类
-
没有继承object的类,就是经典类,python3中没有经典类,python2中才有
class A(object):
pass
class C(object):
pass
class B(A, C):
pass
# 类的其他内置属性,__名字__
# 查看类的属性和方法
print(B.__dict__)
# 查看类名
print(B.__name__)
# 查看B类的父类
print(B.__bases__)
{'module': 'main', 'doc': None}
B
(<class 'main.A'>, <class 'main.C'>)
二、继承重用父类
类实例化会自动调用__init__如果类中没有,去父类中找
class Person:
school = 'hnnu'
class Teacher(Person):
def __init__(self, name,age,level):
self.name = name
self.age = age
self.level = level
class Student(Person):
school = 'bj'
def __init__(self, name, age, course):
self.name = name
self.age = age
self.course = course
stu1 = Student('zhangsan', 18, 'python')
print(stu1.school)
stu1.school = 'xxx'
print(stu1.school)
bj
xxx
三、属性的查找顺序
先找到当前的对象—>类中找--->父类中找(注意多继承)—>报错(找不到)
四、多层继承和多继承
# 多层继承
class A:
a = 'aaa'
class B(A):
b = 'bbb'
class C(B):
c = 'ccc'
class D(C):
d = 'ddd'
d = D()
print(d.a)
ddd
# 多继承
class A:
a = 'aaa'
class B:
a = 'bbb'
class C:
a = 'ccc'
class D(A,B,C):
a = 'ddd'
d = D()
print(d.a)
ddd
四、菱形问题
# 继承菱形问题: 新式类和经典类的查找顺序不一样
# 新式类的查找属性:广度优先
# 经典类:深度优先
class G():
a = 'ggg'
class F(G):
a = 'fff'
class E(F):
a = 'eee'
class D(E):
a = 'ddd'
class C(D):
a = 'ccc'
class B(C):
a = 'bbb'
class A(B, C, D):
a = 'aaa'
a = A()
print(a.a)
# mro 列表,查看继承顺利列表(只在新式类中有)
print(A.mro())
print(A.__mro__)
- 继承菱形问题在python3中显示的都是继承一个类,不是object类, 新式类和经典类的查找顺序是不一样
- 新式类(python3中全是新式类):广度优先---从左侧开始,一直往上找,找到菱形的顶点结束(不包含菱形顶点),继续下一个继承父类往上找,找到菱形的顶点结束(不包含括菱形的顶点),最后找到菱形顶点
- 经典类(python2中才有):深度优先搜索---从左侧开始,一直往上找,找到菱形顶点结束(包括菱形顶点),继续下一个继承父类往上找,找到菱形的顶点结束(不包含菱形顶点)
五、重用父类方法的两种方式
class Person:
school = 'hnnu'
def __init__(self, name, age):
self.name = name
self.age = age
def study(self):
print('study...')
class Teacher(Person):
def __init__(self, name, age, level):
self.name = name
self.age = age
self.level = level
# 重用父类方法一
class Student1(Person):
# 重用父类__init__方法
def __init__(self, name, age, course):
Person.__init__(self, name, age)
self.course = course
def study(self):
Person.study(self)
print(f'{self.name}学生在学习')
# 重用父类方法二
class Student2(Person):
# 重用父类方法__init方法
def __init__(self, name, age, course):
# super() 会按照mro列表拿到父类对象
# 对象来调用绑定方法,不需要传递第一个参数(self)
super().__init__(name, age)
# 经典类中必须这样写(py3中没有经典类),但是在python3中都用上面那种方式写
super(Student2, self).__init__(name, age)
self.course = course
def study(self):
Person.study(self)
print(f'{self.name}学生在学习')
stu1 = Student1('web', 18, 'Python')
stu1.study()
stu2 = Student2('xiaomei', 19, 'Linux')
stu2.study()
study...
web学生在学习
study...
xiaomei学生在学习
-
总结,有继承关系的时候,通常用super
-
指名道姓的方式在什么情况下用?
- 没有继承关系
- 如果继承了多个父类,super是按照mro列表找,现在想指名道姓的用某个父类的某个方法,就需要指名道姓的使用