(二十二)类与对象 ---- 继承

什么时候用继承?

1.当类之间有显著不同,且较小的类是较大的类的组件时,用组合比较好

比如机器人类是一个大类,躯干类、胳膊类、腿类是小类

2.当类之间有很多相同的属性与功能,提取这些共性作为基类,用继承比较好

比如鸡和鸭,我们可以提取他们的共性(两只翅膀、用两只脚走路)做一个禽类,但是他们也有各自独特的个性(鸡会打鸣,鸭会游泳)

class qing():                                 #共性提取为一个基类(禽类)
    wing = 2                                  #父类数据属性
    def __init__(self,owner):          
        self.owner = owner
    def walk(self):                           #父类函数属性
        print(‘%s用两只脚走路‘ %self.owner)

class ji(qing):                               #鸡类继承禽类
    def da_ming(self):                        #子类有自己的函数属性
        print(‘%s会打鸣‘ %self.owner)

class ya(qing):                               #鸭类继承禽类
    def you_yong(self):                       #子类有自己的函数属性
        print(‘%s会游泳‘ %self.owner)

j1 = ji(‘小王家的鸡‘)                           #鸡类实例化
j1.da_ming()                                  #可以调用实例自己的函数属性
j1.walk()                                     #可以调用实例继承来的函数属性

y1 = ya(‘小明家的鸭‘)                           #鸭类实例化
y1.you_yong()
y1.walk()结果:

小王家的鸡会打鸣
小王家的鸡用两只脚走路
小明家的鸭会游泳
小明家的鸭用两只脚走路

继承有两种含义

含义一:子类继承基类的方法,并且做出自己的改变或扩展(代码重用),如上禽类的例子

含义二:基类是一个接口类,子类继承这个接口类,并实现接口中定义的方法

实践中,继承的第一种含义意义并不大,甚至是有害的,因为这种方式使得子类与基类出现强耦合

继承的第二种含义就很重要了,它又叫“接口继承”

接口继承实质上做了一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可以一视同仁的处理实现了接口的所有对象——程序设计上,这叫归一化

就像linux的泛文件概念(一切皆文件),所有东西都可以当文件处理,不必关心它是内存、磁盘还是网络(然后在内存、磁盘和网络的子类中,再去做针对性的底层设计,即具体实现接口类中定义的接口)

如何强制子类必须实现基类中某些指定的方法和属性,否则就抛异常?python的abc模块就满足了这个需求。

import abc
class All_file(metaclass=abc.ABCMeta):          #abc.ABCMeta是一个用于实现抽象类的一个基础类
    @abc.abstractmethod                         #加上@abstractmethod之后,如果需要用到的这个方法则必须用新的方法将其实现
    def read(self):                             #子类必须实现读方法
        pass                                    #接口类不用实现逻辑,只是用来规范子类
    @abc.abstractmethod                         #子类必须实现写方法
    def write(self):
        pass

class Disk(All_file):
    def read(self):
        print(‘disk read‘)

    def write(self):
        print(‘disk write‘)

class Cdrom(All_file):
    def read(self):
        print(‘cdrom read‘)

    def write(self):
        print(‘cdrom write‘)

class Mem(All_file):
    def read(self):
        print(‘mem read‘)

    def write(self):                     #如果这个write方法不写,将报错:TypeError: Can‘t instantiate abstract class Mem with abstract methods write
        print(‘mem write‘)

m1=Mem()
m1.read()                     #mem read
m1.write()                    #mem write

1.接口类的作用只是用来规范子类,所以他不用实现逻辑,写个pass就ok

2.接口类不需要被实例化,也没有这个必要

3.子类如果继承了接口类,就一定要实现接口类中加了@abstractmethod的方法

继承的顺序

python的类可以继承多个类,如果继承多个类,那么其继承顺序的方式有:深度优先和广度优先
基类或者父类继承了object类,那么该类就是新式类,否则便是经典类
注意:python3中统一都是新式类,pyhon2中才分新式类与经典类
当类是经典类时,多继承情况下,会按照深度优先方法查找
当类时新式类时,多继承情况下,会按照广度优先方法查找

class A:
    def test(self):
        print(‘A‘)
    pass
class B(A):
    def test(self):
        print(‘B‘)
    pass
class C(A):
    def test(self):
        print(‘C‘)
    pass
class D(B):
    def test(self):
        print(‘D‘)
    pass
class E(C):
    def test(self):
        print(‘E‘)
    pass
class F(D,E):
    def test(self):
        print(‘F‘)
    pass
f1=F()                   #python3都是新式类,广度优先,所以继承顺序是:F--D--B--E--C--A
f1.test()   

print(F.__mro__)  #(<class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>)

B.C继承A,D继承B,E继承C,F继承D,E,我们看下F的继承顺序:

如果是新式类,继承的顺序是:F--D--B--E--C--A,如图中绿线所示,左边的线不会找到头,这就是所谓的广度优先

如果是经典类,继承的顺序是:F--D--B--A--E--C,如图中红线所示,左边的线直接找到头,这就是所谓的深度优先

Python到底是如何实现继承的?

对于定义的每一个类,Python会计算一个方法解析顺序列表(MRO列表),这个MRO列表就是一个简单的所有基类的线性顺序列表

为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止

MRO列表遵循以下三条准则:

  • 子类会先于父类被检查;
  • 多个父类会根据它们在列表中的顺序被检查;
  • 如果对下一个类存在两个合法的选择,则选择第一个类;

注意:只有新式类才有.__mro__这个属性,可以查看线性列表,经典类没有这个属性

在子类中调用父类方法

