Python 带参数的装饰器 [2] 函数参数类型检查
Python 类型 参数 检查 装饰 函数参数
2023-09-11 14:14:58 时间
在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装饰器 [1]
那么,接下来,在装饰器中,我们需要获取函数参数列表,并且要和类型参数表映射。
这要借助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
两层闭包三个def函数 = 带参数的装饰器
上面的代码中,我们使用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
。
相关文章
- Python学习--03变量类型
- 在Python中定义和使用抽象类的方法
- 使用python和tableau对数据进行抓取及可视化
- Python 日期和时间_python 当前日期时间_python日期格式化
- 【学习总结】GirlsInAI ML-diary day-2-Python版本选取与Anaconda中环境配置与下载
- 使用Python调用容器服务应用的API
- Python判断当前操作系统类型以及os/sys/platform模块简介
- 【Python数据挖掘课程】三.Kmeans聚类代码实现、作业及优化
- python-docx 设置标题heading的中文字体类型+设置正文的中文字体类型
- Python的特殊数字类型(无穷大、无穷小等)
- Python语言学习:Python语言学习之python包/库package的简介(模块的封装/模块路径搜索/模块导入方法/自定义导入模块实现华氏-摄氏温度转换案例应用)、使用方法、管理工具之详细攻略
- Python:利用python语言实现18位身份证号码和15位身份证号码相互转换
- Python编程语言学习:包导入和模块搜索路径(包路径)简介、使用方法(python系统环境路径的查询与添加)之详细攻略
- Python之tkinter:动态演示调用python库的tkinter带你进入GUI世界(Find/undo事件)
- Python语言学习之数值、小数、空格那些事:python和数值、小数、空格的使用方法之详细攻略
- Py之pipenv:Python包的管理利器pipenv简介、安装、使用方法详细攻略
- 新手对Python学习路线还犯迷糊?这篇赶紧码住了!
- python基础知识之 Python代码规范
- 实战案例丨分布式系统中如何用python实现Paxos
- 从零开始学python | 什么是Python JSON?
- multiprocessing:这样做才能重复利用 Python 的多核
- 【LeetCode Python实现】6. Z 字形变换(中等)
- 《Python程序设计》专栏介绍
- Python爬虫:PyExecJS在python中运行javascript代码
- python 将一个JSON 字典转换为一个Python 对象
- 不会吧,不会吧,不会还有人觉得Python是胶水语言吧?
- python 合并k个有序链表
- python实战===短信验证码的小项目
- 用setuptools_scm来自动控制Python包的版本
- 多版本Python共存时pip给指定版本的python安装package的方法
- 【python】Python实现网络爬虫demo实例