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发送邮件示例(支持中文邮件标题)
Feb 16 Python
python遍历文件夹并删除特定格式文件的示例
Mar 05 Python
python单线程实现多个定时器示例
Mar 30 Python
Python标准库之随机数 (math包、random包)介绍
Nov 25 Python
使用Python获取网段IP个数以及地址清单的方法
Nov 01 Python
使用Python自动化破解自定义字体混淆信息的方法实例
Feb 13 Python
Python3实现的判断回文链表算法示例
Mar 08 Python
python获取引用对象的个数方式
Dec 20 Python
Python class的继承方法代码实例
Feb 14 Python
Python正则表达式学习小例子
Mar 03 Python
Django 删除upload_to文件的步骤
Mar 30 Python
Python使用Pygame绘制时钟
Nov 29 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
Discuz 6.0+ 批量注册用户名
2009/09/13 PHP
javascript 小型动画组件与实现代码
2010/06/02 PHP
深入PHP FTP类的详解
2013/06/13 PHP
Yii框架中memcache用法实例
2014/12/03 PHP
详解PHP执行定时任务的实现思路
2015/12/21 PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
2016/02/26 PHP
ThinkPHP表单令牌错误的相关解决方法分析
2016/05/20 PHP
php实现获取近几日、月时间示例
2019/07/06 PHP
javascript抖动元素的小例子
2013/10/28 Javascript
javascript 回到顶部效果的实现代码
2014/02/17 Javascript
jquery对象和javascript对象即DOM对象相互转换
2014/08/07 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
2015/01/22 Javascript
用JavaScript实现PHP的urlencode与urldecode函数
2015/08/13 Javascript
简单谈谈JS数组中的indexOf方法
2016/10/13 Javascript
微信小程序 实现拖拽事件监听实例详解
2016/11/16 Javascript
Vue-cli proxyTable 解决开发环境的跨域问题详解
2017/05/18 Javascript
easyUI下拉列表点击事件使用方法
2017/05/18 Javascript
关于jQuery库冲突的完美解决办法
2017/05/20 jQuery
微信小程序开发之实现自定义Toast弹框
2017/06/08 Javascript
使用async、enterproxy控制并发数量的方法详解
2018/01/02 Javascript
node.js处理前端提交的GET请求
2019/08/30 Javascript
[07:08]2014DOTA2西雅图国际邀请赛 小组赛7月11日TOPPLAY
2014/07/11 DOTA
如何在Python函数执行前后增加额外的行为
2016/10/20 Python
python读取ini配置的类封装代码实例
2020/01/08 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
2013/11/07 HTML / CSS
SmartBuyGlasses台湾:名牌眼镜,名牌太阳眼镜及隐形眼镜
2017/01/04 全球购物
如何现实servlet的单线程模式
2014/08/05 面试题
AJAX检测用户名是否存在的方法
2021/03/24 Javascript
母亲节演讲稿
2014/05/27 职场文书
建筑工地标语
2014/06/18 职场文书
班级标语大全
2014/06/21 职场文书
党员群众路线对照检查材料思想汇报
2014/09/17 职场文书
四风查摆问题自查报告
2014/10/10 职场文书
长城导游词
2015/01/30 职场文书
生日寿星公答谢词
2015/09/29 职场文书