Python中定义抽象基类
What
python中定义可以定义抽象类,和Java中的抽象类是一样的,不能被直接实例化,而是作为一个基类,主要用于定义一组接口规范,接口的实现在继承其的子类中完成,并且要求子类必须实现定义的所有接口,和Java一样如何子类未完全实现父类中的所有接口,那么这个子类也会被定义成为一个抽象类,不能直接实例化。
Why
- 强制接口一致性
- 实现多态性
- 促进代码重用
- 模板化编程
总之就是好处多多
How
定义抽象类主要有两种方法一种是通过继承ABC类,另一种是直接使用ABCMeta作为元类。
还可以结合使用 @abstractmethod 和 @abstractproperty(Python 3.3 及以上版本推荐使用 @property + @abstractmethod)来定义抽象方法和属性。
下面将依次介绍这两种方法。
继承ABC类
最常用、最简洁的方式,适用于绝大多数情况。只需要让自己的抽象类去继承abc.ABC即可,并使用@abstractmethod装饰器标记应该被子类实现的方法。
from abc import ABC, abstractmethod
class MyabstractClass(ABC):
@abstractmethod
def my_method(self):
pass
@property
@abstractmethod
def my_property(self):
pass
使用ABCMeta元类
from abc import ABCMeta, abstractmethod
class MyAbstractClass(metaclass=ABCMeta):
@abstractmethod
def my_method(self):
pass
@property
@abstractmethod
def my_property(self):
pass
- @abstractmethod:用于装饰普通方法,表明该方法是抽象的,所有非抽象子类都必须实现它。
- @property + @abstractmethod:用于定义抽象属性,确保子类提供具体的属性实现。
静态方法和类方法
除了普通的实例方法外,也可以定义抽象的静态方法和类方法。通过组合@abstractmethod 和 @staticmethod 或 @classmethod 来完成。
from abc import ABC, abstractmethod
class AbstractBaseClass(ABC):
@abstractmethod
@staticmethod
def static_method():
"""这是一个抽象静态方法"""
pass
@abstractmethod
@classmethod
def class_method(cls):
"""这是一个抽象类方法"""
pass
注册虚拟子类
有时可能想要声明某个类实现了特定接口,但并不直接继承自那个抽象基类。这时可以使用 register() 方法来注册一个“虚拟子类”。
from abc import ABC, abstractmethod
class PluginBase(ABC):
@abstractmethod
def load(self, input):
pass
class LocalPlugin:
def load(self, input):
return input.read()
PluginBase.register(LocalPlugin) # 注册 LocalPlugin 为 PluginBase 的虚拟子类
# 测试是否成功注册
print(issubclass(LocalPlugin, PluginBase)) # 应该输出 True
local_plugin = LocalPlugin()
print(isinstance(local_plugin, PluginBase)) # 应该输出 True