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下的Softmax回归函数的实现方法(推荐)
Jan 26 Python
Python入门_浅谈数据结构的4种基本类型
May 16 Python
Python爬虫天气预报实例详解(小白入门)
Jan 24 Python
django中的HTML控件及参数传递方法
Mar 20 Python
Python中数组,列表:冒号的灵活用法介绍(np数组,列表倒序)
Apr 18 Python
PyCharm代码提示忽略大小写设置方法
Oct 28 Python
浅析Python3中的对象垃圾收集机制
Jun 06 Python
python面试题之列表声明实例分析
Jul 08 Python
python中eval与int的区别浅析
Aug 11 Python
春节到了 教你使用python来抢票回家
Jan 06 Python
基于python实现微信好友数据分析(简单)
Feb 16 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
Oct 10 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 批量删除数据的方法分析
2009/10/30 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
curl实现站外采集的方法和技巧
2014/01/31 PHP
PHP中字符串长度的截取用法示例
2017/01/12 PHP
Yii2使用表单上传文件的实例代码
2017/08/03 PHP
网站上面有这种切换效果
2006/06/26 Javascript
JavaScript 学习笔记(九)call和apply方法
2010/01/11 Javascript
JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型
2012/10/11 Javascript
Javascript模块化编程(一)模块的写法最佳实践
2013/01/17 Javascript
JS实现图片横向滚动效果示例代码
2013/09/04 Javascript
javascript 实现字符串反转的三种方法
2013/11/23 Javascript
javascript先序遍历DOM树的方法
2016/02/27 Javascript
javascript 中iframe高度自适应(同域)实例详解
2017/05/16 Javascript
解决Mac安装thrift因bison报错的问题
2018/05/17 Javascript
详解如何从零开始搭建Express+Vue开发环境
2018/07/17 Javascript
vue实现pdf导出解决生成canvas模糊等问题(推荐)
2018/10/18 Javascript
详解vue中移动端自适应方案
2019/05/05 Javascript
ES6 Array常用扩展的应用实例分析
2019/06/26 Javascript
package.json中homepage属性的作用详解
2020/03/11 Javascript
微信小程序选择图片控件
2021/01/19 Javascript
[00:16]热血竞技场
2019/03/06 DOTA
matplotlib实现热成像图colorbar和极坐标图的方法
2018/12/13 Python
对python中词典的values值的修改或新增KEY详解
2019/01/20 Python
Pyqt5 基本界面组件之inputDialog的使用
2019/06/25 Python
python中单下划线(_)和双下划线(__)的特殊用法
2019/08/29 Python
pytorch下大型数据集(大型图片)的导入方式
2020/01/08 Python
python GUI库图形界面开发之PyQt5多行文本框控件QTextEdit详细使用方法实例
2020/02/28 Python
Myprotein葡萄牙官方网站:英国优质运动营养品牌
2016/09/12 全球购物
Amara德国:家居饰品、设计师品牌和豪华礼品
2019/05/20 全球购物
实习期自我鉴定
2013/10/11 职场文书
远程研修随笔感言
2014/02/10 职场文书
写字楼租赁意向书
2014/07/30 职场文书
公司离职证明标准范本
2014/10/05 职场文书
承德避暑山庄导游词
2015/02/03 职场文书
2015年服务员工作总结
2015/04/08 职场文书
Java的Object类的九种方法
2022/04/13 Java/Android