我有一个函数接受一些需要验证的参数。例如:
def foo(a: int, b: float, c: str) -> None:
if a <= 0:
raise ValueError(f"'a' must pe positive: {a}")
if not (0 < b <= 1):
raise ValueError(f"'b' must be in the range (0, 1]: {b}")
if not c:
raise ValueError(f"'c' can't be empty: {c!r}")
# Do things with the validated parameters a, b and c...
这是很多样板代码,用于在我到达函数的实际代码之前验证参数。我想知道是否有一个方案或一个库来简化此参数验证。我将
attrs
及其验证器用于类的字段,但它不适用于简单的函数。我尝试了 validate_call
中的 pydantic
装饰器,但问题是 pydantic
看起来像是一个“全集成”库。我必须验证所有内容,如果我有一些不需要验证的参数,或者我认为类型提示和静态检查足够好,那么 pydantic
仍然尝试验证它们,这很糟糕,尤其是当我有复杂的情况时任意类型的类型提示,例如 Callable
或 numpy
数组(我知道 arbitrary_types_allowed
参数,但它仍然执行 isinstance
检查,在我看来这是浪费)。
换句话说,我真的不需要像
pydantic
这样复杂的数据验证解决方案。我只需要添加简单的验证当我想要的时候。我想要类似 attrs
的东西,其中验证是可选的(如果我声明 attrs
字段并传递给它一个字符串,int
不会抱怨。只有静态类型检查器会警告我),并且如果我想要例如,为了确保 int
字段为正,我可以轻松添加一个没有样板的验证器。我想要类似的函数及其参数。我应该使用哪个库来实现如此简单的函数验证?
我用
marshmallow
来存放我的东西。您可以尝试以下方法是否适合您:
from functools import wraps
from marshmallow import Schema, fields, validate
class FooArgsSchema(Schema):
a = fields.Int(required=True, validate=validate.Range(min=1))
b = fields.Float(required=True, validate=validate.Range(min=0, max=1, min_inclusive=False))
c = fields.Str(required=True, validate=validate.Length(min=1))
def validate_args(schema):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
data = schema().load(kwargs)
return func(**data)
return wrapper
return decorator
@validate_args(FooArgsSchema)
def foo(a: int, b: float, c: str) -> None:
# Do things with the validated parameters a, b, and c...
print(f"a: {a}, b: {b}, c: {c}")
# Test the function
foo(a=1, b=0.5, c="hello") # Valid input
foo(a=0, b=0.5, c="hello") # Raises a ValidationError
那么,您是否考虑过编写另一个函数,只负责验证?
def validateParams():
#Do the necessary validation
def foo():
validateParams()