完整代码>>

前言

抽象基类(abstract base class,ABC),提到这个概念应该会马上联想到面向对象、继承。作为继承的一种,它拥有继承中代码共享、提高代码的重用性等优点。例如,下面示例,

class 

狗(Dog)和猫(Cat)都属于动物(Animal),它们有很多类似的属性和动作,我们可以在父类中实现这些方法,在子类中直接继承或者重载父类中的方法,这样减少了代码的重复性,提高了代码的共享能力。

作为继承的一种,抽象基类有用继承的上述这些优点,但是它与普通的继承也有不同之处,

  • 抽象基类不能实例化
  • 子类需要实现基类指定的抽象方法

看到这里应该会意识到,抽象基类有一种接口的感觉,没错,抽象基类的出现主要是功能就是类似于Java等编程语言中的接口。但是需要明确一点,Python语言中没有interface这个概念,只是这是一种约定俗成的编程规范,就如同Python也没有真实意义上的私有变量,我们在编程中可以规范的使用下划线来表示某个变量为私有变量。

尽管Python中没有接口这个关键字,但是抽象基类实现的功能主要围绕接口在展开,因此,首先类比Java来阐述一下编程语言中接口的概念,然后介绍一下Python中如何实现抽象基类。

接口

接口(Interface)是对象公开方法的一种集合,在Java中通常以interface关键字来定义,接口虽然实现过程中和相似,但是却具有不同的概念。具体而言,类与接口主要有以下几点不同之处:

  • 类实现了对象的属性和方法,而接口指定了使用该接口需要实现哪些方法
  • 类可以实例化,而接口不可以被实例化
  • 类中的方法可以是实现,接口中的方法都是抽象方法

抽象方法:抽象方法的概念是父类中只负责声明该方法,但不具体实现这个方法,实现部分由继承该类的子类负责实现。

如果觉得上述描述有点云里雾里、对接口的概念依然不是非常清楚,不妨来试想一个场景:当你开发一个项目或者服务,你需要给上下游的组件提供接口,让别人来调用你的程序接口(Application Programming Interface,API),上下游组件该怎么样才能达到想要的目的和你的组件无缝衔接?需要通过按照你接口中规定的抽象方法来实现,例如,你提供一个访问网络请求的接口,你不会去实现host、username、password的注册和发送请求,这些需要调用的用户去实现,你只需要规定:“调用者必须实现指定方法才能实现调用”即可。

抽象基类

虽然Python中抽象基类和接口概念非常相近,但是它们还是有一些不同之处,例如,

  • 接口需要被实现的子类完成接口中指定的所有方法,而抽象基类不是,抽象基类则没有这么严格的要求
  • 接口需要所有方法都是抽象方法,而抽象基类中有抽象方法,也有自己实现的方法

正是因为抽象基类和接口的不同之处使得接口之所以称为接口、抽象基类之所以称为抽象基类。

为什么使用抽象基类?

前面铺垫了这么多,话说回来,为什么需要抽象基类?

存在的即是合理的,抽象基类的存在自然有它的价值。当你学会一种编程语言的语法时,你可以轻松的完成一项功能的开发,但是如果希望把代码完成的更加优美高效,那么就需要在设计模式等方面下一些功夫,抽象基类就是其中的一个选择,抽象基类具有以下优点:

  • 处理继承问题方面更加规范、系统
  • 明确调用之间的相互关系
  • 使得继承层次更加清晰
  • 限定子类实现的方法

什么是抽象基类?

前面已经介绍了很多有关接口的概念,抽象基类和接口有很多相似之处,例如需要包含抽象方法,不能被实例化,如果更加确切的定义抽象基类:必须包含一个抽象函数(纯虚函数),它是一个不完整的类,它有已经被实现的方法,也有需要子类重写的方法。

抽象基类使用场景

一项功能只有具有应用场景才能体现出它的价值,如果仅仅是为了看上去高逼格,那么倒不如使用最简单的条件、循环语句,没必要花里胡哨,让代码变得难以维护、晦涩难懂。

抽象基类首先它具备普通继承的功能,因此,在代码可以共用,或者需要获取额外属性的时候可以考虑使用抽象基类,例如,狗、猫、牛、羊这些动物有很多共有的属性和方法,我们可以通过实现一个基类,让每个特定的对象来继承它,这样不仅可以实现多态,还可以提高代码的复用能力。

