
接口是面向对象编程 (OOP) 的基石,使开发人员能够为其代码定义一致的协定,虽然 Python 像其他语言一样缺少专用关键字,但它通过抽象基类 (ABC) 实现接口功能。
作为一名软件工程师,我参与过定义健壮接口至关重要的项目,没有它们,扩展系统就会变得混乱,调试问题是一场噩梦,在这种情况下,Python 的 ABC 一直是救星,有助于实施设计规则并使代码库更易于管理。
在本文中,我将解释 ABC 的工作原理、为什么它们必不可少,以及我如何在实际项目中使用它们,我还将引导你使用 ABC 设计插件系统,重点介绍它们在确保灵活性和可靠性方面的作用。
接口指定类必须实现的方法,充当协定,这确保了不同实施之间的一致性,同时允许灵活地实现功能。
几年前,我在一个支持多种支付网关(如 PayPal、Stripe 和 BankTransfer)的电子商务平台上工作。每个网关都需要处理 和 等操作。process_paymentvalidate_transaction
最初,我们没有强制执行严格的接口,开发人员会以不同的方式实现支付方式,经常遗漏或错误命名关键方法,这会导致运行时错误,并使新开发人员难以入职。
引入界面改变了游戏规则,它确保所有支付网关都遵循相同的结构,使系统更易于维护和扩展。
Python 的模块允许你创建类似于接口的抽象基类 (ABC),它们允许:
定义 subclasses 必须实现的方法。
防止实例化不完整的实现。
在类创建期间(而不是在运行时)及早检测实现问题。
让我逐步向你展示如何定义和使用 ABC。
以下是使用 ABC 的支付网关接口的示例:
from abc import ABC, abstractmethodclassPaymentGateway(ABC): @abstractmethoddefprocess_payment(self, amount):"""Process the payment of a specified amount."""pass @abstractmethoddefvalidate_transaction(self, transaction_id):"""Validate a transaction using its ID."""pass此类定义支付网关的接口,装饰器确保任何子类都必须实现这些方法。@abstractmethod
现在让我们创建两个支付网关实现:
classPayPal(PaymentGateway):defprocess_payment(self, amount):print(f"Processing payment of ${amount} via PayPal.")defvalidate_transaction(self, transaction_id):print(f"Validating PayPal transaction ID: {transaction_id}")classStripe(PaymentGateway):defprocess_payment(self, amount):print(f"Processing payment of ${amount} via Stripe.")defvalidate_transaction(self, transaction_id):print(f"Validating Stripe transaction ID: {transaction_id}")
both 和 implementation 所需的方法,遵守 定义的协定。
如果有人忘记实现 required 方法,会发生什么情况?Python 不允许实例化类:
classIncompleteGateway(PaymentGateway):passtry: gateway = IncompleteGateway()except TypeError as e: print(f"Error: {e}")输出:
Error: Can't instantiate abstract class IncompleteGateway with abstract method process_payment这是 ABC 最有价值的功能之一 — 它们在开发过程中尽早发现错误,而不是在运行时发现错误。
我发现 Python 的迷人之处之一是它如何执行这样的规则。在内部,ABC 使用一个名为 track 所有抽象方法的特殊属性。
以下是检查属性的方法:__abstractmethods__
from abc import ABC, abstractmethodclassExampleABC(ABC):@abstractmethoddefexample_method(self):passprint(ExampleABC.__abstractmethods__)
输出:
frozenset({'example_method'})Python 使用此 frozenset 来确定必须实现哪些方法,如果子类中缺少 中列出的任何方法,则 Python 会阻止实例化该子类。__abstractmethods__
让我分享我最近的一个项目的例子,我的任务是构建一个插件系统,允许开发人员扩展应用程序的功能,每个插件都需要:
为主机应用程序提供要调用的标准化方法:execute
无需修改核心应用程序即可轻松添加或删除。
确保无法加载不完整或无效的插件。
使用 ABC 来强制执行插件接口使此设计变得更加简单。
from abc import ABC, abstractmethodclassPlugin(ABC):@abstractmethoddefexecute(self):"""Execute the plugin's functionality."""pass
这可确保所有插件都实现该方法。
classLoggerPlugin(Plugin):defexecute(self): print("Logging system activity...")classEmailPlugin(Plugin):defexecute(self): print("Sending notification email...")这些插件实现该方法,遵守接口。
defrun_plugin(plugin: Plugin):"""Run the specified plugin.""" plugin.execute()# Instantiate pluginslogger = LoggerPlugin()email = EmailPlugin()# Run pluginsrun_plugin(logger)run_plugin(email)输出:
Loggingsystem activity...Sendingnotification email...
此结构可确保主机应用程序以一致的方式与插件交,如果有人试图创建无效的插件,Python 将立即阻止它。
以下是我依赖 ABC 进行此类项目的原因:
及早发现错误:ABC 可以防止实例化不完整的类,从而降低运行时失败的风险。
明确的约定:它们提供清晰明确的约定,使团队更容易处理大型项目。
可扩展性:添加新的插件或实现很简单,因为界面确保了兼容性。
工具支持:ABC 与 IDE 等工具很好地集成,这些工具可以验证代码并提供更好的自动完成建议。mypy
接口编程对于构建可扩展且可维护的系统至关重要,Python 的抽象基类 (ABC) 提供了一种强大的方法来执行协定,确保实现之间的一致性和可靠性。
无论是设计支付系统还是构建插件架构,ABC 都允许在不牺牲可维护性的情况下执行约定、确保兼容性和扩展代码库,接受 ABC 将提升你的 Python 编程技能并带来更好的软件设计。
原文:https://www.tk1s.com/python/interface-programming-in-python
长按或扫描下方二维码,免费获取 Python公开课和大佬打包整理的几百G的学习资料,内容包含但不限于Python电子书、教程、项目接单、源码等等 推荐阅读
在python中0.1+0.2,谁能回答正确?我用1个多小时才知道
点击 阅读原文 了解更多