面向对象的特征之继承


目录

  • 今日内容概要
    • 内容详细
      • 封装
      • 继承(概念)
      • 继承实例
      • 单继承下的属性查找
      • 多继承下的属性查找
      • super()和mro列表
      • 多态和多态性(了解)

今日内容概要
  • 面向对象的三大特征
    • 封装
    • 继承(重要)
    • 多态
  • 继承的属性查找顺序
    • 单继承下的属性查找
    • 多继承下的属性查找
  • super()和mro()列表
  • 多态与多态性(了解)
面向对象的特征之继承
文章图片

内容详细 封装
# 将功能封装成函数# 在类中 我们正常定义的方法 就是封装

面向对象的特征之继承
文章图片

继承(概念)
1.什么是继承 ''' 继承就是新建类的一种方式 新建的类我们称之为 子类 或者 派生类 被继承的类称之为 父类 或者 基类 子类可以使用父类中的属性或方法 '''2.为什么要用继承 ''' 类解决了对象与对象之间的代码冗余问题 继承解决的是类与类之间的代码冗余问题 ''' 3.如何使用继承 # 新式类 继承了object类的子子孙孙类 # 经典类 没有继承object类的子子孙孙类 ''' 新式类和经典类只在python2中区分 python3只有新式类 '''

【面向对象的特征之继承】面向对象的特征之继承
文章图片

继承实例
# 以学生选课系统为例# 定义父类 class People: school = 'SH' def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender# 定义学生类(子类) class Student(People):# 继承父类Peopledef __init__(self, name, age, gender, course=None): if course is None: course = [] People.__init__(self, name, age, gender) self.courses = coursedef choose_course(self, course): self.courses.append(course) print('%s 选课成功 %s' % (self.name, self.courses))stu = Student('ly', 19, 'male') print(stu.name)# ly# 定义老师类(子类) class Teacher(People):# 继承父类Peopledef __init__(self, name, age, gender, level): self.level = level People.__init__(self, name, age, gender)def score(self, stu_obj, score): stu_obj.score = score# 给学生打分 print('%s给%s打了%s分' % (self.name, stu_obj.name, score))tea = Teacher('ly', 19, 'male', 10) print(tea.name)# ly print(tea.level)# 10

面向对象的特征之继承
文章图片

单继承下的属性查找
class Foo: def f1(self): print('Foo.f1')def f2(self): print('Foo.f2')# 1 self.f1()# self = obj = Bar 所以要找 Bar中的 f1class Bar(Foo): def f1(self): print('Bar.f1')# 2obj = Bar()# {} print(Bar.mro())# [, , ] 查找空间顺序 obj.f2() ''' 打印结果: Foo.f2 Bar.f1 '''# 练习 class Foo: def __f1(self):# _Foo__f1() print('Foo.f1')def f2(self): print('Foo.f2')# 1 self.__f1()# _Foo__f1() 此处的__f1是属于Foo类空间产生的f2对象空间中 所以结果是 Foo.f1class Bar(Foo): def __f1(self):# # _Bar__f1() print('Bar.f1')obj = Bar()# {} print(Bar.mro())# [, , ] 查找空间顺序 obj.f2() ''' 打印结果: Foo.f2 Foo.f1 '''

面向对象的特征之继承
文章图片

多继承下的属性查找
# 新式类:按照广度优先查询(经典类:按照深度优先查询) class A(object): def test(self): print('from A')class B(A): def test(self): print('from B') passclass C(A): def test(self): print('from C') passclass D(B): # def test(self): #print('from D') passclass E(C): # def test(self): #print('from E') passclass F(D, E): # def test(self): #print('from F') passf1 = F() f1.test() print(F.mro())# 查找顺序按照 [, , , , , , ] 找不到就下一个类 不能返回查找 ''' 打印结果: from B '''

面向对象的特征之继承
文章图片

super()和mro列表
# 父类 class People(): school = 'SH'def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender# 学生类(子类) class Student(People): def __init__(self, name, age, gender, course=None): if course is None: course = [] # People.__init__(self, name, age, gender)# 指名道姓的调用父类的方法 # super(Student, self) 返回了一个特殊的对象 # 它的使用遵从mro列表 # super(Student, self).__init__(name, age, gender)# python2的写法 super().__init__(name, age, gender)# python3 的写法 self.courses = coursedef choose_course(self, course): self.courses.append(course) print('%s 选课成功 %s' % (self.name, self.courses))stu = Student('ly', 19, 'male') print(stu.name)# ly# 老师类(子类) class Teacher(People): def __init__(self, name, age, gender, level): self.level = level People.__init__(self, name, age, gender)def score(self, stu_obj, score): stu_obj.score = score# 给学生打分 print('%s给%s打了%s分' % (self.name, stu_obj.name, score))tea = Teacher('ly', 19, 'male', 10) print(tea.name)# ly print(tea.level)# 10# 例题1 class A: def test(self): print('from A.test') super().test()class B: def test(self): print('from B')class C(A, B): passc = C() c.test() print(C.__mro__)# 查找顺序 按照mro列表 由C3线性算法产生 (, , , ) ''' 打印结果: from A.test from B '''# 例题2 class B: def test(self): print('B---->test')def aaa(self): print('B---->aaa')class A: def test(self): print('A---->test') super().aaa()class C(A, B): def aaa(self): print('C----->aaa')c = A() c.test()# 打印结果: A---->test + 报错 print(A.mro())# 查找顺序 [, ] A类找不到就直接报错

面向对象的特征之继承
文章图片

多态和多态性(了解)
1.什么是多态 水: 液态水 固态水 气态水 动物: 人 猪 狗 猫...# 抽象类 定义 抽象类只能被继承 不能被实例化# 固定语法 import abcclass Animal(metaclass=abc.ABCMeta): @abc.abstractmethod# 该方法已经是抽象方法了 def speak(self): pass@abc.abstractmethod# 子类函数必须含有 login 方法 没有就会直接报错 def login(self): passclass People(Animal): def speak(self): print('嗷嗷嗷')def login(self):# 子类函数必须含有 login 方法 没有就会直接报错 pass''' 如果定义抽象类了 那么子类当中必须由抽象类的方法名 即使子类函数体代码为pass也可 否则将直接报错 而不会再到抽象类(父类)查找 eg: class People(Animal): def jiao(self): print('嗷嗷嗷')obj = People() obj.speak() 打印结果: 直接报错 '''class Pig(Animal): def speak(self): print('哼哼哼')class Dog(Animal): def speak(self): print('汪汪汪')obj = People() obj.speak() ''' 打印结果: 嗷嗷嗷 '''# 在python3中 抽象类写法墨守成规为以下 # 省去了abc模块固定语法 class People(): def speak(self): print('嗷嗷嗷')class Pig(): def speak(self): print('哼哼哼')class Dog(): def speak(self): print('汪汪汪')class Txt(): def speak(self): print('Txt')obj = People() obj1 = Pig() obj2 = Dog() obj3 = Txt()# 多态带来的特性:在不用考虑对象数据类型的情况下,直接调用对应的函数 封装成函数调用 def animal(animal): return animal.speak()animal(obj) animal(obj1) animal(obj2) animal(obj3)# len 就是多态一种场景 len('abc') len([1, 2, 3]) len({'username': 'ly'})def len(item): return item.__len__() print(len('abc'))# 父类限制子类的行为(抽象类) 还可以用异常捕获主动报错 class Animal(): def speak(self): raise Exception("必须实现speak方法")# 主动报错出去 class People(Animal): pass class Pig(): def speak(self): print('哼哼哼') class Dog(): def speak(self): print('汪汪汪')obj = People() obj.speak()# 一切皆文件 只要类中含有read,write方法 就看做文件类 class Txt: def read(self): passdef write(self): passclass Process(): def read(self): passdef write(self): pass

面向对象的特征之继承
文章图片

    推荐阅读