如何正确标注asyncio类实例变量类型并解决mypy校验问题
异步初始化属性的类型安全解决方案
方案1:异步工厂模式(最优设计)
直接从类设计层面消除未初始化的中间状态,完全规避_connection为None的可能性,同时符合OOP设计规范:
from typing import Optional import asyncio class Example: # 私有化构造方法,禁止外部直接实例化 def __init__(self, connection: Connection) -> None: # 直接传入初始化完成的连接,无需Optional标注 self._connection: Connection = connection # 对外仅暴露异步构造类方法 @classmethod async def create(cls) -> "Example": # 先完成异步连接初始化,再构造实例 connection = await connect_somewhere(...) return cls(connection) async def send(self, data: bytes) -> None: # 此时_connection必然不为None,mypy不会触发strict-optional报错 self._connection.send(data)
使用时只能通过await Example.create()获取实例,保证拿到实例时连接已经初始化完成,既解决了类型安全问题,也避免了运行时忘记调用connect就调用send的逻辑错误。
方案2:封装内部校验方法(兼容原有使用方式)
如果确实需要保留「先实例化,后调用connect初始化」的使用逻辑,可以封装统一的连接获取方法,避免重复写assert或type ignore:
from typing import Optional class Example: def __init__(self) -> None: self._connection: Optional[Connection] = None async def connect(self) -> None: self._connection = await connect_somewhere(...) # 统一做非空校验,mypy可识别返回值类型非空 def _get_connection(self) -> Connection: if self._connection is None: raise RuntimeError("连接未初始化,请先调用connect方法") return self._connection async def send(self, data: bytes) -> None: self._get_connection().send(data)
这个方案只需要维护一处校验逻辑,所有用到连接的方法都可以复用,运行时报错信息明确,类型校验也能正常通过。
不推荐的临时方案说明
你当前用的# type: ignore会屏蔽该行所有类型错误,后续代码变更引入的真实类型问题也会被忽略;每次手动写assert self._connection重复代码多,维护成本高,非特殊情况不建议长期使用。
内容的提问来源于stack exchange,提问作者Lefty
相关产品推荐
相关产品推荐

