首页 > 其他 > 详细

第38讲:类和对象——继承

时间:2020-08-15 17:35:37      阅读:67      评论:0      收藏:0      [点我收藏+]

一  继承

1 继承的基本概念

  • 定义:继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。
  • 分类:python中类的继承分为:单继承和多继承
  • 语法:
    1 class 类名(父类1, 父类2, ...):
    2     #类定义部分
  • 特点:
    • 如果该类没有显式指定继承自哪个类,则默认继承 object 类(object 类是 Python 中所有类的父类/基类,即要么是直接父类,要么是间接父类)。
    • Python 的继承是多继承机制(和 C++ 一样),即一个子类可以同时拥有多个直接父类。
  • 查看:
    • 类名.__base__:只查看从左到右继承的第一个子类
    • 类名.__bases__:查看所有继承的父类
  • 经典类与新式类:
    • 只有在python2中才分新式类和经典类,python3中统一都是新式类
    • 在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类
    • 在python2中,显式地声明继承object的类,以及该类的子类,都是新式类
    • 在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

2 继承与抽象(先抽象再继承)

  • 抽象:
    • 即抽取类似或者说比较像的部分。
    • 抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
    • 抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
  • 继承:
    • 是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
    • 继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承

3 继承与重用性

  • 代码重用:通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用
  • 开发过程中,不仅可以重用自己的类,也可以继承别人的,比如标准库,来定制新的数据类型,这样就是大大缩短了软件开发周期,对大型软件开发来说,意义重大.

4 派生

  • 定义:它和继承是一个意思,只是观察角度不同而已。换句话说,继承是相对子类来说的,即子类继承自父类;而派生是相对于父类来说的,即父类派生出子类。
  • python父类方法的重写:
    • 适用情况:对于父类中的一些方法,子类对象不能直接使用时,必须将这些方法在子类中重新定义一遍,即重写
    • 定义:重写,有时又称覆盖,是一个意思,指的是对类中已有方法的内部实现进行修改。
    • 举例:
      技术分享图片
       1 class Bird:
       2     #鸟有翅膀
       3     def isWing(self):
       4         print("鸟有翅膀")
       5     #鸟会飞
       6     def fly(self):
       7         print("鸟会飞")
       8 class Ostrich(Bird):
       9     # 重写Bird类的fly()方法
      10     def fly(self):
      11          print("鸵鸟不会飞")
      12 
      13 # 创建Ostrich对象
      14 ostrich = Ostrich()
      15 #调用 Ostrich 类中重写的 fly() 类方法
      16 ostrich.fly()
      方法重写
    • 调用重写之后的方法:子类对象名.重写后的方法,例如"ostrich.fly()"语句
    • 调用被重写方法:父类名.被重写的方法名(子类对象名)
      • 技术分享图片
        1  # 创建Ostrich对象
        2  ostrich = Ostrich()
        3  #调用 Bird 类中的 fly() 方法
        4  Bird.fly(ostrich)
        View Code
      • Python 中的类可以看做是一个独立空间,而类方法其实就是出于该空间中的一个函数。
      • 而如果想要全局空间中,调用类空间中的函数,只需要在调用该函数时备注类名即可。
      • 使用类名调用其类方法,Python 不会为该方法的第一个 self 参数自定绑定值,因此采用这种调用方法,需要手动为 self 参数赋值。

5 关于python的多继承

  • 大部分面向对象的编程语言,都只支持单继承,即子类有且只能有一个父类。而Python 却支持多继承(C++也支持多继承)
  • 和单继承相比,多继承容易让代码逻辑复杂、思路混乱,一般较少使用
  • 使用多继承经常需要面临的问题是,多个父类中包含同名的类方法
    • 对于这种情况,Python 的处置措施是:根据子类继承多个父类时这些父类的前后次序决定,即排在前面父类中的类方法会覆盖排在后面父类中的同名类方法。
    • 代码:
    • 技术分享图片多个父类中包含同名类方法解决办法
    • 运行结果:
    • 1 People类 张三

