关于python:对函数部分或全部参数进行类型检查

6次阅读

共计 1842 个字符,预计需要花费 5 分钟才能阅读完成。

对函数局部或全副参数进行类型查看

构建一个装璜器,通过对装璜器中传入类型参数,来对装璜的函数的对应参数进行类型查看。

from inspect import signature
from functools import wraps

def typeassert(*tyargs,**tykwargs):
    def decorator(func):
        #获取指定的强制类型参数
        sig=signature(func)
        required_types=sig.bind_partial(*tyargs,**tykwargs).arguments#OrderedDict 类型,能够只对后面的参数进行 in 搜寻断定, 能够把后面的参数当作 key 来获取对应的类型

        @wraps(func)
        def wrapper(*args,**kwargs):
            #获取函数输出的各参数类型
            input_vals=sig.bind(*args,**kwargs)

            #对输出的每个参数,如果呈现在设定的类型查看中,则进行类型查看
            for name,value in input_vals.arguments.items():
                if name in required_types:
                    if not isinstance(value,required_types[name]):
                        raise TypeError('Argument {} must be {}'.format(name, required_types[name])
                            )
            return func(*args,**kwargs)
        return wrapper
    return decorator

@typeassert(str,z=int)# 第一个地位参数为 str,z 必须为 int
def func(x,y,z):
    return y+z

>>>print(func(1,2,3))
TypeError: Argument x must be <class 'str'>
    
@typeassert(int,y=str,z=int)# 第一个地位参数为 int,y 为 str,z 必须为 int
def func(x,y,z):
    print(x,y,z)
>>>func1(3,'s',1)
3 s 1
>>>func1('hhh','s',1)
TypeError: Argument x must be <class 'int'>

另外也能够通过函数注解来实现,之前实现过,代码如下:

def para_check(func):# 外函数,传入的参数是待检验函数对象自身
    sig=inspect.signature(func)# 获取函数参数签名
    parameters=sig.parameters# 获取参数的有序字典
    arg_names=tuple(parameters.keys())# 获取参数的名称
    def wrapper(*args,**kwargs):# 内函数
        check_list=[]# 待测验的参数对
        for i,val in enumerate(args):# 测验所有的地位参数
            arg_name=arg_names[i]
            anno=parameters[arg_name].annotation# 该参数期待的类型
            check_list.append((arg_name,anno,val))
        for arg_name,val in kwargs.items():# 测验所有的关键字参数
            anno=parameters[arg_name].annotation
            check_list.append((arg_name,anno,val))

        for check_arg in check_list:# 一一参数检验
            if not isinstance(check_arg[2],check_arg[1]):
                raise TypeError('the input %s expect type %s,but got %s'%(check_arg[0],check_arg[1],type(check_arg[2])))
        return func(*args,**kwargs)
    return wrapper

@para_check
def test(x: int, y: int):
    return x + y
>>>print(test(1,2))
3
>>>print(test(1,'3'))
TypeError: the input y expect type <class 'int'>,but got <class 'str'>

后者不须要应用传参数的装璜器。然而显著前者更灵便,用前者进行类型查看,那么前面的函数注解就能够做其它事件而非类型查看了。

正文完
 0