如何动态测试一个值是否符合Python Literal类型?

问题描述 投票:0回答:1

我想了解如何在Python中动态测试一个值是否符合Literal类型。假设我有以下代码:

from typing import Literal

PossibleValues = Literal["a", "b"]

x = input()

我想使用

isinstance
,但这样做会给我一个类型错误:

>>> isinstance(x, PossibleValues)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../typing.py", line 720, in __instancecheck__
    return self.__subclasscheck__(type(obj))
  File "/.../typing.py", line 723, in __subclasscheck__
    raise TypeError("Subscripted generics cannot be used with"
TypeError: Subscripted generics cannot be used with class and instance checks

我发现我可以使用

get_args
,但这种方法似乎有点老套。

>>> from typing import get_args
>>> x = input()
'c'
>>> x in get_args(PossibleValues)
False

有更好的方法吗?

python typing
1个回答
0
投票

这就是我刚刚想出的,我对此非常满意。

"""
seems like hard coding is the only way to make literal type to accept anything to be literal
(which makes sense if you think about it)
"""

from typing import Literal


my_literal_type = Literal["a", "b", "c"]


def guard_mlt(value: str) -> my_literal_type:
    """
    only allow values in my_literal_type to pass
    and otherwise raise TypeError
    this requires hard coding the return values as it's explained at the top

    >>> guard_mlt('a')
    'a'
    >>> guard_mlt('b')
    'b'
    >>> guard_mlt('c')
    'c'
    >>> guard_mlt('d')
    Traceback (most recent call last):
        ...
    TypeError: d is not in typing.Literal['a', 'b', 'c']
    """
    match value:
        case "a":
            return "a"
        case "b":
            return "b"
        case "c":
            return "c"

    raise TypeError(f"{value} is not in {my_literal_type}")


if __name__ == "__main__":
    import doctest

    doctest.testmod()

(不可避免的)缺点是您需要为每种文字类型提供保护函数。

© www.soinside.com 2019 - 2024. All rights reserved.