mypy报错:list[dict[str,str]]为何不兼容AsyncCollection.add参数类型?
解决mypy与chromadb AsyncCollection.add的类型不匹配问题
为啥会报错?
mypy对泛型列表这类容器默认采用严格不变类型检查。虽然单个dict[str, str]属于Mapping[str, str|int|float|bool]的子类,但list[dict[str,str]]并不被视为list[Mapping[str, str|int|float|bool]]的子类——mypy担心如果允许这种赋值,后续代码可能会向列表中添加其他类型的Mapping(比如自定义的Mapping子类),但原列表实际只能容纳dict,会破坏类型安全。
修复办法
这里有几个实用的解决方式:
1. 直接给metadatas标注目标类型
创建列表时明确告诉mypy它的类型符合要求:
from typing import List, Mapping # 其他代码... metadata = { "dc.identifier": str(path), "code": str(code), } # 显式标注类型 metadatas: List[Mapping[str, str | int | float | bool]] = [metadata for chunk in chunks] await collection.add( ids=ids, documents=chunks, metadatas=metadatas, )
2. 用cast强制转换类型
如果确定代码逻辑安全,直接让mypy接受这个类型:
from typing import cast, List, Mapping # 其他代码... metadatas = cast(List[Mapping[str, str | int | float | bool]], [metadata for chunk in chunks]) await collection.add( ids=ids, documents=chunks, metadatas=metadatas, )
3. 给单个metadata字典标注类型
把单个字典的类型指定为Mapping,生成的列表自然符合要求:
from typing import Mapping # 其他代码... # 给单个metadata标注类型 metadata: Mapping[str, str | int | float | bool] = { "dc.identifier": str(path), "code": str(code), } metadatas = [metadata for chunk in chunks] await collection.add( ids=ids, documents=chunks, metadatas=metadatas, )
额外说明
如果chromadb的类型定义采用协变泛型(比如Sequence[Mapping[...]])就能避免这个问题,但你无法修改第三方库的代码,只能在自己的代码中适配mypy的严格检查。
内容的提问来源于stack exchange,提问作者Bob Dowling
相关产品推荐
相关产品推荐

