【进阶Python】第七讲:接口与抽象基类

简介: 抽象基类(abstract base class,ABC),提到这个概念应该会马上联想到面向对象、继承。作为继承的一种,它拥有继承中代码共享、提高代码的重用性等优点,此外它还拥有接口相关的一些特性,本文就来介绍一下Python抽象基类的使用。

前言

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

class Animal(object):
    def eat(self, kind):
        print("{} eat food....".format(kind))
class Dog(Animal):
    pass
class Cat(Animal):
    pass
dog = Dog()
cat = Cat()
dog.eat("dog")
cat.eat("cat")
# 输出
dog eat food....
cat eat food....

狗(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 abc import ABC
from abc import abstractmethod
class Database(ABC):
    def register(self, host, user, password):
        print("Host : {}".format(host))
        print("User : {}".format(user))
        print("Password : {}".format(password))
        print("Register Success!")
    @abstractmethod
    def query(self, *args):
        """
        传入查询数据的SQL语句并执行
        """
    @staticmethod
    @abstractmethod
    def execute(sql_string):
        """
        执行SQL语句
        """

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

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

class Component1(Database):
    def __init__(self, host, user, password):
        self.register(host, user, password)
    @staticmethod
    def execute(sql_string):
        print(sql_string)
    def query(self, *args):
        sql_string = "SELECT ID FROM db_name"
        self.execute(sql_string)
class Component2(Database):
    def __init__(self, host, user, password):
        self.register(host, user, password)
    @staticmethod
    def execute(sql_string):
        print(sql_string)
    def query(self, *args):
        sql_string = "SELECT NAME FROM db_name"
        self.execute(sql_string)
comp1 = Component1("00.00.00.00", "abc", "000000")
comp2 = Component2("11.11.11.11", "ABC", "111111")
comp1.query()
comp2.query()
# 输出结果
Host : 00.00.00.00
User : abc
Password : 000000
Register Success!
Host : 11.11.11.11
User : ABC
Password : 111111
Register Success!
SELECT ID FROM db_name
SELECT NAME FROM db_name

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

相关文章
|
1月前
|
C语言 Python
python 调用c接口
【10月更文挑战第12天】 ctypes是Python的一个外部库,提供和C语言兼容的数据类型,可以很方便地调用C DLL中的函数
49 0
|
1月前
|
JSON 缓存 API
在 Python 中使用公共类处理接口请求的响应结果
在 Python 中使用公共类处理接口请求的响应结果
29 1
|
2月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
107 6
|
2月前
|
Java Python
全网最适合入门的面向对象编程教程:50 Python函数方法与接口-接口和抽象基类
【9月更文挑战第18天】在 Python 中,虽无明确的 `interface` 关键字,但可通过约定实现类似功能。接口主要规定了需实现的方法,不提供具体实现。抽象基类(ABC)则通过 `@abstractmethod` 装饰器定义抽象方法,子类必须实现这些方法。使用抽象基类可使继承结构更清晰、规范,并确保子类遵循指定的方法实现。然而,其使用应根据实际需求决定,避免过度设计导致代码复杂。
|
2月前
|
Python
全网最适合入门的面向对象编程教程:Python函数方法与接口-函数与方法的区别和lamda匿名函数
【9月更文挑战第15天】在 Python 中,函数与方法有所区别:函数是独立的代码块,可通过函数名直接调用,不依赖特定类或对象;方法则是与类或对象关联的函数,通常在类内部定义并通过对象调用。Lambda 函数是一种简洁的匿名函数定义方式,常用于简单的操作或作为其他函数的参数。根据需求,可选择使用函数、方法或 lambda 函数来实现代码逻辑。
|
3月前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
3月前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
3月前
|
存储 测试技术 数据库
Python接口自动化测试框架(练习篇)-- 函数编程(一)
本文通过实际的编程练习,讲解了面向过程编程的概念和应用,包括如何定义函数、处理文件读写以及实现用户注册功能,最终将这些过程封装成函数,体现了Python作为脚本语言的面向过程编程特性。
28 2
|
3月前
|
API 开发工具 数据安全/隐私保护
【Azure Developer】Python 获取Micrisoft Graph API资源的Access Token, 并调用Microsoft Graph API servicePrincipals接口获取应用ID
【Azure Developer】Python 获取Micrisoft Graph API资源的Access Token, 并调用Microsoft Graph API servicePrincipals接口获取应用ID
|
3月前
|
JSON jenkins 测试技术
Python接口自动化测试框架(工具篇)-- 接口测试工具HTTPRUNNER
本文介绍了Python接口自动化测试框架HTTPRunner,包括其安装、使用方法,并通过实际操作演示了如何利用HTTPRunner进行接口测试,同时还探讨了HTTPRunner作为接口自动化测试解决方案的可能性和实用性。
67 0