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
猜你喜欢
- 动态变量名赋值在使用 tkinter 时需要动态生成变量,如动态生成 var1...var10 变量。使用 exec 动态赋值exec 在
- riginal_Data因为程序是为了实现对纯数值型Excel文档进行导入并生成矩阵,因此有必要对第五列文本值进行删除处理。Import_D
- documentFragment 是一個無父對象的document對象.他支持以下DOM2方法:appendChild, cloneNode
- 一 代码编排1 缩进4个空格的缩进(编辑器都可以完成此功能),不要使用Tap,更不能混合使用Tap和空格。2 每行最大长度79,换行可以使用
- 一个已知管用的方法是,使用session_set_save_handler,接管所有的session管理工作,一般是把session信息存储
- 1 硬件设备TTL串口摄像头(VC0706)USB转TTL烧录器2 serial安装第一次安装的是serial的包导包的时候发现下载错了,正
- 前言文章抄袭在互联网中普遍存在,很多博主都收受其烦。近几年随着互联网的发展,抄袭等不道德行为在互联网上愈演愈烈,甚至复制、黏贴后发布标原创屡
- system函数 说明:执行外部程序并显示输出资料。 语法:string system(string command, int [retur
- import webbrowser as webimport timeimport oscount=0while count<10:&
- 参数让我们进一步看看CPU的数量是如何影响这些参数的。 参数fast_start_parallel_rollback Oracle并行机制中
- 在第一部分中,我们主要讲解了一下如何用列表元素来实现柱状图效果。其中需要特别注意的就是相对定位和绝对定位的的使用。在本节中,将来讨论一下使用
- 一、“无”的哲学佛家讲究“因果报应”,有果必有应。此段看似与主题没有血缘关系,实际讲的是“因”。我个人比较喜欢老子的道家思想,并喜欢以其思想
- 页面加载loading效果, 这个挺好玩的!用setTimeout实现的!可以和服务端整合弄一些生成HTML或者上传文件等应用!
- PHP hebrev() 函数实例反向显示希伯来字符:<?php echo hebrev("á çù&
- hello,我是小小炽,这是我写的第一篇博客,写博客一直都想在写,但是苦于能力尚浅,在各位大牛面前那既然是关公面前耍大刀了,但是其实想来每一
- 最近在工作当中遇到一个问题 有个页面需要添加一个浏览历史记录功能具体来说就是要记录下用户在此网站的点击历史 并把它们降序排列出来(只显示前6
- 用于匹配的正则表达式为 :([1-9]\d*\.?\d*)|(0\.\d*[1-9])([1-9] :匹配1~9的数字;\d :匹配数字,包
- isnumeric()方法检查字符串是否仅由数字组成。这种方法只表示为Unicode对象。注意:要定义一个字符串为Unicode
- 作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。Go 语言中变量可以在三个地方声明:函数内定义的变量称为局部变量
- SQL Server数据库涉及到的数据仓库概念:1.多维数据集:多维数据集是联机分析处理 (OLAP) 中的主要对象,是一项可对数据仓库中的