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 相关文章推荐
Linux下使用python调用top命令获得CPU利用率
Mar 10 Python
深入源码解析Python中的对象与类型
Dec 11 Python
解决Linux系统中python matplotlib画图的中文显示问题
Jun 15 Python
使用python在本地电脑上快速处理数据
Jun 22 Python
python 读写文件,按行修改文件的方法
Jul 12 Python
numpy 对矩阵中Nan的处理:采用平均值的方法
Oct 30 Python
jupyter notebook中美观显示矩阵实例
Apr 17 Python
Python 爬虫的原理
Jul 30 Python
Python+Selenium随机生成手机验证码并检查页面上是否弹出重复手机号码提示框
Sep 21 Python
pycharm中选中一个单词替换所有重复单词的实现方法
Nov 17 Python
将Python代码打包成.exe可执行文件的完整步骤
May 12 Python
python 爬取天气网卫星图片
Jun 07 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
从MySQL数据库表中取出随机数据的代码
2007/09/05 PHP
PHP生成随机用户名和密码的实现代码
2013/02/27 PHP
WordPress中编写自定义存储字段的相关PHP函数解析
2015/12/25 PHP
Js之软键盘实现(js源码)
2007/01/30 Javascript
广告代码静态化js通用函数
2007/05/09 Javascript
jquery学习笔记 用jquery实现无刷新登录
2011/08/08 Javascript
window.onload和$(function(){})的区别介绍
2013/10/30 Javascript
jquery实现的随机多彩tag标签随机颜色和字号大小效果
2014/03/27 Javascript
Jquery全屏相册插件zoomvisualizer具有调节放大与缩小功能
2015/11/02 Javascript
JavaScript判断对象是否为数组
2015/12/22 Javascript
基于jQuery实现页面搜索功能
2020/03/26 Javascript
jQuery 实现鼠标画框并对框内数据选中的实例代码
2017/08/29 jQuery
12条写出高质量JS代码的方法
2018/01/07 Javascript
JS基于开关思想实现的数组去重功能【案例】
2019/02/18 Javascript
Vue 列表上下过渡效果的实例代码
2019/06/25 Javascript
layui输入框只允许输入中文且判断长度的例子
2019/09/18 Javascript
微信小程序使用自定义组件导航实现当前页面高亮
2020/01/02 Javascript
vuex中store存储store.commit和store.dispatch的用法
2020/07/24 Javascript
原生js实现照片墙效果
2020/10/13 Javascript
Python实现根据指定端口探测服务器/模块部署的方法
2014/08/25 Python
python通过wxPython打开一个音频文件并播放的方法
2015/03/25 Python
Python装饰器基础详解
2016/03/09 Python
python+pyqt实现12306图片验证效果
2017/10/25 Python
python机器人运动范围问题的解答
2019/04/29 Python
Python使用正则表达式分割字符串的实现方法
2019/07/16 Python
美国设计师精美珠宝购物网:Netaya
2016/08/28 全球购物
家长会邀请书
2014/01/25 职场文书
就业表自我评价分享
2014/02/06 职场文书
竞选宣传委员演讲稿
2014/05/24 职场文书
消防宣传口号
2014/06/16 职场文书
促销活动总结怎么写
2014/06/25 职场文书
学习十八大的心得体会
2014/09/01 职场文书
解除劳动合同协议书范本
2014/09/13 职场文书
2015年乡镇统计工作总结
2015/04/22 职场文书
SqlServer数据库远程连接案例教程
2021/07/15 SQL Server
MyBatis在注解上使用动态SQL方式(@select使用if)
2022/07/07 Java/Android