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实现调用其他python脚本的方法
Oct 05 Python
使用Python的Scrapy框架编写web爬虫的简单示例
Apr 17 Python
python使用装饰器和线程限制函数执行时间的方法
Apr 18 Python
Python操作列表之List.insert()方法的使用
May 20 Python
深入理解Django中内置的用户认证
Oct 06 Python
详解如何为eclipse安装合适版本的python插件pydev
Nov 04 Python
Python小工具之消耗系统指定大小内存的方法
Dec 03 Python
python Django中models进行模糊查询的示例
Jul 18 Python
python实现桌面托盘气泡提示
Jul 29 Python
Python学习笔记之列表和成员运算符及列表相关方法详解
Aug 22 Python
pytorch使用tensorboardX进行loss可视化实例
Feb 24 Python
python利用 keyboard 库记录键盘事件
Oct 16 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
改造一台复古桌面收音机
2021/03/02 无线电
PHP中的串行化变量和序列化对象
2006/09/05 PHP
php上的memcache和memcached两个pecl库
2010/03/29 PHP
PHP无敌近乎加密方式!
2010/07/17 PHP
php并发对MYSQL造成压力的解决方法
2013/02/21 PHP
PHP根据key删除数组中指定的元素
2019/02/28 PHP
php pdo连接数据库操作示例
2019/11/18 PHP
EXT窗口Window及对话框MessageBox
2011/01/27 Javascript
js实现在文本框光标处添加字符的方法介绍
2012/11/24 Javascript
RequireJS入门一之实现第一个例子
2015/09/30 Javascript
jQuery中的siblings用法实例分析
2015/12/24 Javascript
js改变style样式和css样式的简单实例
2016/06/28 Javascript
Javascript Function.prototype.bind详细分析
2016/12/29 Javascript
详解使用vscode+es6写nodejs服务端调试配置
2017/09/21 NodeJs
Thinkjs3新手入门之如何使用静态资源目录
2017/12/06 Javascript
浅谈js获取ModelAndView值的问题
2018/03/28 Javascript
extract-text-webpack-plugin用法详解
2019/02/14 Javascript
arcgis.js控制地图地体的显示范围超出区域自动弹回(实现思路)
2021/01/28 Javascript
[52:00]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 LGD vs Optic
2018/04/02 DOTA
Python操作SQLite简明教程
2014/07/10 Python
python2.7和NLTK安装详细教程
2018/09/19 Python
python实现控制COM口的示例
2019/07/03 Python
python3在同一行内输入n个数并用列表保存的例子
2019/07/20 Python
Python3实现打印任意宽度的菱形代码
2020/04/12 Python
纽约海:Sea New York
2018/11/04 全球购物
三星印度官网:Samsung印度
2019/08/03 全球购物
应届生求职简历的自我评价怎么写
2013/10/23 职场文书
机械电子工程专业推荐信范文
2013/11/20 职场文书
运动会广播稿50字-100字
2014/10/11 职场文书
英语辞职信怎么写
2015/02/28 职场文书
事业单位财务人员岗位职责
2015/04/14 职场文书
上诉状格式
2015/05/23 职场文书
心术观后感
2015/06/11 职场文书
暑期工社会实践报告
2015/07/13 职场文书
技能培训通讯稿
2015/07/18 职场文书
2015年除四害工作总结
2015/07/23 职场文书