首页 > 编程问答 >NotRequired 和Optional 的通用类型别名

NotRequired 和Optional 的通用类型别名

时间:2024-07-25 15:00:40浏览次数:14  
标签:python python-typing

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

相关文章

  • 在 Python 中动态定义文字字符串排列的并集
    我有一个字符串列表:strings=['a','b','c']我想声明列表中所有可能的有序对的Union类型。硬编码,这看起来像:Literal我如何动态定义CustomType=Literal['ab','ac','aa','ba','bb','bc�......
  • 关于 Python 中装饰器缓存的困惑
    我正在使用Python装饰器来实现函数的缓存。我了解缓存结果以提高性能的基本概念,但我正在努力解决如何处理不同的函数参数并确保底层数据更改时缓存更新。我已经实现了一个基本装饰器,它将函数结果存储在基于参数的字典。但是,此方法无法处理函数参数可能具有复杂结构(如嵌套列......
  • Python:__add__ 和 +,浮点数和整数的不同行为
    当将整数值添加到浮点值时,我意识到如果在浮点上调用该方法可以正常工作,例如:__add__但如果在整数上调用则不行:>>>n=2.0>>>m=1>>>n.__add__(m)3.0起初我认为|||只是对>>>m.__add__(n)NotImplemented和__add__类型的实现方式不同(例如f......
  • python中scrapy爬取数据get()与getall()区别
    在使用scrapy进行爬取数据的时候,有些时候需要爬取的是一段文本,或者一个div里面有很多内容,这时候我们就要使用到get()或者getall()来获取数据: get():是获取的满足条件的第一个数据。getall():是获取的满足条件的所有数据。scrapyget()getall()原理在Scrapy中,get(......
  • python—NumPy基础(3)
    文章目录算术函数算术函数的使用算术函数中out参数的使用mod()函数的使用统计函数power()函数的使用median()函数的使用mean()函数的使用函数的使用其他常用函数tile()和repeat()函数的使用roll()函数的使用resize()函数的使用replace()和put()函数的使savetxt()和lo......
  • Python爬虫:代理ip电商数据实战
    引言:数据访问管理引发的烦恼作为一名Python博主,爬虫技能对于获取和分析数据至关重要,经常爬一下,有益身心健康嘛。爬虫技术对很多人来说,不仅仅是一种工具,更像是一种艺术,帮助我们从互联网中,捕捉到有价值的信息。我经常就会用爬虫来爬取一些所需的数据,用来进行数据分析和模型训......
  • python科学计算:加速库numba —— 安装和试用
    安装(anaconda环境下)condainstallnumbaDemo代码:fromnumbaimportjitfromnumpyimportarangeimportnumpyimporttime@jitdefsum2d(arr):M,N=arr.shaperesult=0.0foriinrange(M):forjinrange(N):result+=a......
  • Python - Selenium抓取淘宝直播间评论(可使用无头模式)
    Python-Selenium抓取淘宝直播间评论(可使用无头模式)下面介绍如何使用python中的selenium简单抓取淘宝直播间实时评论。友情提醒,仅供学习交流使用,请勿用于非法用途!一、创建python项目1.在目录下新建main.py和venv虚拟环境:创建虚拟环境:python-mvenvvenv激活虚拟环......
  • 需要帮助来提取此 XML 节点 - Python 中的 Excel 连接字符串
    我有一个Python程序,打开Excel(XLSX)文件,并尝试查找<connection>节点。这是connections.xml文件中的完整XML。<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?><connectionsxmlns="http://schemas.op......
  • 【python】Python中采集Prometheus数据,进行数据分析和可视化展示
    ✨✨欢迎大家来到景天科技苑✨✨......