繁体   English   中英

使用默认参数时如何验证 python 方法的签名?

[英]How to verify the signature of python method when using Default parameters?

有没有办法检查传递给方法的所有参数是否与预期的参数匹配? 我尝试使用 inspect.signature.bind 来匹配它们,但它现在在使用默认参数时可以正常工作,即使默认值的类型与传递的类型不同。 例如,在最后一次调用faa 方法时,我发送了一个列表作为第三个参数,但预期的默认参数是Bool。 有没有办法匹配呢?

import inspect
def foo(a, b, x=True):
    pass

def faa(*args, **kwargs):
  try:
    inspect.signature(foo).bind(*args, **kwargs)
  except TypeError:
    print("Does not match")
  else:
    print("Matches")  


faa(1)                     # Does not match , Ok
faa(10, None, 'something') # Matches, Ok.
faa(1, 2)                  # Matches, Ok.
faa(10, None, [1,2])       # Matches, NOK. Is there a way to add a check to not match ?

您可以使用属于模块pydantic的装饰器validate_arguments 举个例子:

from pydantic import validate_arguments


@validate_arguments
def faa(a, b, x: bool = True):
    pass


faa(
    a=10, b=None, x=[1, 2]
)

Output

pydantic.error_wrappers.ValidationError: 1 validation error for Faa
x
  value could not be parsed to a boolean (type=type_error.bool)

您可以定义一个简单的装饰器,可用于您要验证的每个 function。 这个装饰器建立在inpsect模块上。 这个想法是根据 function 中相应参数的默认值来验证 function 参数(位置和非位置)。

import inspect
from functools import wraps

def validate_func_args(func):
    def check_type(value, fn_param: inspect.Parameter):
        if not fn_param.default is fn_param.empty:
            _default = fn_param.default
            # We do not type check if the default value is None or if the argument is none
            is_none = _default is None or value is None

            if not is_none and type(value) != type(_default):
                raise TypeError(f"Invalid type encountered for {fn_param.name}")

    @wraps(func)
    def wrapper(*args, **kwargs):
        # First pass
        inspect.signature(foo).bind(*args, **kwargs)

        # Second pass (validate parameters with default values)
        args_count = len(args)
        fn_params = inspect.signature(foo).parameters

        for arg, param in zip(args, list(fn_params)[:args_count]):
            check_type(arg, fn_params[param])

        for kwarg, value in kwargs.items():
            check_type(value, fn_params[kwarg])

        # All good. Now call the function and return the result
        result = func(*args, **kwargs)
        return result

    return wrapper

Function定义

@validate_func_args
def foo(a, b=2, x=True):
    pass

Function 来电

foo(10, None, "something") 

Output

TypeError: Invalid type encountered for x

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM