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中time()方法的使用的教程
May 22 Python
实例讲解Python编程中@property装饰器的用法
Jun 20 Python
Python线性方程组求解运算示例
Jan 17 Python
PyCharm配置mongo插件的方法
Nov 30 Python
利用Python对文件夹下图片数据进行批量改名的代码实例
Feb 21 Python
搭建python django虚拟环境完整步骤详解
Jul 08 Python
Django 多表关联 存储 使用方法详解 ManyToManyField save
Aug 09 Python
解决python 文本过滤和清理问题
Aug 28 Python
解决Jupyter Notebook开始菜单栏Anaconda下消失的问题
Apr 13 Python
django有哪些好处和优点
Sep 01 Python
Python根据字典的值查询出对应的键的方法
Sep 30 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
Nov 26 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无限分类的类
2007/01/02 PHP
php生成随机密码的三种方法小结
2010/09/04 PHP
ecshop适应在PHP7的修改方法解决报错的实现
2016/11/01 PHP
替换php字符串中的单引号为双引号的方法
2017/02/16 PHP
Thinkphp通过一个入口文件如何区分移动端和PC端
2017/04/18 PHP
TNC vs BOOM BO3 第二场2.13
2021/03/10 DOTA
如何取得中文输入的真实长度?
2006/06/24 Javascript
Javascript中的Split使用方法与技巧
2007/03/09 Javascript
Chrome Form多次提交表单问题的解决方法
2011/05/09 Javascript
Jquery插件写法笔记整理
2012/09/06 Javascript
简单的Jquery全选功能
2013/11/07 Javascript
javascript中var的重要性分析
2015/02/11 Javascript
jQuery插件实现大图全屏图片相册
2015/03/14 Javascript
jQuery中bind(),live(),delegate(),on()绑定事件方法实例详解
2016/01/19 Javascript
Java  Spring 事务回滚详解
2016/10/17 Javascript
详解Vue方法与事件
2017/03/09 Javascript
详解nodejs微信jssdk后端接口
2017/05/25 NodeJs
vue路由跳转时判断用户是否登录功能的实现
2017/10/26 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
使用Easyui实现查询条件的后端传递并自动刷新表格的两种方法
2019/09/09 Javascript
vue+element tabs选项卡分页效果
2020/06/29 Javascript
简单的抓取淘宝图片的Python爬虫
2014/12/25 Python
Python挑选文件夹里宽大于300图片的方法
2015/03/05 Python
Python3基础教程之递归函数简单示例
2019/06/07 Python
python+opencv像素的加减和加权操作的实现
2019/07/14 Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
2021/01/27 Python
HTML5手机端弹出遮罩菜单特效代码
2016/01/27 HTML / CSS
薇诺娜官方网上商城:专注敏感肌肤
2017/05/25 全球购物
服务承诺书怎么写
2014/05/24 职场文书
工作骂脏话检讨书
2014/10/05 职场文书
工作批评与自我批评范文
2014/10/16 职场文书
幼儿园个人总结
2015/02/28 职场文书
2016年党校科级干部培训班学习心得体会
2016/01/06 职场文书
CSS 文字装饰 text-decoration & text-emphasis 详解
2021/04/06 HTML / CSS
详解JavaScript中的执行上下文及调用堆栈
2021/04/29 Javascript
Android开发之WECHAT微信小程序路由跳转的两种形式
2022/04/12 Java/Android