我想了解如何在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
有更好的方法吗?
这就是我刚刚想出的,我对此非常满意。
"""
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()
(不可避免的)缺点是您需要为每种文字类型提供保护函数。