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处理字符串之isspace()方法的使用
May 19 Python
Perl中著名的Schwartzian转换问题解决实现
Jun 02 Python
python Socket之客户端和服务端握手详解
Sep 18 Python
Python安装模块的常见问题及解决方法
Feb 05 Python
Python实现线程状态监测简单示例
Mar 28 Python
用python 实现在不确定行数情况下多行输入方法
Jan 28 Python
在Python中实现函数重载的示例代码
Dec 12 Python
使用PyOpenGL绘制三维坐标系实例
Dec 24 Python
pyenv虚拟环境管理python多版本和软件库的方法
Dec 26 Python
opencv python如何实现图像二值化
Feb 03 Python
基于python实现对文件进行切分行
Apr 26 Python
基于python+selenium自动健康打卡的实现代码
Jan 13 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/06/14 PHP
php设计模式之单例、多例设计模式的应用分析
2013/06/30 PHP
thinkphp区间查询、统计查询与SQL直接查询实例分析
2014/11/24 PHP
thinkphp3.2.2实现生成多张缩略图的方法
2014/12/19 PHP
详解Yii2 rules 的验证规则
2016/12/02 PHP
php常用正则函数实例小结
2016/12/29 PHP
详解Yii2高级版引入bootstrap.js的一个办法
2017/03/21 PHP
Javascript 中文字符串处理额外注意事项
2009/11/15 Javascript
用js实现的模拟jquery的animate自定义动画(2.5K)
2010/07/20 Javascript
解析Jquery的LigerUI如何实现文件上传
2013/07/09 Javascript
运用JQuery的toggle实现网页加载完成自动弹窗
2014/03/18 Javascript
当jquery ajax遇上401请求的解决方法
2016/05/19 Javascript
JavaScript正则表达式替换字符串中图片地址(img src)的方法
2017/01/13 Javascript
js学习总结_轮播图之渐隐渐现版(实例讲解)
2017/07/17 Javascript
JS实现动态生成html table表格的方法分析
2018/07/11 Javascript
js简单的分页器插件代码实例
2019/09/11 Javascript
使用vue-cli3+typescript的项目模板创建工程的教程
2020/02/28 Javascript
vue打开其他项目页面并传入数据详解
2020/11/25 Vue.js
Python自动化测试工具Splinter简介和使用实例
2014/05/13 Python
python实现xlsx文件分析详解
2018/01/02 Python
Python实现读取及写入csv文件的方法示例
2018/01/12 Python
Python编写一个验证码图片数据标注GUI程序附源码
2019/12/09 Python
浅谈python元素如何去重,去重后如何保持原来元素的顺序不变
2020/02/28 Python
python实现猜单词游戏
2020/05/22 Python
python中if及if-else如何使用
2020/06/02 Python
Keras load_model 导入错误的解决方式
2020/06/09 Python
基于CentOS搭建Python Django环境过程解析
2020/08/24 Python
Python数据可视化常用4大绘图库原理详解
2020/10/23 Python
CSS3 :not()选择器实现最后一行li去除某种css样式
2016/10/19 HTML / CSS
DC Shoes俄罗斯官网:美国滑板鞋和服饰品牌
2020/08/19 全球购物
什么是托管函数?托管函数有什么用?
2014/06/15 面试题
J2EE系统只能是基于web
2015/09/08 面试题
《学会待客》教学反思
2014/02/22 职场文书
群众路线自查报告及整改措施
2014/11/04 职场文书
给朋友的道歉短信
2015/05/12 职场文书
欠条格式范本
2015/07/03 职场文书