from strongtyping.strong_typing import match_typing
@match_typing
def func_a(a: str, b: int, c: list):
...
func_a('1', 2, [i for i in range(5)])
# >>> True
func_a(1, 2, [i for i in range(5)])
# >>> will raise a TypeMismatch Exception
import inspect
def enforce_type_annotation(fn):
parameters = inspect.signature(fn).parameters
param_keys = list(parameters.keys())
def wrapper(*args, **kwargs):
errors = list()
# -- iterate over positionals
for i in range(len(args)):
param = parameters[param_keys[i]]
value = args[i]
# -- if the parameter is not annotated, don't validate.
if not param.annotation:
continue
if not isinstance(value, param.annotation):
errors.append(
f'Positional argument {param} was given type {type(value)} but expected {param.annotation}!'
)
# -- this might throw a KeyError if an incorrect argument is provided
for key, value in kwargs.items():
param = parameters[key]
value = kwargs[key]
# -- if the parameter is not annotated, don't validate.
if not param.annotation:
continue
if not isinstance(value, param.annotation):
errors.append(
f'Keyword argument {param} was given type {type(value)} but expected {param.annotation}!'
)
if len(errors):
raise TypeError('\n'.join(errors))
return fn(*args, **kwargs)
return wrapper
@enforce_type_annotation
def foo(bar: bool, barry: str = None):
return "hello world"
# -- works - keyword arguments remain optional
print(foo(True))
# -- works - all types were passed correctly
print(foo(True, 'Hello'))
# -- does not work, keyword arguments may also be passed as positional
print(foo(True, 1))
# -- does not work, "barry" expects a string
print(foo(True, barry=1))
4条答案
按热度按时间xmq68pz91#
我正在寻找类似的东西,并找到了库typeguard。这可以在您想要的任何地方自动执行运行时类型检查。也支持像问题中那样直接检查类型。从文件上看,
wgmfuz8q2#
在
typing
模块中没有这样的函数,而且很可能永远不会有。检查一个对象是否是一个类的示例--这只意味着“这个对象是由类的构造函数创建的”--是一个简单的测试一些标记的问题。
然而,检查对象是否是类型的“示例”不一定是可判定的:
虽然很容易检查
foo
的类型注解(假设它不是lambda
),但根据Rice定理,检查它是否符合它们通常是不可判定的。即使使用更简单的类型,如
List[int]
,测试也很容易变得过于低效,除了最小的玩具示例之外,无法用于任何其他类型。允许类型检查器以相对有效的方式执行此操作的技巧是保守的:类型检查器试图证明
foo
总是返回int
。如果失败,则拒绝该程序,即使该程序可能是有效的,即这个函数很可能被拒绝,尽管它是完全安全的:gzszwxb43#
这是我最近发现的,基本上这个装饰器在运行时进行类型检查,如果某些类型定义不匹配,则会引发异常。它还可以对嵌套类型(字符串的dict等)进行类型检查
https://github.com/FelixTheC/strongtyping
示例:
piok6c0g4#
inspect模块可以很容易地使用vanilla python解决这个问题-不需要外部模块:)
这是一个有点简单化,授予;它可能不适用于深度嵌套的类型(比如需要给定键/值类型的字典),但您可以使用“类型化”库来扩展它。