6 继承的实现原理

  • 继承顺序问题(继承了多个类):
    • Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先
    • 技术分享图片
  • 经典类和新式类的区别:
    • 语法区分:是否继承了object类
      • 技术分享图片
    • 多继承查找方式区分:
      • 当类是经典类时,多继承情况下,会按照深度优先方式查找
        • 技术分享图片
          1 class D:
           2 
           3     def bar(self):
           4         print D.bar
           5 
           6 
           7 class C(D):
           8 
           9     def bar(self):
          10         print C.bar
          11 
          12 
          13 class B(D):
          14 
          15     def bar(self):
          16         print B.bar
          17 
          18 
          19 class A(B, C):
          20 
          21     def bar(self):
          22         print A.bar
          23 
          24 a = A()
          25 # 执行bar方法时
          26 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
          27 # 所以,查找顺序:A --> B --> D --> C
          28 # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
          29 a.bar()
          30 
          31 经典类多继承
          
          经典类多继承
          经典类多继承
        • 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
      • 当类是新式类时,多继承情况下,会按照广度优先方式查找
        • 技术分享图片
          1 class D(object):
           2 
           3     def bar(self):
           4         print D.bar
           5 
           6 
           7 class C(D):
           8 
           9     def bar(self):
          10         print C.bar
          11 
          12 
          13 class B(D):
          14 
          15     def bar(self):
          16         print B.bar
          17 
          18 
          19 class A(B, C):
          20 
          21     def bar(self):
          22         print A.bar
          23 
          24 a = A()
          25 # 执行bar方法时
          26 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
          27 # 所以,查找顺序:A --> B --> C --> D
          28 # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
          29 a.bar()
          30 
          31 新式类多继承
          
          新式类多继承
          新式类多继承

          首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

  • 继承原理(python如何实现继承)
    • 原理:
      • python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表——F.mro() #等同于F.__mro__
      • 为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
    • MRO列表
      • 构造:通过一个C3线性化算法来实现
      • 实质:它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
        • 子类会先于父类被检查
        • 多个父类会根据它们在列表中的顺序被检查
        • 如果对下一个类存在两个合法的选择,选择第一个父类

7 子类中调用父类的方法

  • 问题:
    • 当一个子类继承多个类时,在创建子类的对象后,程序运行可能会出错;
    • 因为不同父类的构造方法之间会被覆盖,导致有些父类的构造方法没有得到正确的参数;
    • 为解决该问题,正确的做法是在子类中定义自己的构造方法(等同于重写第一个直接父类的构造方法),并且必须在该方法中调用第一个直接父类的构造方法
  • 调用第一个父类的构造方法:
    • 方法一:父类名.父类构造方法()
    • 方法二:super()
      • Python 2.x 语法:
        1 super(Class, obj).__init__(self,...)
      • python 3.x 语法:
        1 super().__init__(self,...)
  • 上述两种方式也可用于调用父类中的其它方法:
    • 方法一:父类名.父类方法()
      • 技术分享图片
        1 #_*_coding:utf-8_*_
         2 __author__ = Linhaifeng
         3 
         4 class Vehicle: #定义交通工具类
         5      Country=China
         6      def __init__(self,name,speed,load,power):
         7          self.name=name
         8          self.speed=speed
         9          self.load=load
        10          self.power=power
        11 
        12      def run(self):
        13          print(开动啦...)
        14 
        15 class Subway(Vehicle): #地铁
        16     def __init__(self,name,speed,load,power,line):
        17         Vehicle.__init__(self,name,speed,load,power)
        18         self.line=line
        19 
        20     def run(self):
        21         print(地铁%s号线欢迎您 %self.line)
        22         Vehicle.run(self)
        23 
        24 line13=Subway(中国地铁,180m/s,1000人/箱,,13)
        25 line13.run()
        非绑定方法
    • 方法二:super()
      • 技术分享图片
        1 class Vehicle: #定义交通工具类
         2      Country=China
         3      def __init__(self,name,speed,load,power):
         4          self.name=name
         5          self.speed=speed
         6          self.load=load
         7          self.power=power
         8 
         9      def run(self):
        10          print(开动啦...)
        11 
        12 class Subway(Vehicle): #地铁
        13     def __init__(self,name,speed,load,power,line):
        14         #super(Subway,self) 就相当于实例本身 在python3中super()等同于super(Subway,self)
        15         super().__init__(name,speed,load,power)
        16         self.line=line
        17 
        18     def run(self):
        19         print(地铁%s号线欢迎您 %self.line)
        20         super(Subway,self).run()
        21 
        22 class Mobike(Vehicle):#摩拜单车
        23     pass
        24 
        25 line13=Subway(中国地铁,180m/s,1000人/箱,,13)
        26 line13.run()
        super()函数

二 课后作业

 

第38讲:类和对象——继承

原文:https://www.cnblogs.com/luoxun/p/13509335.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!