抽象工厂模式中Python抽象类Exchange的方法返回类型提示是否恰当?
问题解答
直接使用联合类型是否可行?
完全可行。在抽象类Exchange中将返回类型定义为float | tuple[float, str],符合Python类型提示的规则,两个子类分别返回float或tuple[float, str]时,类型检查工具(如mypy)会认可这种实现——因为子类的返回类型是父类返回类型的协变子集,属于合法的重写。
但这种写法有个明显缺点:当调用者通过抽象类Exchange的实例调用get_account_balance时,必须同时处理两种返回类型的情况,会增加代码分支和复杂度。
更严谨的替代方案
1. 使用泛型抽象类
通过泛型可以为每个子类指定明确的返回类型,让类型提示更精准,同时避免调用者处理不确定的返回类型。示例代码如下:
from abc import ABC, abstractmethod from typing import TypeVar, Generic # 定义类型变量,限定为允许的两种返回类型 BalanceType = TypeVar('BalanceType', float, tuple[float, str]) class Exchange(ABC, Generic[BalanceType]): @abstractmethod def get_account_balance(self, page_source: str) -> BalanceType: """返回账户余额""" # 子类1:返回float类型 class SimpleExchange(Exchange[float]): def get_account_balance(self, page_source: str) -> float: # 业务实现 return 500.0 # 子类2:返回tuple[float, str]类型 class CurrencyExchange(Exchange[tuple[float, str]]): def get_account_balance(self, page_source: str) -> tuple[float, str]: # 业务实现 return (1000.0, "EUR")
这种方式下,调用者在使用SimpleExchange时明确知道返回的是float,使用CurrencyExchange时明确知道返回的是带币种的元组,类型检查工具也能给出精准的提示,无需额外处理分支。
2. 拆分抽象方法(业务允许时)
如果两种返回类型对应不同的业务诉求,可以考虑在抽象类中拆分出两个独立的方法,比如:
class Exchange(ABC): @abstractmethod def get_balance_amount(self, page_source: str) -> float: """仅返回余额数值""" @abstractmethod def get_balance_with_currency(self, page_source: str) -> tuple[float, str]: """返回余额数值+币种"""
子类可以根据自身能力实现对应的方法(如果某个子类不需要其中一种,也可以抛出NotImplementedError),但这种方式只适用于业务逻辑支持拆分的场景。
总结
- 若只是需要快速兼容两种返回类型,直接用
float | tuple[float, str]的写法完全没问题; - 若追求更精准的类型提示、降低调用者的代码复杂度,泛型抽象类是更优的选择。
内容的提问来源于stack exchange,提问作者64rl0
相关产品推荐
相关产品推荐

