Python中实现参数类型检查的简单方法


Posted in Python onApril 21, 2015

Python是一门弱类型语言,很多从C/C++转过来的朋友起初不是很适应。比如,在声明一个函数时,不能指定参数的类型。用C做类比,那就是所有参数都是void*类型!void类型强制转换在C++中被广泛地认为是个坏习惯,不到万不得已是不会使用的。

Python自然没有类型强制转换一说了,因为它是动态语言。首先,所有对象都从Object继承而来,其次,它有强大的内省,如果调用某个不存在的方法会有异常抛出。大多数情况,我们都不需要做参数类型栓查,除了一些特殊情况。例如,某个函数接受一个str类型,结果在实际调用时传入的是unicode,测试过程中又没有代码覆盖到,这样问题就比较严重了。解决方法也很简单,借助Python的内省,很容易就能判断出参数的类型。但是每个地方都写检查代码会很累赘,何况它带来的实际价值并不高。一个好的解决方法是使用装饰器。

'''
 >>> NONE, MEDIUM, STRONG = 0, 1, 2
 >>>
 >>> @accepts(int, int, int)
 ... def average(x, y, z):
 ...   return (x + y + z) / 2
 ...
 >>> average(5.5, 10, 15.0)
 TypeWarning: 'average' method accepts (int, int, int), but was given
 (float, int, float)
 15.25
'''
def accepts(*types, **kw):
  """ Function decorator. Checks that inputs given to decorated function
  are of the expected type.

  Parameters:
  types -- The expected types of the inputs to the decorated function.
       Must specify type for each parameter.
  kw  -- Optional specification of 'debug' level (this is the only valid
       keyword argument, no other should be given).
       debug = ( 0 | 1 | 2 )

  """
  if not kw:
    # default level: MEDIUM
    debug = 1
  else:
    debug = kw['debug']
  try:
    def decorator(f):
      def newf(*args):
        if debug == 0:
          return f(*args)
        assert len(args) == len(types)
        argtypes = tuple(map(type, args))
        if argtypes != types:
          msg = info(f.__name__, types, argtypes, 0)
          if debug == 1:
            print >> sys.stderr, 'TypeWarning: ', msg
          elif debug == 2:
            raise TypeError, msg
        return f(*args)
      newf.__name__ = f.__name__
      return newf
    return decorator
  except KeyError, key:
    raise KeyError, key + "is not a valid keyword argument"
  except TypeError, msg:
    raise TypeError, msg

def info(fname, expected, actual, flag):
  """ Convenience function returns nicely formatted error/warning msg. """
  format = lambda types: ', '.join([str(t).split("'")[1] for t in types])
  expected, actual = format(expected), format(actual)
  msg = "'%s' method " % fname \
     + ("accepts", "returns")[flag] + " (%s), but " % expected\
     + ("was given", "result is")[flag] + " (%s)" % actual
  return msg

本质上讲,这也是一种运行时检查,但效果已经不错了。
更多有趣的装饰器的使用,可以参考这篇文章http://wiki.python.org/moin/PythonDecoratorLibrary

Python 相关文章推荐
使用Python编写vim插件的简单示例
Apr 17 Python
Python实现删除列表中满足一定条件的元素示例
Jun 12 Python
Python实现的递归神经网络简单示例
Aug 11 Python
PyQt实现界面翻转切换效果
Apr 20 Python
使用Python进行QQ批量登录的实例代码
Jun 11 Python
无法使用pip命令安装python第三方库的原因及解决方法
Jun 12 Python
tensorflow 获取模型所有参数总和数量的方法
Jun 14 Python
对python实时得到鼠标位置的示例讲解
Oct 14 Python
对Python 中矩阵或者数组相减的法则详解
Aug 26 Python
python超时重新请求解决方案
Oct 21 Python
sklearn线性逻辑回归和非线性逻辑回归的实现
Jun 09 Python
Python3读写ini配置文件的示例
Nov 06 Python
python实现的jpg格式图片修复代码
Apr 21 #Python
在Python的Flask框架中使用日期和时间的教程
Apr 21 #Python
在Python的Flask框架下收发电子邮件的教程
Apr 21 #Python
在Python的Flask框架中实现全文搜索功能
Apr 20 #Python
Python的Flask框架中实现分页功能的教程
Apr 20 #Python
在Python的Flask框架中实现单元测试的教程
Apr 20 #Python
Python的Flask框架中实现登录用户的个人资料和头像的教程
Apr 20 #Python
You might like
PHP HTML JavaScript MySQL代码如何互相传值的方法分享
2012/09/30 PHP
ecshop 2.72如何修改后台访问地址
2015/03/03 PHP
微信自定义分享php代码分析
2016/11/24 PHP
php自定义函数br2nl实现将html中br换行符转换为文本输入中换行符的方法【与函数nl2br功能相反】
2017/02/17 PHP
PHP实现文件下载【实例分享】
2017/04/28 PHP
file模式访问网页时iframe高度自适应解决方案
2013/01/16 Javascript
js快速排序的实现代码
2013/12/08 Javascript
教你如何使用PHP输出中文JSON字符串
2014/05/22 Javascript
jQuery获取file控件中图片的宽高与大小
2016/08/04 Javascript
关于js二维数组和多维数组的定义声明(详解)
2016/10/02 Javascript
Vue.js实现移动端短信验证码功能
2017/03/29 Javascript
Vue组件中slot的用法
2018/01/30 Javascript
webpack打包并将文件加载到指定的位置方法
2018/02/22 Javascript
Vue监听一个数组id是否与另一个数组id相同的方法
2018/09/26 Javascript
Vue slot用法(小结)
2018/10/22 Javascript
vue实现form表单与table表格的数据关联功能示例
2019/01/29 Javascript
用js简单提供增删改查接口
2019/05/12 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
2020/07/28 Javascript
解决vue+webpack项目接口跨域出现的问题
2020/08/10 Javascript
Python  连接字符串(join %)
2008/09/06 Python
Python全局变量操作详解
2015/04/14 Python
Python实现将DOC文档转换为PDF的方法
2015/07/25 Python
Windows下python2.7.8安装图文教程
2016/05/26 Python
Python使用matplotlib简单绘图示例
2018/02/01 Python
Python实现的序列化和反序列化二叉树算法示例
2019/03/02 Python
Python连接字符串过程详解
2020/01/06 Python
全球性的众包图形设计市场:DesignCrowd
2021/02/02 全球购物
SQL Server数据库笔试题和答案
2016/02/04 面试题
会展中心部门工作职责
2013/11/27 职场文书
党员自我评价分享
2013/12/13 职场文书
单位成立周年感言
2014/01/26 职场文书
学校法制宣传月活动总结
2014/07/03 职场文书
2014年班组建设工作总结
2014/12/01 职场文书
2015年小学英语教师工作总结
2015/05/12 职场文书
只需要12页,掌握撰写一流商业计划书的技巧
2019/05/07 职场文书
JS Object构造函数之Object.freeze
2021/04/28 Javascript