Hub*_*bro 6 python mypy python-typing
我正在尝试编写一个函数来断言用户输入与定义的文字类型匹配。
基本上,给出:
MyLiteral = Literal["foo", "bar"]
Run Code Online (Sandbox Code Playgroud)
我想编写一个函数来执行此操作:
some_user_provided_value = input() # For example
good_value = assert_literal(MyLiteral, some_user_provided_value)
Run Code Online (Sandbox Code Playgroud)
现在应该将的类型good_value推断为MyLiteral。如果用户值与任何定义的文字字符串都不匹配,则会引发断言错误。
这应该具有与以下相同的效果:
some_user_provided_value = input() # For example
good_value: MyLiteral
if some_user_provided_value == "foo":
good_value = "foo"
elif some_user_provided_value == "bar":
good_value = "bar"
else:
raise AssertionError(f"Value {some_user_provided_value!r} is not a MyLiteral")
Run Code Online (Sandbox Code Playgroud)
这是我的项目中经常重复的模式,因此我想将其包装在一个函数中。
该函数看起来像这样:
from typing import Any, TypeVar
T = TypeVar("T")
def assert_literal(literal_type: T, value: Any) -> T:
if value not in typing.get_args(literal_type):
raise AssertionError(f"Value {value!r} is not a {literal_type!r}")
return typing.cast(T, value)
Run Code Online (Sandbox Code Playgroud)
当然,这是行不通的,因为这个函数当前需要一个type 的实例T,并且它将输出一个type 的实例T。
如果我处理常规类,我可以将参数设置为 type Type[T],但是当我使用 Literal 类型时,这会在我脸上爆炸,大概是因为"foo"不是 的实例,MyLiteral这甚至没有任何意义。
目前有什么方法可以实现我想要做的事情吗?还可以和sLiterals混合吗?TypeVar
yot*_*nor -1
名为pydantic的精彩库恰恰提供了这一点。从他们的主页描述来看:
pydantic 在运行时强制执行类型提示,并在数据无效时提供用户友好的错误。
这是文字类型的示例,可在此处找到:
from typing import Literal
from pydantic import BaseModel, ValidationError
class Pie(BaseModel):
flavor: Literal['apple', 'pumpkin']
Pie(flavor='apple')
Pie(flavor='pumpkin')
try:
Pie(flavor='cherry')
except ValidationError as e:
print(str(e))
"""
1 validation error for Pie
flavor
unexpected value; permitted: 'apple', 'pumpkin'
(type=value_error.const; given=cherry; permitted=('apple', 'pumpkin'))
"""
Run Code Online (Sandbox Code Playgroud)
我会安全地依赖这个库来为你完成繁重的工作(例如,它在流行的 FastAPI 框架中使用) - 但如果你想自己做,那么我会转到他们的源代码,看看他们是如何管理的要做到这一点。
祝你好运!