我有一套类似的类,称为“Executors”,它们在 Strategy pattern 中使用。 。它们是非常简单的类:
class ExecutorA:
def execute(self, data):
pass
class ExecutorB:
def execute(self, data):
pass
所有执行器的 execute()
函数需要以相同的方式运行,即以某种格式获取数据并以另一种特定格式返回数据。由于鸭子类型,不需要有基类,所以我没有编写基类。
但是,我目前正在使用文档字符串等记录我的代码,并且我认为在抽象基类中记录 execute()
函数的数据格式要求可能是个好主意,如下所示:
class Executor(ABC):
def execute(self, data):
"""Process data in format xy and return data in format zy"""
pass
我的理由是我不想在每个 Executor 类中复制相同的文档。这是 ABC 的常见用例吗?
澄清: 我需要使用 python 3.6,因为我们使用的是 RHEL,而更新的 python 尚未正式可用。
最佳答案
如果仅用于文档/静态类型检查目的,您也可以使用 typing.Protocol
(从 Python 3.8 开始并通过 typing_extensions
向后移植)。这用于 structural subtyping这不需要显式继承。所以你可以这样做:
from typing import List, Protocol
class Executor(Protocol):
def execute(self, data: List[float]) -> float: # example type annotations
"""Reduce `data` to a single number."""
...
class ExecutorA: # no base class required, it implements the protocol
def execute(self, data: List[float]) -> float:
return sum(data)
def do_work(worker: Executor, # here we can use the Protocol class
data: List[float]) -> float:
return worker.execute(data)
do_work(ExecutorA(), [1., 2., 3.]) # this check passes
这里的文档字符串位于协议(protocol)类上,提供了 execute
方法的作用的一般信息。由于 Executor 用于类型注释,用户将被引用到协议(protocol)类。如果需要,还可以将附加信息添加到实现中(ExecutorA
,...),或者可以复制原始文档字符串(这项工作可以由装饰器完成)。
使用抽象基类也是一种解决方案。 ABC 允许进行 isinstance
和 issubclass
检查,并且您可以注册不显式继承 ABC 的其他类。
关于python - 使用抽象基类仅用于文档目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60651485/