如何覆盖 TypedDict 中的 __getitem__?

How do I override __getitem__ in a TypedDict?

我正在尝试创建一个 TypedDict 子类 returns None 如果一个键会导致 KeyError 并且该键是 TypedDict的注释为Optional。我意识到这不太可能,因为 TypedDict 除了定义注释外不能被子类化。还有其他 eloquent 方法吗?

这是我正在尝试做的事情:

from typing import TypedDict, get_args, get_origin

class FilledTypedDict(TypedDict):
    def __getitem__(self, k):
        if k in self.__annotations__:
            annotation = self.__annotations__[k]
            if get_origin(annotation) is Union and type(None) in get_args(annotation):
                return None
        return super().__getitem__(k)

这给了我一个TypedDict classes can contain only type annotations。我该如何解决这个问题?

你没有。 TypedDict 不是正确的类型,它是具有明确定义项的常规 dict 表示

重点是没有 TypedDict 的实例,任何具有正确项目的 dict 都可以分配给 TypedDict 变量。

from typing import TypedDict

class TD(TypedDict):
    a: int
    b: str

print(type(TD(a=1, b="two")))  # <class 'dict'>

td: TD = {"a": 1, "b": "two"}  # valid

这使得无法向 TypedDict 添加行为,因为它必须始终与 dict 行为完全匹配。

PEP 589 –– TypedDict - Methods are not allowed, since the runtime type of a TypedDict object will always be just dict (it is never a subclass of dict).


可以做的是满足“TypedDictOptional 值”类型——通过将缺失值显式设置为 None.

from typing import Optional, TypedDict

class Call(TypedDict):
    who: str
    when: Optional[str]

call: Call
call = Call(who="Gwen", when="tomorrow")  # valid
call = {"who": "me", "when": None}        # valid
call = {"who": "us"}                      # error: Missing key 'when' for TypedDict "Call"