当然,上述说的这些场景都偏重于普通继承的优势,而抽象基类的特别之处更加偏向于接口的特点,因此,它的使用场景和接口也有很多相通之处,例如我们开发一个系统,下面有若干个组件,每个组件都需要按照指定的规范来实现特定的方法,这时候我可以发挥抽象基类的限定功能的优势

下面就结合这个场景来介绍Python中抽象基类的实现方法。

Python抽象基类

场景介绍

假如我们现在实现了一个数据中台的开发,我们对外提供一个接口让不同组件通过这个接口进行访问数据库,来读取数据,我们给数据接口主要有2个功能,

  • 登录数据库
  • 读取数据
  • 执行SQL语句

可以想象,登录数据库这个功能在不同组件之间可以共用,不同组件只需要提供host、user、passwd即可,至于读取数据这是每个组件都必须单独实现的,可以声明为抽象方法,执行SQL语句也是每个子类需要实现的,可以声明为抽象的静态方法。

实现

Python标准库中有一个模块abc可以实现抽象基类和抽象方法,它们的实现方式如下:

抽象基类:通过继承abc模块中的ABC类来实现抽象基类。

抽象方法:通过装饰器的方法来调用abc模块中abstractmethod方法来注解抽象基类的方法。

abstractmethod注解除了可以实现抽象方法外,还可以注解类方法(@classmethod)、静态方法(@staticmethod)、属性(@property)。

下面就先实现抽象基类,

from 

从抽象基类Database的实现可以看出,它共包含3个方法,其中register是每个子类都需要的,直接实现在抽象基类里,是一个普通的类方法。queryexecute只是在基类中进行类声明,给出了描述,但并没有实现,它限定了继承Database的子类必须实现这两个方法。

下面就来实现两个组件(子类),

class 

上述是通过Python标准库中abc模块实现了抽象基类,其实在Python中collections中也实现了抽象基类,numbers中也定义了有关数字对象的抽象基类,可见,抽象基类在Python中占据着至关重要的地位。

完整代码

本文所涉及的完整代码可以查看github项目advance-python,也可以直接访问下方链接,

Jackpopc/advance-python​github.com


干货

最近,为了方便大家,我花费了半个月的时间把这几年来收集的各种技术干货整理到一起,其中内容包括但不限于Python、机器学习、深度学习、计算机视觉、推荐系统、Linux、工程化、Java,内容多达5T+,我把各个资源下载链接整理到一个文档内,目录如下:

所有干货送给大家,希望能够点赞支持一下!

https://pan.baidu.com/s/1eks7CUyjbWQ3A7O9cmYljA (提取码:0000)

精选作品

Jackpop:强烈推荐 | 这将会成为一个优质的github项目

Jackpop:计算机小白如何开始机器学习的学习,有入门课程推荐吗?

Jackpop:C盘快满了,该如何清理?

Jackpop:学习pytorch该怎么提高自己的代码能力?

