Python类型:从有效值列表动态创建文本别名

2024-04-20 06:14:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个函数,它验证它的参数,只接受给定有效选项列表中的值。在键入方面,我使用Literal类型别名反映此行为,如下所示:

from typing import Literal


VALID_ARGUMENTS = ['foo', 'bar']

Argument = Literal['foo', 'bar']


def func(argument: 'Argument') -> None:
    if argument not in VALID_ARGUMENTS:
        raise ValueError(
            f'argument must be one of {VALID_ARGUMENTS}'
        )
    # ...

这违反了DRY原则,因为我必须重写文本类型定义中的有效参数列表,即使它已经存储在变量VALID_ARGUMENTS给定VALID_ARGUMENTS变量,如何动态创建Argument文本类型?

以下事项不起作用:

from typing import Literal, Union, NewType


Argument = Literal[*VALID_ARGUMENTS]  # SyntaxError: invalid syntax

Argument = Literal[VALID_ARGUMENTS]  # Parameters to generic types must be types

Argument = Literal[Union[VALID_ARGUMENTS]]  # TypeError: Union[arg, ...]: each arg must be a type. Got ['foo', 'bar'].

Argument = NewType(
    'Argument',
    Union[
        Literal[valid_argument]
        for valid_argument in VALID_ARGUMENTS
    ]
)  # Expected type 'Type[_T]', got 'list' instead

那么,如何做到这一点呢?或者根本就做不到


Tags: fromtyping类型列表参数foobarbe
3条回答

这里是解决这个问题的方法。但我不知道这是否是一个好的解决方案

VALID_ARGUMENTS = ['foo', 'bar']

Argument = Literal['1']

Argument.__args__ = tuple(VALID_ARGUMENTS)

print(Argument)
# typing.Literal['foo', 'bar']

如果有人仍在为此寻找解决方案:

typing.Literal[tuple(VALID_ARGUMENTS)]

反过来,从Argument构建VALID_ARGUMENTS

Argument = typing.Literal['foo', 'bar']
VALID_ARGUMENTS: typing.Tuple[Argument, ...] = typing.get_args(Argument)

在运行时可以从VALID_ARGUMENTS构建Argument,但是这样做与静态分析不兼容,静态分析是类型注释的主要用例。从Argument构建VALID_ARGUMENTS是一条路要走

我在这里为VALID_ARGUMENTS使用了一个元组,但是如果出于某种原因您确实喜欢列表,您可以得到一个:

VALID_ARGUMENTS: typing.List[Argument] = list(typing.get_args(Argument))

相关问题 更多 >