Python ECS Entity类get_first_components方法多参数类型提示实现
Python ECS 中 get_first_components 方法的多参数类型提示实现
Python 类型系统中列表属于同构可变容器,默认要求所有元素类型一致,无法表达「第1个元素为A类型、第2个为B类型」的异构结构,因此首先需要将get_first_components的返回值从列表改为元组,这是实现对应类型提示的前提。
方案1:多重重载实现(兼容性最佳)
该方案支持所有主流类型检查器(mypy、pyright、PyCharm等),不需要高版本Python依赖,只需根据你常用的参数数量写对应重载即可:
from typing import Optional, TypeVar, Type, overload T = TypeVar('T') # 定义多个TypeVar对应不同位置的参数类型 T1 = TypeVar('T1') T2 = TypeVar('T2') T3 = TypeVar('T3') T4 = TypeVar('T4') T5 = TypeVar('T5') class Entity: def __init__(self): self.components = [] def add_component(self, c): self.components.append(c) def get_first_component(self, Type: Type[T]) -> Optional[T]: for c in self.components: if isinstance(c, Type): return c # 1个参数的重载 @overload def get_first_components(self, __t1: Type[T1]) -> tuple[Optional[T1]]: ... # 2个参数的重载 @overload def get_first_components(self, __t1: Type[T1], __t2: Type[T2]) -> tuple[Optional[T1], Optional[T2]]: ... # 3个参数的重载 @overload def get_first_components(self, __t1: Type[T1], __t2: Type[T2], __t3: Type[T3]) -> tuple[Optional[T1], Optional[T2], Optional[T3]]: ... # 可继续扩展4、5个乃至更多参数的重载,覆盖常用场景即可 def get_first_components(self, *Types) -> tuple: res = [] for Type in Types: res.append(self.get_first_component(Type)) return tuple(res)
修改后调用e.get_first_components(Pos2, Move2)时,返回值类型会被推导为tuple[Optional[Pos2], Optional[Move2]],解包后的pos和m2即可获得正确的类型提示。如果业务逻辑可以保证传入的类型对应的组件一定存在,可以去掉重载返回值里的Optional,避免后续做空判断。
方案2:可变泛型实现(代码更简洁)
如果使用Python 3.11+,或通过typing_extensions兼容Python 3.8+,可以用PEP 646引入的可变泛型实现,不需要写多个重载,自动适配任意数量的参数:
from typing import Optional, TypeVar, Type, TypeVarTuple, Unpack T = TypeVar('T') Ts = TypeVarTuple('Ts') # 可变类型元组 class Entity: def __init__(self): self.components = [] def add_component(self, c): self.components.append(c) def get_first_component(self, Type: Type[T]) -> Optional[T]: for c in self.components: if isinstance(c, Type): return c def get_first_components(self, *Types: Type[Unpack[Ts]]) -> tuple[Optional[Unpack[Ts]]]: res = [] for Type in Types: res.append(self.get_first_component(Type)) return tuple(res)
该方案不管传入多少个类型参数,都会自动推导出对应结构的元组类型。
内容的提问来源于stack exchange,提问作者psqq
相关产品推荐
相关产品推荐

