Python中的函数参数类型检查

作者:子休_ 时间:2023-10-15 20:41:05 

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)的类型,使用isintance函数进行比较就好。

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。

来源:https://www.jianshu.com/p/7a2c9133a002

标签:Python,函数,参数,类型检查
0
投稿

猜你喜欢

  • Flask中jinja2的继承实现方法及实例

    2022-09-24 12:31:09
  • 微信小程序学习笔记之表单提交与PHP后台数据交互处理图文详解

    2023-11-22 19:29:44
  • Python pygame绘制文字制作滚动文字过程解析

    2022-06-10 13:21:11
  • matplotlib基础绘图命令之errorbar的使用

    2022-03-10 23:20:38
  • ASP转化ip地址为长整型数字

    2008-04-06 14:23:00
  • 12个步骤教你理解Python装饰器

    2021-01-25 18:28:56
  • Jupyter Notebook 远程访问配置详解

    2023-09-11 03:19:06
  • PDO::quote讲解

    2023-06-03 21:14:37
  • python3 cmp实现方式

    2023-12-13 18:10:25
  • meta标签之详解

    2008-01-13 18:48:00
  • Python操作Word批量生成合同的实现示例

    2023-06-17 09:59:14
  • 两行代码实现的QQ窗口抖动效果

    2008-09-06 12:34:00
  • 3个asp简单技巧

    2009-11-26 20:55:00
  • Python中三种条件语句示例介绍

    2022-09-17 17:28:30
  • 实现div可编辑的常见方法

    2007-11-06 12:02:00
  • JDBC 连接MySQL实例详解

    2024-01-26 23:34:27
  • jQuery 1.4官方中文手册[译]

    2010-01-20 10:46:00
  • Golang中goroutine和channel使用介绍深入分析

    2023-07-07 16:51:48
  • windows环境下mysql的解压安装及备份和还原

    2024-01-27 05:55:48
  • Python常用数据类型之间的转换总结

    2023-06-21 10:06:21
  • asp之家 网络编程 m.aspxhome.com