class People:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def run(self):
        print(‘%s 在跑!‘%self.name)

class China(People):
    def __init__(self,name,age,country):
        People.__init__(self,name,age)                  #子类中调用父类的__init__方法,可以用super().__init__(name,age) 代替,注意用super()调用父类的方法时不用传self
        self.country = country
    def run(self):
        People.run(self)                                #子类中调用父类的run方法  可以用super().run()代替
        print(‘%s人 %s 在跑!‘%(self.country,self.name))

p2 = China(‘Tom‘,26,‘中国‘)
p2.run()

原文地址:https://www.cnblogs.com/xulan0922/p/10339245.html

时间: 2024-11-06 03:40:46

(二十二)类与对象 ---- 继承的相关文章

JAVA之旅(二十二)——Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习

JAVA之旅(二十二)--Map概述,子类对象特点,共性方法,keySet,entrySet,Map小练习 继续坚持下去吧,各位骚年们! 事实上,我们的数据结构,只剩下这个Map的知识点了,平时开发中,也是能看到他的,所以还是非常值得去学习的一个知识点的,我们直接开车了 一.Map概述 泛型< k,v> 键值对,映射关系 基本特点 该集合存储键值对,是一对一对往里存,而且要保证键的唯一性 1.添加 put(key ,values) putAll() 2.删除 clear() remove(ob

(转)Inno Setup入门(二十二)——Inno Setup类参考(8)

本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17268473 列表框 列表框(ListBox)是Windows应用程序中重要的输入手段,其中包括多个选项用户可以从其中选择一个或者多个,程序根据用户的选择做出相应的处理,列表框在外观上和存储框类似,但是行为却有很大的不同,列表框中项一般是预先给定的,而存储框则可以让用户进行输入,并且列表框中的项被选择之后也会触发事件.Pascal脚本中列表框的类由TlistBox实

QT开发(二十二)——QMainWindow主窗口

QT开发(二十二)--QMainWindow主窗口 一.主窗口简介 应用程序中的主窗口是与用户进行长时间交互的顶层窗口,提供了应用程序的大部分功能,通常是应用程序启动后的第一个窗口,应用程序一般由一个主窗口和多个对话框组成. QT中直接支持主窗口,QMainWindow是QT中主窗口的基类,是继承于QWidget类的容器型组件. QMainWindow内部封装了菜单栏.工具栏.中心组件.停靠组件.状态栏等. QMainWindow内置了布局管理器,基本的组件布局如下: 二.菜单栏 QT中提供了预

企业搜索引擎开发之连接器connector(二十二)

下面来分析线程执行类,线程池ThreadPool类 对该类的理解需要对java的线程池比较熟悉 该类引用了一个内部类 /** * The lazily constructed LazyThreadPool instance. */ private LazyThreadPool lazyThreadPool; 该成员实现了单例模式,即该对象只有一个实例,属于懒汉式单例模式,当实例化该成员时,启用了线程同步机制 /** * Shut down the {@link ThreadPool}. Afte

从零开始学android&lt;SeekBar滑动组件.二十二.&gt;

拖动条可以由用户自己进行手工的调节,例如:当用户需要调整播放器音量或者是电影的播放进度时都会使用到拖动条,SeekBar类的定义结构如下所示: java.lang.Object ? android.view.View ? android.widget.ProgressBar ? android.widget.AbsSeekBar ? android.widget.SeekBar 常用方法 public SeekBar(Context context) 构造 创建SeekBar类的对象 publi

《Programming in Lua 3》读书笔记(二十二)

日期:2014.8.6 PartⅣ The C API 26 Extending Your Application 使用Lua很重要的一点是用来做配置语言.配合主语言做一些功能的配置. 26.1 The Basics 有的时候程序需要配置一些功能信息,很多时候可能有许多别的方法比用lua做配置要更简单:如使用环境变量或者读取文件,读取文件涉及到文件的解析.如果使用Lua进行配置的话,相当于用lua文件替代了要读取的如csv.txt文件等. 使用Lua进行配置的时候,就需要使用Lua API去控制

微软云计算介绍与实践(实践之二十二)

创建私有云Runbook 小张目前是手动管理大量(由晓红申请)的私有云.而自动化是私有云的重要特点,所以小张想用自动化功能去完成很多简单机械的任务.小张决定设法实现这一目标,利用System Center 2012 Orchestrator.于是我们看到了下面的内容: 1.登录到Orchestrator服务器Orchestrator 2.打开Runbook设计 3.在左边的连接下,在运行手册单击鼠标右键并选择New...>文件夹 4.给新文件夹的名称,例如CloudResources 5.在新创

二十二、android中application标签说明

<application> <applicationandroid:allowClearUserData=["true" | "false"]android:allowTaskReparenting=["true" | "false"]android:backupAgent="string"android:debuggable=["true" | "false

【管理心得之二十二】小人物 仰视 大授权

场景再现====================Boss:小王,来我办公室一下.小王: 嗯Boss:近期总公司有会,需要到外地出差几日.我不在的这段期间里,公司大小事务你帮忙处理一下.          如果有什么难决定的事,第一时间电话.邮件联系我商定即可.小王:  明白.放心吧领导,绝不会让你失望的Boss:嗯,那就好,没事了. {小王走出办公室} 心中暗喜,"难道这就是传说中的授权,Boss不在的时候,我岂不是最高权力的行使者." ==================== 从场景

每日算法之二十二:Swap Nodes in Pairs

Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2->3->4, you should return the list as 2->1->4->3. Your algorithm should use only constant space. You may not modify the values in the list, on