返回介绍

建议12:不推荐使用 type 来进行类型检查

发布于 2024-01-30 22:19:09 字数 2919 浏览 0 评论 0 收藏 0

作为动态性的强类型脚本语言,Python中的变量在定义的时候并不会指明具体类型,Python解释器会在运行时自动进行类型检查并根据需要进行隐式类型转换。按照Python的理念,为了充分利用其动态性的特征是不推荐进行类型检查的。如下面的函数add(),在无需对参数进行任何约束的情况下便可以轻松地实现字符串的连接、数字的加法、列表的合并等多种功能,甚至处理复数都非常灵活。解释器能够根据变量类型的不同调用合适的内部方法进行处理,而当a、b类型不同而两者之间又不能进行隐式类型转换时便抛出TypeError异常。

def add(a, b):
  return a+b
print add(1,2j)     
①复数相加
print add('a','b')    
②字符串连接
print add(1,2)      
③整数
print add(1.0,2.3)    
④浮点数处理
print add([1,2],[2,3])  
⑤处理列表
print add(1,'a')    
⑥不同类型

输出如下:

(1+2j)
ab
3
3.3
[1, 2, 2, 3]
Traceback (most recent call last):
  File "tests.py", line 9, in <module>
  print add(1,'a')
  File "tests.py", line 2, in add
  return a+b
TypeError: unsupported operand type(s) for +: 'int' and 'str'

不刻意进行类型检查,而是在出错的情况下通过抛出异常来进行处理,这是较为常见的方式。但实际应用中为了提高程序的健壮性,仍然会面临需要进行类型检查的情景。那么使用什么方法呢?很容易想到,使用type()。

内建函数type(object)用于返回当前对象的类型,如type(1)返回<type 'int'>。因此可以通过与Python自带模块types中所定义的名称进行比较,根据其返回值确定变量类型是否符合要求。例如判断一个变量a是不是list类型可以使用以下代码:

if type(a) is types.ListType:

所有基本类型对应的名称都可以在types模块中找到,如types.BooleanType、types.IntType、types.StringType、types.DictType等。然而使用type()函数并不是就意味着可以高枕无忧了,主张“不推荐使用type来进行变量类型检查”是有一定的缘由的。来看几个例子。

示例一:下例中用户类UserInt继承int类实现定制化,它不支持操作符+=。具体代码如下:

import types
class UserInt(int) :          #int
为UserInt
的基类
  def __init__(self, val=0) :
    self._val = int(val)
  def __add__(self, val) :      #
实现整数的加法
    if isinstance(val,UserInt):
      return UserInt(self._val + val._val)
    return self._val + val
  def __iadd__(self, val) :       
①UserInt
不支持+=
操作
    raise NotImplementedError("not support operation")
  def __str__(self) : 
    return str(self._val)
  def __repr__(self) :
    return 'Integer(%s)' %self._val       
n = UserInt()
print n
m = UserInt(2)
print m
print n+m
print type(n) is types.IntType      
②使用type
进行类型判断

程序输出如下:

0
2
2
False

上例标注②处输出False,这说明type()函数认为n并不是int类型,但UserInt继承自int,显然这种判断不合理。由此可见基于内建类型扩展的用户自定义类型,type函数并不能准确返回结果。

示例二:在古典类中,所有类的实例的type值都相等。

>>> class A:
...  pass
... 
>>> a = A()
>>> class B:
...  pass
... 
>>> b = B()
>>> type(a) == type(b)             #
判断两者类型是否相等
True

在古典类中,任意类的实例的type()返回结果都是<type 'instance'>。这种情况下使用type()函数来确定两个变量类型是否相同显然结果会与我们所理解的大相径庭。

因此对于内建的基本类型来说,也许使用type()进行类型检查问题不大,但在某些特殊场合type()方法并不可靠。那么究竟应怎样来约束用户的输入类型从而使之与我们期望的类型一致呢?答案是:如果类型有对应的工厂函数,可以使用工厂函数对类型做相应转换,如list(listing)、str(name)等,否则可以使用isinstance()函数来检测,其原型如下:

isinstance(object, classinfo)
;

其中,classinfo可以为直接或间接类名、基本类型名称或者由它们组成的元组,该函数在classinfo参数错误的情况下会抛出TypeError异常。

isinstance基本用法举例如下:

>>> isinstance(2,float)
False
>>> isinstance("a",(str,unicode))
True
>>> isinstance((2,3),(str,list,tuple))  
①支持多种类型列表
True

因此示例一中可以将print type(n) is types.IntType改为print isinstance(n,int),以获取正确的结果。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文