面向对象继承、派生
面向对象的三大特性:
继承
封装
多态
----什么是继承:一种新建类的方式,继承了一个类,类中的属性和方法就在子类中
----父类/基类
----子类/派生类
----新式类:只要继承了object类,就是新式类,在python3中,默认是新式类
--python3中:默认继承object
--python2中:需要显示的指定继承object
----经典类:没有继承object的类,就是经典类
--python3中没有经典类
--python2中才有
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('LZS',19,"python")
print(stu1.school)
stu1.school='xxx'
print(stu1.school)
问题一:如何重用父类的属性
问题二:属性的查找顺序是什么
先找对象---》类中找----》父类中找(多继承)---》报错
问题三:如何重用父类的方法
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
class Teacher(Person):
pass
class Student(Person):
pass
stu1.school='xxxx'
print(stu1.school)
类实例化会自动调用__init__如果类中没有,就去父类中找,对于上面的程序,如果执行stu1=Student(),会报错,因为父类中必须传两个参数
多层继承
class A:
a="AAAA"
class B(A):
a="BBBB"
class C(B):
a="CCCC"
class D(C):
a="DDDD"
d=D()
print(d.a)
多继承
class A:
a="AAAA"
class B:
a="BBBB"
class C:
a="CCCC"
class D(A,B,C):
# a="DDDD"
pass
d=D()
print(d.a)
继承的菱形问题:新式类和经典的查找顺序是不一样的
新式类的查找属性:广度优先
经典类:深度优点
class G(object):
a="GGGG"
class F(G):
a='FFFF'
class E(G):
a='GGGG'
class D(G):
a='DDDD'
class C(F):
a='CCCC'
class B(E):
a='BBBB'
class A(B,C,D):
a='FFFF'
# a=A()
# print(a.a)
##mro列表,继承顺序查找列表(只在新式类中有)
print(A.mro()) ##返回列表类型
print(A.__mro__) ##返回元祖类型
继承的菱形问题(显示的都继承一个类,不是object类):新式类和经典类的查找顺序不一样的
新式类:(py3中全是新式类):广度优先---》从左侧开始,一直往上找,找到菱形的顶点结束(不包括顶点)
经典类:(只有py2中才有):深度优先---》从左侧开始,一直往上找,找到菱形的顶点结束(包括菱形顶点),继续下一个继承的父类
不出现菱形问题:正常查找
继承重用父类方法方式一:指名道姓的使用,跟继承没有关系
继承重用父类方法方式二:通过super()关键字,跟继承有关系
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)
#self.name=name
#self.age=age
self.level=level
class Student(Person):
school='yyyy'
def __init__(self,name,age,course):
#如何重用父类的__init__方法
Person.__init__(self,name,age)
self.course=course
def study(self):
Person.study(self)
print("%s学生在学习"%self.name)
stu1=Student('LZS',19,"python")
print(stu1.school)
stu1.study()
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)
# 经典类和新式类
# 经典类中必须这么写(py3中没有经典类),都用上面那种方式写
# super(Student,self).__init__(name,age)
self.course = course
def study(self):
# Person.study(self)
super().study()
# print("%s学生在学习"%self.name)
stu1=Student('LZS',23,"python")
stu1.school='xxxx'
print(stu1.school)
既然选择了远方,只能风雨兼程