我没有写出所有组合,而是尝试了以下方法:
from typing import Union, Tuple
from itertools import product as prod
class A: pass
v = (A, None)
annot = Union[Tuple[x, y] for x, y in prod(v, v)] # breaks ofc
显然这会破坏,因为我试图将其视为列表理解。执行以下操作(无论如何与上面类似)也会中断:
X = [Tuple[x, y] for x, y in prod(v, v)]
Union[X] # breaks
Union[*X] # also breaks
Union[*[X]] # breaks again
但是有某种方法可以做到这一点吗?
为了清楚起见,我想要的最终结果是:
Union[Tuple[A, A], Tuple[A, NoneType], Tuple[NoneType, A], Tuple[NoneType, NoneType]]
Python 元组解包可以解决这个问题,在
[
的上下文中保持 ]
和 typing.Union[expression]
的不同“元”级语义不受影响。
所以试试这个:
annot = Union[
*tuple(
Tuple[x, y] for x, y in prod(v, v))
]
我们基本上从 Python 生成器理解表达式中创建一个元组,然后将其解压并将其放入
Union[expr]
。
其实,
tuple
这个词可以去掉,只留下*(
和)
。
当我需要从 FastAPI 和 Pydantic 中实现的微服务 Web API 生成 OpenAPI 文档时,我有一个与 OP 类似的需求,用于“简单”Python
enum.IntEnum
类型。像这样:
from typing import Annotated, Literal, Union
from enum import IntEnum, unique
from pydantic import BaseModel, Field
@unique
class SessionStatus(IntEnum):
"""
SessionStatus enum type
"""
Stopped = 0
WaitingForServer = 1
WaitingForClient = 2
Started = 3
class Session(BaseModel):
"""
Session DTO
"""
status: Annotated[
Union[*(Annotated[Literal[v.value], Field(description=v.name)] for v in SessionStatus)],
Field(title="status", description="# Session status")
]
My OpenAPI JSON schema outcome then looked like this:
[![OpenAPI JSON schema result][1]][1]
[1]: https://i.stack.imgur.com/b79nI.png