在
typing.TypedDict
中,
NotRequired
字段与声明值
Optional
的字段之间存在差异。第一个意味着该键可能不存在,后者意味着现有键上的值可能是
None
在我的上下文中(使用mongodb),我不想区分这一点,只是允许一个字段既
NotRequired
又
Optional
这可以通过
class Struct(TypedDict):
possibly_string = NotRequired[str | None]
在我的上下文中实现,我从来不想区分这一点,所以我想要一个通用类型,比如说
Possibly[T]
我可以用它作为写作的简写
NotRequired[T | None]
当我尝试编写一个通用别名,mypy 给了我代码注释中指出的两个错误:
from typing import NotRequired, Optional, TypeVar, TypedDict
T = TypeVar("T")
Possibly = NotRequired[Optional[T]]
class Struct(TypedDict):
possibly_string: Possibly[str] # Variable "Possibly" is not valid as a type [valid-type]
non_compliant: Struct = {"possibly_string": int}
compliant_absent: Struct = {} # Missing key "possibly_string" for TypedDict "Struct" [typeddict-item]
compliant_none: Struct = {"possibly_string": None}
compliant_present: Struct = {"possibly_string": "a string, indeed"}
是否可以实现我想要的?如果是这样,如何?
我寻找Python3.11或更高版本的解决方案。
很遗憾,不能直接使用类型别名来实现想要的目标。这是因为
NotRequired
的工作方式与
Optional
不同。
NotRequired
是
TypedDict
中的一个特殊标记,表示该键不是必需的。它不是一个类型本身,而是一个修饰符,用于修改键的可选性。
另一方面,
Optional[T]
是一个类型别名,表示
T | None
,也就是要么是类型
T
的值,要么是
None
。
当尝试使用
Possibly = NotRequired[Optional[T]]
时,实际上是在将
NotRequired
应用于
Optional[T]
类型,这在语法上是不允许的。
解决方法
虽然无法创建想要的通用别名,但可以使用以下两种方法之一:
1. 继续使用
NotRequired[T | None]
:
这是最直接和类型安全的方法。它明确表示该键是可选的,并且其值可以是 `T` 类型或 `None`。
```python
from typing import NotRequired, TypedDict
class Struct(TypedDict):
possibly_string: NotRequired[str | None]
non_compliant: Struct = {"possibly_string": int} # 错误
compliant_absent: Struct = {}
compliant_none: Struct = {"possibly_string": None}
compliant_present: Struct = {"possibly_string": "a string, indeed"}
```
2. 使用自定义函数来创建 TypedDict:
可以创建一个函数,该函数接受一个 TypedDict 定义,并返回一个新的 TypedDict,其中所有键都标记为 `NotRequired[T | None]`。
```python
from typing import TypedDict, TypeVar
T = TypeVar("T")
def PossiblyTypedDict(typed_dict: dict[str, T]) -> TypedDict:
return TypedDict('PossiblyTypedDict', {
key: NotRequired[value | None] for key, value in typed_dict.items()
})
class Struct(PossiblyTypedDict({'possibly_string': str})):
pass
non_compliant: Struct = {"possibly_string": int} # 错误
compliant_absent: Struct = {}
compliant_none: Struct = {"possibly_string": None}
compliant_present: Struct = {"possibly_string": "a string, indeed"}
```
这两种方法都能达到的目标,并确保类型安全。可以根据个人偏好选择其中一种。
标签:python,python-typing From: 77954574