繼承特性
一、什么是繼承
-
繼承是一種新建類的方式,繼承了一個類,類中的屬性和方法就在子類中,類主要分為:父類/基類,子類/派生類
-
新式類
-
經典類
-
沒有繼承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列表找,現在想指名道姓的用某個父類的某個方法,就需要指名道姓的使用