[转载] python 函数参数类型检查

参考链接: Python函数参数

在Python中,不知道函数参数类型是一个很正常的事情,特别是在一个大项目里。 我见过有些项目里,每一个函数体的前十几行都在检查参数类型,这实在是太麻烦了。而且一旦参数有改动,这部分也需要改动。 下面我们用装饰器来实现,函数参数的强制类型检查。 

 

首先,这个装饰器,要接受类型参数,和指定函数参数的类型参数。也就是一个list和一个dict 

from functools import wraps

 

def typeassert(*type_args, **type_kwargs):

    def decorate(func):

        @wraps(func)

        def wrapper(*args, **kwargs):

            return func(*args, **kwargs)

        return wrapper

    return decorate

 

@wraps(func)的作用请看另一篇 

 

那么,接下来,在装饰器中,我们需要获取函数参数列表,并且要和类型参数表映射。 这要借助Python的一个标准库——inspect 这个库一般用于Python代码调试 

from inspect import signature

from functools import wraps

 

def typeassert(*type_args, **type_kwargs):

    def decorate(func):

        sig = signature(func)

        bound_types = sig.bind_partial(*type_args, **type_kwargs).arguments

 

        @wraps(func)

        def wrapper(*args, **kwargs):

            return func(*args, **kwargs)

        return wrapper

    return decorate

 

上面的代码中,我们使用inspect中的signature方法获取了func的Signature对象,然后使用bind_partial方法创建了(*type_args, **type_kwargs)到func参数的映射(也就是一个字典)。 

 

接下来就简单了,我们只需要再获取(*args, **kwargs)的类型,使用 isinstance 函数进行比较就好。 

from inspect import signature

from functools import wraps

 

def typeassert(*type_args, **type_kwargs):

    def decorate(func):

        sig = signature(func)

        bound_types = sig.bind_partial(*type_args, **type_kwargs).arguments

 

        @wraps(func)

        def wrapper(*args, **kwargs):

            bound_values = sig.bind(*args, **kwargs)

            for name, value in bound_values.arguments.items():

                if name in bound_types:

                    if not isinstance(value, bound_types[name]):

                        raise TypeError('Argument {} must be {}'.format(name, bound_types[name]))

            return func(*args, **kwargs)

        return wrapper

    return decorate

 

 

运行如下代码 

@typeassert(int, int)

def add(x, y):

    return x+y

 

print(add("u", 2))

 

能看到报错如下 

Traceback (most recent call last):

  File "c:\Users\Chen\Desktop\typeassert.py", line 32, in <module>

    print(add("u", 2))

  File "c:\Users\Chen\Desktop\typeassert.py", line 22, in wrapper

    'Argument {} must be {}'.format(name, bound_types[name])

TypeError: Argument x must be <class 'int'>

 

很贴心的提醒了我们哪一个参数应该是什么类型。你甚至可以自己改动这个装饰器,让它还能告诉你传进去了什么错误参数(特别是写爬虫的时候,参数很难掌握,一旦报错,还得重跑一遍才知道为什么。) 

你也可以指定某一个参数的类型,譬如 

@typeassert(int, z=str)

def display(x, y, z):

    print(x, y, z)

 

这时你会发现,y的类型就像原生的Python函数一样,什么都行。而x必须是int,z必须是str。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值