面向对象进阶
类的继承
什么是继承
- 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类
- python当中,父类,子类(派生类),父类和子类只有在继承的时候才会产生
- 继承是为了获取父类的属性
为什么要用继承
- 集成可以减少代码冗余
对象的继承
- python中支持一个子类继承多个父类,但是不推荐使用继承多个父类,当你继承多个的时候,功能与功能之间就会混乱,所以建议继承一个
- python3中如果一个类没有继承任何类,那么默认继承object类
- python2中如果一个类没有继承任何类,不会继承object类
对象查找属性的顺序
先对象自己,后然后对象的类,然后父类,在父类,知道object类
类的派生
派生就是子类定义新的属性,同时还继承父类的所有属性
方法一:指名道姓的访问某一个类的函数,该方式与继承无关
class Animal():
def __init__(self, height, weight):
self.height = height
self.weight = weight
def jiao(self):
print(self.__class__.__name__, '叫')
class People(Animal):
def __init__(self, name, age,height,weight):
Animal.__init__(self,height,weight)
self.name = name
self.age = age
def read(self):
print('read')
p1=People('nick',18,180.140)
print(p1.__dict__)
方法二:派生
- 严格以继承属性查找关系
- super()会得到一个特殊的对象,该对象就是专门用来访问父类中的属性的(按照继承的关系)
- super的完整用法是super(自己的类名,self),在python2中需要完整写明,二python3中可以简写为super()
class OldBoyPeople:
school='oldboy'
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
class OldBoyStudent(OldBoyPeople):
def __init__(self,name,age,sex,stu_id):
super().__init__(name,age,sex)
self.stu_id=stu_id
def choose_course(self):
print(f'{self.name} is choosing course')
stu1=OldBoyStudent('nick',19,'male','001')
类的组合
组合就是一个类的对象具备某一个属性,该属性的值是指向另外一个类的对象
组合就是用来解决类与类之间代码冗余的问题
class People:
def __init__(self,name,sex):
self.name=name
self.sex=sex
def eat(self):
print(f'{self.name}开始吃')
class Student(People):
def __init__(self,id,name,sex):
super(Student, self).__init__(name,sex)
self.id=id
def choose_course(self,course):
self.course=course #相当于student派生一个course属性,该属性引用外部传入的course也就是Course生成的对象
print(f'{self.name}选择了课程{course.name}')
class Teacher(People):
def __init__(self,level,name,sex):
super(Teacher, self).__init__(name,sex)
self.level=level
def scored(self,student,course,score):
print(f'{self.name}给学生{student.name}的课程{course.name}打{score}分')
class Admin(People):
def create_course(self,name,price):
course=Course(name,price)
print(f'管理员{self.name}创建了课程{name}')
return course
class Course:
def __init__(self,name,price):
self.name=name
self.price=price
st1=Student('01','zhujian','male')
st2=Student('02','tom','male')
print(st1.__dict__)
print(st2.__dict__)
t1=Teacher('1','nick','male')
print(t1.__dict__)
a1=Admin('egon','male')
print(a1.__dict__)
linux=a1.create_course('linux',6666)
python=a1.create_course('python',8888)
st1.choose_course(python)
st2.choose_course(linux)
t1.scored(st1,python,'96')
t1.scored(st2,linux,'95')
菱形继承问题
类的分类
- 新式类
- 继承了object的类以及该类的子类,都是新式类
- python3中所有的类都是新式类
- 经典类
- 没有继承object的类以及该类的子类,都是经典类
- 只有python2中才有经典类
菱形继承问题
如果继承关系为菱形结构,即子类的父类最后继承了同一个类,那么属性的查找有两种:
- 经典类:深度优先:一条路走到底.先从子类的第一个父类开始查找,直到这个子类继承的最后一个父类,如果没有找到就从子类的第二个父类开始查找(但不会找到最后一个父类),然后是子类的第三个父类,第四个父类,直到找到需要的属性
- 新式类:广度优先:不直接找最后一个继承的父类,先从子类的子一个父类开始找,跳过继承的最后一个父类,然后子类的第二个父类,第三个,直到最后一个父类然后再去查找他们继承的最后一个父类
普通继承就是按照正常循序查找
多态与多态性
多态
多态指的是一类事物有多种形态(一个抽象类有多个子类,因而多态的概念依赖于继承)
多态性
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用给一个函数名调用不同内容的函数