You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否为类字典自定义对象添加TypedDict风格的类型提示?

解决方案:为自定义类添加TypedDict风格的类型提示

你的核心问题是:TypedDict是专门为原生字典设计的类型标注,自定义类即便实现了字典的存取方法,类型检查器也不会默认将其与TypedDict类型划等号。不过完全可以通过类型系统的特性实现兼容,以下是针对不同场景的解决方案:

场景1:可以修改MyDictImplementation类代码

给自定义类添加泛型支持,让它可以绑定到对应的TypedDict结构,这样类型检查器就能识别它的结构兼容性:

import typing
from typing import Generic, TypeVar, TypedDict

# 定义类型变量,绑定到Mapping类型(包含TypedDict)
T = TypeVar('T', bound=typing.Mapping)

class MyDictImplementation(Generic[T]):
    def __init__(self, values: T):
        self.values: T = values

    def __setitem__(self, key: typing.Any, value: typing.Any) -> None:
        self.values[key] = value

    def __getitem__(self, item: typing.Any) -> typing.Any:
        return self.values[item]

    def __repr__(self) -> str:
        return f'{self.__class__.__name__}({self.values.__repr__()})'

# 原TypedDict定义保持不变
class StatusState(typing.TypedDict):
    enabled: bool
    group: str

class States(typing.TypedDict):
    states: typing.Dict[int, StatusState]

class Project(typing.TypedDict):
    project: States

# 修改函数参数,同时接受原生Project字典和泛型自定义类实例
def typing_test(input_: typing.Union[Project, MyDictImplementation[Project]]):
    pass

# 原生字典正常使用
foo: Project = {'project': {"states": {0: {"enabled": True, "group": 'Meta'}}}}
typing_test(foo)

# 自定义类实例指定泛型类型后可通过检查
bar: MyDictImplementation[Project] = MyDictImplementation({
    'project': MyDictImplementation({
        'states': MyDictImplementation({
            0: MyDictImplementation({'enabled': True, 'group': 'Meta'})
        })
    })
})
typing_test(bar)  # 类型检查通过

场景2:无法修改MyDictImplementation类代码

使用Protocol定义一个符合TypedDict结构的访问协议,类型检查器会自动识别实现了__getitem__/__setitem__的自定义类是否符合该协议:

import typing
from typing import Protocol, TypedDict, Literal

# 原自定义类保持不变
class MyDictImplementation:
    def __init__(self, values):
        self.values = values

    def __setitem__(self, key, value):
        self.values[key] = value

    def __getitem__(self, item):
        return self.values[item]

    def __repr__(self):
        return f'{self.__class__.__name__}({self.values.__repr__()})'

# 原TypedDict定义保持不变
class StatusState(typing.TypedDict):
    enabled: bool
    group: str

class States(typing.TypedDict):
    states: typing.Dict[int, StatusState]

class Project(typing.TypedDict):
    project: States

# 定义对应Project结构的协议
class ProjectProtocol(Protocol):
    def __getitem__(self, key: Literal['project']) -> States: ...
    def __setitem__(self, key: Literal['project'], value: States) -> None: ...

# 函数参数接受原生Project或符合协议的自定义类
def typing_test(input_: typing.Union[Project, ProjectProtocol]):
    pass

foo: Project = {'project': {"states": {0: {"enabled": True, "group": 'Meta'}}}}
typing_test(foo)

bar = MyDictImplementation({
    'project': MyDictImplementation({
        'states': MyDictImplementation({
            0: MyDictImplementation({'enabled': True, 'group': 'Meta'})
        })
    })
})
typing_test(bar)  # 类型检查通过

临时权宜方案(不推荐)

如果以上方法都无法使用,可以用typing.cast强制类型转换绕过检查,但这会失去类型检查的意义,仅适合临时场景:

typing_test(typing.cast(Project, bar))

内容的提问来源于stack exchange,提问作者Jerakin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:59:59