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脚本实现自动将数据库备份到 Dropbox
Feb 06 Python
Python爬取网页中的图片(搜狗图片)详解
Mar 23 Python
Python中动态检测编码chardet的使用教程
Jul 06 Python
python安装Scrapy图文教程
Aug 14 Python
基于python元祖与字典与集合的粗浅认识
Aug 23 Python
Django数据库表反向生成实例解析
Feb 06 Python
Django学习笔记之ORM基础教程
Mar 27 Python
python 文件转成16进制数组的实例
Jul 09 Python
通过python将大量文件按修改时间分类的方法
Oct 17 Python
python 在屏幕上逐字显示一行字的实例
Dec 24 Python
使用Python将字符串转换为格式化的日期时间字符串
Sep 01 Python
python安装及变量名介绍详解
Dec 12 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函数,php爱好者站推荐
2007/03/19 PHP
PHP XML数据解析代码
2010/05/26 PHP
PHP 获取文件权限函数介绍
2013/07/11 PHP
workerman结合laravel开发在线聊天应用的示例代码
2018/10/30 PHP
Mootools 1.2教程 设置和获取样式表属性
2009/09/15 Javascript
Jquery读取URL参数小例子
2013/08/30 Javascript
Javascript学习笔记之函数篇(五) : 构造函数
2014/11/23 Javascript
jQuery实现预加载图片的方法
2015/03/17 Javascript
jquery实现图片上传之前预览的方法
2015/07/11 Javascript
JavaScript的jQuery库插件的简要开发指南
2015/08/12 Javascript
Underscore源码分析
2015/12/30 Javascript
Angularjs之filter过滤器(推荐)
2016/11/27 Javascript
jQuery基本筛选选择器实例代码
2017/02/06 Javascript
详解nodejs中exports和module.exports的区别
2017/02/17 NodeJs
JavaScript使用FileReader实现图片上传预览效果
2020/03/27 Javascript
jQuery EasyUI Layout实现tabs标签的实例
2017/09/26 jQuery
分享vue.js devtools遇到一系列问题
2017/10/24 Javascript
移动端自适应flexible.js的使用方法(不用三大框架,仅写一个单html页面使用)推荐
2019/04/02 Javascript
JS阻止事件冒泡的方法详解
2019/08/26 Javascript
8个非常实用的Vue自定义指令
2020/12/15 Vue.js
Node.js中的异步生成器与异步迭代详解
2021/01/31 Javascript
python读取二进制mnist实例详解
2017/05/31 Python
利用python获取当前日期前后N天或N月日期的方法示例
2017/07/30 Python
Python3.遍历某文件夹提取特定文件名的实例
2018/04/26 Python
python 遍历目录(包括子目录)下所有文件的实例
2018/07/11 Python
django有外键关系的两张表如何相互查找
2020/02/10 Python
python如何求100以内的素数
2020/05/27 Python
Html5页面点击遮罩层背景关闭遮罩层
2020/11/30 HTML / CSS
Feelunique澳大利亚:欧洲的化妆品零售电商
2019/12/18 全球购物
婚庆司仪主持词
2014/03/15 职场文书
水毁工程实施方案
2014/04/01 职场文书
勤俭节约倡议书
2014/04/14 职场文书
产品售后服务承诺书
2014/05/21 职场文书
简单租房协议书范本
2014/08/20 职场文书
2015年房产销售工作总结范文
2015/05/22 职场文书
九年级历史教学反思
2016/02/19 职场文书