1、什么是继承
继承是一种新建类的方式,新建的类称之为子类或派生类,继承的父类称之为基类或超类
- 在python中一个子类可以继承多个父类 ******
- 在其他语言中,一个子类只能继承一个父类
2、继承的作用
减少代码的冗余
3、如何实现继承?
1)先确认谁是子类,谁是父类
2)在定义子类时,子类名(父类名)
#父类
class Father1:
x = 1
pass
class Father2:
pass
class Father3:
pass
#子类
class Sub(Father1, Father2, Father3):
pass
#子类.__bases__查看父类
print(Sub.__base__) #<class '__main__.Father1'>
print(Sub.x) #1
如何寻找到继承的关系:
-
确认谁是子类:
hcy对象----->人子类------>动物父类
猪坚强对象----->猪子类-------->动物父类
哈士奇对象------->狗子类------->动物父类 -
确认谁是父类
动物类是父类
1.抽取对象之间相似的部分,总结出来
2.抽取类之间相似的部分,总结出父类
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
#oldboy人类
class OldboyPeople:
school = 'oldbay'
country = 'china'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
#老师类
class OldboyTeacher(OldboyPeople):
#老师修改分数
def change_score(self):
print(f'老师{self.name}正在修改分数。。。。')
#学生类
class OldboyStudent(OldboyPeople):
#学生选课系统
def choose_course(self):
print(f'学生『{self.name}正在选择课程。。。')
stu1 = OldboyStudent('YJG', 50, 'female')
print(stu1.school, stu1.name, stu1.age, stu1.sex)
tea1 = OldboyTeacher('大脸', 75, 'female')
print(tea1.school, tea1.name, tea1.age, tea1.sex)
注意:中程序的执行顺序是由上到下,父类必须定义在子类的上方
- 在继承背景下,对象属性的查找顺序:
1.先从对象自己的名称空间中查找
2.对象中没有,从子类的名称空间中查找
3.子类中没有,从父类的名称空间中查找,若父类没有,则会报错!
#父类
class Goo:
x =10
pass
#子类
class Foo(Goo):
x =100
pass
foo_obj= Foo()
#1)
# foo_obj.x = 1000
print(foo_obj.x) #100
print('对象的名称空间:', foo_obj.__dict__) # {}
print('子类的名称空间:', Foo.__dict__) #{'__module__': '__main__', 'x': 100, '__doc__': None}
print('父类的名称空间:', Goo.__dict__) #{'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__' of 'Goo'
print('对象的名称空间:', foo_obj.__dict__) #{}
#2)
foo_obj.x = 1000
print(foo_obj.x) #1000 对象添加属性的操作,并不是修改了子类的属性
print('对象的名称空间',foo_obj.__dict__) #{'x': 1000}
print('子类的名称空间',Foo.__dict__ ) #{'__module__': '__main__', 'x': 100, '__doc__': None}
print('父类的名称空间', Goo.__dict__) #{'__module__': '__main__', 'x': 10, '__dict__': <attribute '__dict__'...
print('对象的名称空间', foo_obj.__dict__) #{'x': 1000}
派生:
指的是子类继承父类的属性方法,并且派生出自己独有的属性与方法
若子类中的方法名与父类的相同,优先用子类的
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
#父类
class Foo:
def f1(self):
print('from Foo.f1...')
def f2(self): #self ---->bar_obj
print('from Foo.f2...')
#bar_obj.f1()---->对像自己找---->Bar ----->Foo
self.f1()
#子类
class Bar(Foo):
#相当于重写
def f1(self):
print('from Bar.f1...')
def func(self):
print('from Bar.func...')
bar_obj = Bar()
bar_obj.f1() #from Bar.f1...
bar_obj.func() #from Bar.func...
bar_obj.f2() #from Foo.f2...
#from Bar.f1...
#派生后继承关系查找验证:
bar_obj = Bar()
bar_obj.f2()
'''
结果1:
from Foo.f2...
from Bar.f1...
'''
派生与继承:
子类继承父类,派生出自己的属性与方法,并且重用父类的属性与方法。
解决问题:子类重用父类的属性,并派生出新的属性
两种方式:
1.直接引用父类的__init__
为其传参,并添加子类的属性
2.通过super来指向父类的属性
- super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间
注意:使用哪一种都可以,但不能两种方式混合使用
class People:
school = '清华大学'
def __init__(self, name, sex, age):
self.name = name
self.sex = sex
self.age = age
class Teacher(People):
def __init__(self, name, sex, age, title): #派生
self.name = name
self.sex = sex
self.age = age
self.title = title
def teach(self):
print('%s is teaching'%self.name)
obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
print(obj.name, obj.sex, obj.age, obj.title) #lili female 28 高级教师
这里Teacher中的__init__
内的前三行又是在写重复代码,若想在子类派生出的方法重用父类的功能,可以用两种方式:
# #方式一‘:指名道姓’地调用某一个类的函数
# class Teacher(People):
# def __init__(self, name, sex, age, title):
# People.__init__(self, name, age, sex)
# self.title = title
# def teach(self):
# print('%s is teaching' %self.name)
# obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
#
# print(obj.teach()) #lili is teaching
# #None
# #方法二:super()
'''
调用super()会得到一个特殊的对象,该对象专门用来引用父类的属性,且严格按照
MRO规定的顺序向后查找
'''
class Teacher(People):
def __init__(self, name, sex, age, title):
super().__init__(name, age, sex) #调用的是绑定方法,自动传入self
self.title = title
def teach(self):
print('%s is teaching' %self.name)
obj = Teacher('lili','female', 28, '高级教师') #只会找自己类中的__init__
print(obj.teach()) #lili is teaching
#None
注意:在python2中super 的使用需要完整地写成super(自己的类名,self),而在python3中可以简写为super()。
新式类:
1.凡是继承object的类或子孙类都是新式类
2.在python3中所有的类都默认继承object
经典类:
1.在python2中才会有经典类与新式类之分
2.在python2中,凡是没有继承object的类,都是经典类
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
class User(object):
pass
class User:
x =10
pass
class Sub(User):
pass
print(User.__dict__) # {'__module__': '__main__', 'x': 10, '__dict__':
# <attribute '__dict__' of 'User' objects>,
print(object) #<class 'object'>
调用mro 返回的是一个继承序列
super 的继承顺序严格遵循mro继承序列
class Father1:
x =10
pass
class Father2:
x = 20
pass
#多继承的情况下,从左到右
class Sub(Father1,Father2):
def __init__(self): #注意__int__不是__init__
print(super().__delattr__)
print(Sub.mro()) # [<class '__main__.Sub'>, <class '__main__.Father1'>, <class '__main__.Father2'>, <class 'object'>]
obj = Sub()
print(object) #<class 'object'>
在python3中提供了一种查找新式类查找顺序的内置方法
mro():会把当前类的继承关系列出来
注:supper()会严格按照mro列表的顺序往后查找
class A: #默认继承object
def test(self):
print('from A.test')
super().test()
class B:
def test(self):
print('from B.test')
class C(A, B):
pass
c = C()
#检查super的继承顺序
#mro(): 会把当前类的继承关系列出来。
print(C.mro()) #[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
c.test() #from A.test
#from B.test
砖石继承:
多继承情况下造成’“砖石继承”
mro 的查找顺序:
-
新式类:
广度优先 -
经典类:
深度优先
#新式类
class A(object):
def test(self):
print('from A')
pass
class B(A):
def test(self):
print('from B')
pass
class C(A):
def test(self):
print('from C')
pass
class D(B):
def test(self):
print('from D')
pass
class E(C):
def test(self):
print('from E')
pass
class F(D, E):
def test(self):
print('from F')
pass
# F-->D-->B-->E-->C-->A-->object,注意:当class C(A)中A不存在时,则查找顺序为F-D-B-A-E-C->object
print(F.mro())
obj = F()
obj.test()如果是经典类,查找顺序为:F-D-C-A-E-C