如何告知mypy指定对象具备特定属性?
解决方案
方案1:Protocol + TypeGuard 组合(推荐)
无需修改原有类继承结构,通过静态类型约定实现自动类型窄化,维护成本最低。
- 先定义Protocol描述目标属性结构:
from typing import Protocol, TypeGuard class PositionedWidget(Protocol): posx: float posy: float
- 实现类型守卫函数封装判断逻辑:
def has_position_attrs(obj: Widget) -> TypeGuard[PositionedWidget]: return hasattr(obj, "posx") and hasattr(obj, "posy")
- 过滤时使用该函数做判断,mypy会自动将符合条件的实例识别为
PositionedWidget类型,直接访问属性不会报错:
for widget in all_widgets: if has_position_attrs(widget): # 此处mypy已确认widget包含posx、posy属性 print(widget.posx, widget.posy)
方案2:cast显式类型转换
适合临时、少量场景使用,比# type: ignore可控性更高,仅作用于当前转换的变量:
from typing import cast, Union for widget in all_widgets: if hasattr(widget, "posx") and hasattr(widget, "posy"): # 可直接填所有带属性的子类联合,也可以用之前定义的PositionedWidget Protocol positioned_widget = cast(Union[Rectangle, Button], widget) print(positioned_widget.posx, positioned_widget.posy)
方案3:多类型isinstance判断
仅适合带属性的子类数量少且固定的场景,无需引入额外注解工具:
for widget in all_widgets: if isinstance(widget, (Rectangle, Button)): # mypy会自动窄化类型为Rectangle/Button的联合,可正常访问属性 print(widget.posx, widget.posy)
内容的提问来源于stack exchange,提问作者Jean-Francois T.
相关产品推荐
相关产品推荐