使用“override”声明的成员函数不能重写基类成员_【进阶Python】第七讲:接口与抽象基类...相关推荐

  1. JAVA面向对象中继承的子父类成员函数的内存图解,以及成员函数中的覆盖的应用.

    JAVA中继承子父类成员函数的使用 我把成员函数理解为就是类里面的功能,或者说是方法. 子父类的成员函数调用可以是这样的 例如: class Fu{void show1(){System.out.pr ...

  2. 使用“override”声明的成员函数不能重写基类成员_C++日志(三十五)虚基类与其子类的构造函数...

    第三十四篇日志中提到,子类对象调用父类同名的函数时需要使用作用域标识符进行限定,这是在任何继承情况下都可以使用的普适方法. 问题引入: 考虑一种特殊的情况:子类全部或部分的基类(称为中间基类)同是继承 ...

  3. 绑定成员函数表达式上的非法操作_在优麒麟上使用MPV编写自己的播放器

    上一期,小编给大家简要介绍了MPV的配置和使用方法,虽然MPV功能强大,但默认情况下,MPV无GUI图形界面,用户需要通过命令行或者手动修改其配置文件达到配置MPV的目的,这样就给普通用户带来了诸多不 ...

  4. 指向成员函数的指针有什么用_指针函数,函数指针,有点懵圈了?你能分清楚吗...

    指针函数和函数指针到底怎么区分? 1.前言 数组.指针,这两个词结合的顺序不同,其意义也不同. 同样的,函数.指针这两个词结合的顺序不同其意义也不同,即指针函数与函数指针的意义不同. 2.指针函数 指 ...

  5. python中matrix函数_使用python解线性矩阵方程(numpy中的matrix类)

    这学期有一门运筹学,讲的两大块儿:线性优化和非线性优化问题.在非线性优化问题这里涉及到拉格朗日乘子法,经常要算一些非常变态的线性方程,于是我就想用python求解线性方程.查阅资料的过程中找到了一个极 ...

  6. python中函数提高代码执行速度吗_为什么Python代码在一个函数中运行得更快?

    匿名用户 除了局部/全局变量存储时间外,操作码预测使函数更快. 正如其他答案所解释的,该函数在循环中使用store_fast操作码.下面是函数循环的字节码:>> 13 FOR_ITER 6 ...

  7. python 函数前有一个下划线_【Python】怎么写好一个 Python 函数?

    1. 命名 符合 PEP-8 函数命名书写规范的是小写+下划线或者比较常用的驼峰命名法.内容方面是动宾结合. 举个例子: def setUserName(String userName):pass 推 ...

  8. python 中定义的函数 如何在main中调用_在python中,在定义类时自动运行函数的方法?_class_酷徒编程知识库...

    类定义时初始化类属性,不需要函数.import numpy as np class Foo: bar = np.range(100) def __init__(self): # etc. 如果要在导入 ...

  9. python函数中的变量取出来_在Python中从函数调用中提取变量

    我试图提取函数接收到的Python字符串.在 考虑以下因素: 我有一个用Python运行的脚本.脚本将继续运行.它绑定到一个USB端口,监听进入的ZigBee数据帧.在 我有一个分解这个数据帧的函数# ...

  10. python 查找函数所在模块和文件位置_查看python的模块和函数帮助文档方法

    python的一个优势是有着大量自带和在线的模块(module)资源,可以提供丰富的功能,在使用这些模块的时候,如果每次都去网站找在线文档会过于耗费时间,结果也不一定准确.因此这里介绍下python自 ...

最新文章

  1. qq邮箱高频率邮件来源自动屏蔽的信任办法
  2. easyUI droppable组件使用
  3. Javascript高级程序设计第二版第四章--变量,作用域及内存问题--笔记
  4. 配置环境将win32项目移植到Android
  5. setTimeout和setInterval方法
  6. PHP实习之路—NO.1(看LINUX、APACHE、MYSQL、PHP文档)
  7. charles代理手机调试_Mac 上使用 Charles 进行手机抓包调试
  8. 《网站安全攻防秘笈》摘录
  9. 【CCFCSP - 201403-4】无线网络(分层图最短路)
  10. gridsearchcv参数_Python机器学习库Sklearn系列教程(21)-参数优化
  11. [Python] L1-040. 最佳情侣身高差 团体程序设计天梯赛GPLT
  12. php mysql修复_php简单备份与还原MySql的方法 | 瑕疵学院 – 学习无瑕疵,成就有保障...
  13. 从SAP BPC中Entity维设计的理念考虑Web程序中类似文档库之类的设计该考虑的东西...
  14. java中访问权限的设置
  15. 软件测试 集成测试
  16. Kotlin习惯用语和编码风格[转自Kotlin中文文档]
  17. 在Spring AOP切面中启用新事务
  18. phpspider案例
  19. 使用fiddler绕过“请在微信客户端打开链接”
  20. java word文档_[转载]java读写word文档,完美解决方案

热门文章

  1. dubbo如何正确关闭Spring容器
  2. WIN2003 IIS6.0+PHP+ASP+MYSQL优化配置
  3. redhat/centos下的lamp
  4. 数据结构 - 字符串的模式匹配
  5. Spring 下 MyBatis 的基本使用
  6. Mysql几种索引类型的区别及适用情况
  7. win7上安装mysql数据库_mysql-windows系统安装mysql数据库
  8. 拓端tecdat|R语言ggmap空间可视化机动车交通事故地图
  9. (15)Python识别文字,tesseract包
  10. (2)机器学习_train_test_split