如何实现继承后包装方法与私有方法的静态类型签名匹配
问题场景与需求
场景说明
现有基类Base,其中do_something方法作为包装方法处理日志等通用逻辑,内部会调用私有方法_actually_do_something;子类通过重写_actually_do_something来实现具体功能,示例代码如下:
from typing import Any class Base: def do_something(self, *args, **kwargs) -> Any: # 处理日志等通用逻辑 result = self._actually_do_something(*args, **kwargs) # 后续通用逻辑处理 return result def _actually_do_something(self, *args, **kwargs) -> Any: raise NotImplementedError class Child1(Base): def _actually_do_something(self, x: int) -> str: return str(x)
核心需求
为Base添加类型注解,使得任意子类的do_something方法在静态类型分析工具(如mypy、VS Code的Pylance)中,拥有与该子类_actually_do_something方法完全一致的签名(包括参数类型和返回类型)。
已尝试的解决方案
选项A:泛型实现
- 优点:能正确推导返回类型
- 缺点:需要手动在类继承时标注返回类型,无法生成参数类型提示
示例代码:
from typing import TypeVar, Generic R = TypeVar("R") class BaseA(Generic[R]): def do_something(self, *args, **kwargs) -> R: ... class ChildA1(BaseA[str]): def _actually_do_something(self, x: int) -> str: ...
选项B:带泛型的装饰器与间接层
- 优点:可同时匹配返回类型与方法签名
- 缺点:需要额外的间接层实现,且每个子类都需调用
propagate_types,可能对深层继承产生影响
示例代码:
from typing import Callable, TypeVar R = TypeVar("R") def propagate_types(actual: Callable, hinted: R) -> R: return actual class BaseB: def _inner_do_something(self, *args, **kwargs) -> Any: return self._actually_do_something(*args, **kwargs) def _actually_do_something(self, *args, **kwargs) -> Any: raise NotImplementedError class ChildB1(BaseB): def _actually_do_something(self, x: int) -> str: pass do_something = propagate_types(BaseB._inner_do_something, _actually_do_something)
内容的提问来源于stack exchange,提问作者Till Hoffmann
相关产品推荐
相关产品推荐

