目录
继承介绍
一、什么是继承
继承是一种新建类的方式,继承了一个类,类中的属性和方法就在子类中。
-
父类/基类
-
子类/派生类
-
新式类:只要继承了object类,就是新式类,再python3中,默认继承object类
-
Python3中:默认继承object
-
class A:
pass
-
-
python2中,需要显示的指定继承object
-
-
经典类:没有继承object的类,就是经典类
- python3中没有经典类
- python2中才有
如何使用继承
class 类名(父类1, 父类2):
pass
class A(object):
pass
class C:
pass
#B继承了A, C这个类
class B(A,C):
pass
#类的其他内置方法
print(B.__dict__)
#类名
print(B.__name__)
#B的父类
print(B.__bases__)
减少代码冗余
#利用父类Person减少代码冗余
class Person:
school = 'oldboy'
class Teacher(Person):
def __init__(self,name,age,level):
self.name = name
self.age = age
self.level = level
class Student(Person):
def __init__(self,name,age,course):
self.name = name
self.age = age
self.course = course
stu1 = Student('nick', 18, python)
print(stu1.school) #oldboy
一、关于查找顺序
对象 ——> 类 ——> 父类 ——> 报错
class Person:
school = 'oldboy' #1
class Teacher(Person):
def __init__(self,name,age,level):
self.name = name
self.age = age
self.level = level
class Student(Person):
#school = 'oldbaby' #3
def __init__(self,name,age,course):
self.name = name
self.age = age
self.course = course
stu1.school = 'oldgirl' #2
print(stu1.school)
#1 结果:oldboy
#2 结果:oldgirl
#3 结果:oldbaby
二、如何重用父类属性
class Person(object):
school = 'oldboy'
def __init__(self, name, age):
self.name = name
self.age = age
class Teacher(Person):
pass
class Student(Person):
pass
stu1 = Student('nick', '18')
print(stu1.school) #oldboy
三、多层继承
class A:
a = "AAA"
class B(A):
a = "BBB" #3
class C(B):
a = "CCC" #2
pass
class D(C):
a = "DDD" #1
pass
d=D()
print(d.a)
#1 结果:CCC
#2 结果:BBB
#3 结果:AAA
四、多继承
class A:
a = "AAA"
pass
class B:
a = "BBB"
pass
class C:
a = "CCC"
pass
class D(A,B,C):
a = "DDD"
pass
d = D()
print(d.a)
注意:多继承执行顺序,例D(A, B, C)是从左到右。
五、继承的菱形问题
总结:经典类(深度优先),第一支找到就不再查找;新式类(广度优先),最后一支找到为止。
六、mro列表
#mro 列表,继承顺序查找列表(只在新式类中有)
print(A.mro())
print(A.__mro__)
#[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class '__main__.D'>, <class '__main__.G'>, <class 'object'>]
注意:可通过mro列表展示继承顺序。
重用父类方法的两种方式
一、方式一
继承重用父类方法方式一:指名道姓的使用
- 与继承无关
- 如果继承了多个父类,super是按照mro列表找,那么此时指名道姓地使用可以抛开mro列表的查找顺序,进行特殊调用
class A:
def __init__(self,name,age):
self.name = name
self.age = age
class Person:
school = 'oldboy'
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):
A.__init__(self,name,age) #A作为类,对于init需传入三个参数
self.level = level
class Student(Person):
school = 'yyyy'
def __init__(self,name,age,course):
#如何重用父类的__init__方法
Person.__init__(self,name,age) #Person作为类,对于init需传入三个参数
self.course = course
def study(self):
Person.study(self)
print("%s学生在学习"%self.name)
stu1=Student('wed',19,"Python")
print(stu1.school)
stu1.study()
#yyyy
#study....
#wed学生在学习
二、方式二
继承重用父类方法方式一:通过super关键字(与继承有关)
class Person(object):
school = 'oldboy'
def __init__(self,name,age):
self.name=name
self.age=age
def study(self):
print('study....')
class Student(Person):
school = 'yyyy'
def __init__(self,name,age,course):
#super() 会按照mro列表拿到父类对象
#对象来调用绑定方法,不需要传递第一个参数(self)
super().__init__(name,age) #super()取出的是对象,所以第一个参数无需传参
#经典类和新式类
#经典类中必须这么写(py3中没有经典类),都用上面那种方式写
# super(Student,self).__init__(name,age)
self.course=course
def study(self):
# Person.study(self)
super().study()
# print("%s学生在学习"%self.name)
stu1=Student('wed',19,"Python")
stu1.study()
#study....
修改参数值的四种方式
#修改学生姓名
stu=Student('nick',18)
#方式一
print(stu.name)
stu.name='tank'
print(stu.name)
#方式二:
stu.chang_name('tank')
print(stu.name)
#方式三
Student.chang_name(stu,'王二蛋')
print(stu.name)
#方式四
#定义了一个函数
def change_name(obj,name):
#修改obj对象的name属性
print('原来的名字是%s' % obj.name)
obj.name=name
print('修改的名字是%s' % obj.name)
change_name(stu,'二丫')
print(stu.name)
super的使用
# super是按照mro列表找
class A:
def f1(self):
print('A.f1')
class B:
def f1(self):
print('B.f1')
def f2(self):
print('B.f2')
super().f1()
# return 'xxxxx'
class C(B,A):
#mro列表按照这个顺序, 注意这个顺序, 这个顺序报错
# class C(A,B):
def f1(self):
print('C.f1')
#C实例化产生一个对象
c=C()
# print(c.f2())
print(C.mro())
c.f2() #C中找不到,再去B中找,打印B.f2,继续执行A中的f1,打印A.f1
#B.f2
#A.f1