Dan*_*mar 10 python type-hinting python-typing python-3.9
我知道有一种新的类型格式,Annotated您可以在其中为函数的入口变量指定一些元数据。从文档中,您可以指定传入列表的最大长度,例如:
- Annotated 可以与嵌套和通用别名一起使用:
T = TypeVar('T')
Vec = Annotated[list[tuple[T, T]], MaxLen(10)]
V = Vec[int]
V == Annotated[list[tuple[int, int]], MaxLen(10)]
Run Code Online (Sandbox Code Playgroud)
但我无法完全理解到底是什么MaxLen。你应该从其他地方导入一个类吗?我尝试过导入typing.MaxLen,但似乎不存在(我正在使用Python 3.9.6,我认为它应该存在于此处...?)。
我想象它应该有效的示例代码:
from typing import List, Annotated, MaxLen
def function(foo: Annotated[List[int], MaxLen(10)]):
# ...
return True
Run Code Online (Sandbox Code Playgroud)
哪里可以找到MaxLen?
编辑:
看起来MaxLen你必须创建某种类。问题是我不知道你应该怎么做。有公开的例子吗?有人如何实现这个功能?
kik*_*s34 11
正如 AntiNeutronicPlasma 所说,Maxlen这只是一个示例,因此您需要自己创建它。
以下是如何创建和解析自定义注释的示例,以MaxLen帮助您入门。
首先,我们定义注释类本身。这是一个非常简单的类,我们只需要存储相关的元数据,在本例中为最大值:
class MaxLen:
def __init__(self, value):
self.value = value
Run Code Online (Sandbox Code Playgroud)
现在,我们可以定义一个使用此注释的函数,如下所示:
def sum_nums(nums: Annotated[List[int], MaxLen(10)]):
return sum(nums)
Run Code Online (Sandbox Code Playgroud)
但如果没人检查的话,那就没什么用了。因此,一种选择可能是实现一个装饰器,在运行时检查您的自定义注释。模块中的函数get_type_hints和将会成为您最好的朋友get_origin。下面是此类装饰器的示例,它解析并强制执行类型上的注释:get_argstypingMaxLenlist
from functools import wraps
from typing import get_type_hints, get_origin, get_args, Annotated
def check_annotations(func):
@wraps(func)
def wrapped(**kwargs):
# perform runtime annotation checking
# first, get type hints from function
type_hints = get_type_hints(func, include_extras=True)
for param, hint in type_hints.items():
# only process annotated types
if get_origin(hint) is not Annotated:
continue
# get base type and additional arguments
hint_type, *hint_args = get_args(hint)
# if a list type is detected, process the args
if hint_type is list or get_origin(hint_type) is list:
for arg in hint_args:
# if MaxLen arg is detected, process it
if isinstance(arg, MaxLen):
max_len = arg.value
actual_len = len(kwargs[param])
if actual_len > max_len:
raise ValueError(f"Parameter '{param}' cannot have a length "
f"larger than {max_len} (got length {actual_len}).")
# execute function once all checks passed
return func(**kwargs)
return wrapped
Run Code Online (Sandbox Code Playgroud)
(请注意,这个特定示例仅适用于关键字参数,但您可能会找到一种方法使其也适用于普通参数)。
现在,您可以将此装饰器应用于任何函数,并且您的自定义注释将被解析:
from typing import Annotated, List
@check_annotations
def sum_nums_strict(nums: Annotated[List[int], MaxLen(10)]):
return sum(nums)
Run Code Online (Sandbox Code Playgroud)
下面是正在运行的代码示例:
from typing import Annotated, List
@check_annotations
def sum_nums_strict(nums: Annotated[List[int], MaxLen(10)]):
return sum(nums)
Run Code Online (Sandbox Code Playgroud)