Python 带参数的装饰器 [2] 函数参数类型检查
在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 带参数的装饰器 [2] 函数参数类型检查的更多相关文章
- python:带参数的装饰器,函数的有用信息
一.带参数的装饰器,函数的有用信息 def func1(): '''此函数的功能是完成的登陆的功能 return: 返回值是登陆成功与否(true,false) ''' print(333) func ...
- 【python 】装饰器 (多个参数的函数,带参数的装饰器)【转】
最简单的模板是这样的 #-*-coding:utf-8-*- def outer(func): def inner(): print 'before' func() print 'after' # r ...
- python 装饰器 (多个参数的函数,带参数的装饰器)
最简单的模板是这样的 #-*-coding:utf-8-*- def outer(func): def inner(): print 'before' func() print 'after' # r ...
- guxh的python笔记三:装饰器
1,函数作用域 这种情况可以顺利执行: total = 0 def run(): print(total) 这种情况会报错: total = 0 def run(): print(total) tot ...
- Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列)
Python进阶(七)----带参数的装饰器,多个装饰器修饰同一个函数和递归简单案例(斐波那契数列) 一丶带参数的装饰器 def wrapper_out(pt): def wrapper(func): ...
- Python之函数的进阶(带参数的装饰器)
函数篇--装饰器二 带参数的装饰器 def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函 ...
- python 全栈开发,Day12(函数的有用信息,带参数的装饰器,多个装饰器装饰一个函数)
函数的执行时,*打散.函数的定义时,*聚合. from functools import wraps def wrapper(f): # f = func1 @wraps(f) def inner(* ...
- python全栈开发day12-函数的有用信息、带参数的装饰器、多个装饰器装饰一个函数、global和nonlocal的进一步解析和总结
1.上周回顾 1).函数名的应用 直接打印函数名,是函数的地址 变量 函数的参数 函数的返回值 可以当容器类数据类型的元素 2).闭包 内层函数对外层函数的非全局变量的引用,就是闭包. 并返回内部函数 ...
- Python带参数的装饰器
在装饰器函数里传入参数 # -*- coding: utf-8 -*- # 2017/12/2 21:38 # 这不是什么黑魔法,你只需要让包装器传递参数: def a_decorator_passi ...
随机推荐
- 【转】hibernate 延迟加载
Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载.hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hiberna ...
- EF实现增删改查
从来没想到过能在这个上面翻车,感慨自学没有培训来得系统啊,废话不多说 ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一 ...
- C# SqlBulkCopy类批量导入 测试
一.功能说明 1.可以选择,只导入部分列,或者导入全部列. 2.导入速度的确比一般sql要快. 3.不用写sql语句 ----------------------------------------- ...
- K8S 部署 ingress-nginx (二) 部署后端为 tomcat
在上面已经部署了 ingress-nginx, https://www.cnblogs.com/klvchen/p/9903480.html 创建 service 和 pods cd vi tomca ...
- Android的ToolBar
ToolBar比ActionBar更加可控,自由.因此,Google 逐渐使用ToolBar来代替ActionBar. 使用ToolBar 1.要引入appCompat_v7支持 2.主题设置为NoA ...
- 常用的JVM调优参数总结汇总【随时查阅学习】
本文章参数根据后期用的参数会持续更新 --- (1)-Xms20M 表示设置JVM启动内存的最小值为20M,必须以M为单位 (2)-Xmx20M 表示设置JVM启动内存的最大值为20M,必须以M为单 ...
- 页面间固定参数,通过cookie传值
最后在做的页面,比如用户数据(用户头像,名称,年龄)这些信息,因为大部分页面都要用,之前是通过url地址传,另一页面接收.考虑到这样做会让url过长,因此,尝试使用cookie,把固定的值保存在coo ...
- Team Services的打包管理
Team Services的打包管理 概述 Package Management (打包管理)是一种扩展,可以更容易地发现.安装和发布包. 它与Team Services中心如构建功能深度集成,这样打 ...
- Could not update the distribution database subscription table. The subscription status could not be changed.
在一个测试服务器删除发布(Publication)时遇到下面错误,具体如下所示 标题: Microsoft SQL Server Management Studio --------------- ...
- GIT基本命令介绍
1.git remote git remote -v| --verbose 查看仓库详细信息 git remote add <name> <url> 关联远程库.如果你本地新建 ...