Python 不推荐使用type来进行类型检查,作为动态性的强类型脚本语言,Python中的变量在定义的时候并不会指明具体类型,Python解释器会在运行时自动进行类型检查并根据需要进行隐式类型转换。按照Python的理念,为了充分利用其动态性的特征是不推荐进行类型检查的。如下面的函数add(),在无需对参数进行任何约束的情况下便可以轻松地实现字符串的连接、数字的加法、列表的合并等多种功能,甚至处理复数都非常灵活。解释器能够根据变量类型的不同调用合适的内部方法进行处理,而当a、b类型不同而两者之间又不能进行隐式类型转换时便抛出TypeError异常。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
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'))
# 不同类型
输出如下:
不刻意进行类型检查,而是在出错的情况下通过抛出异常来进行处理,这是较为常见的方式。但实际应用中为了提高程序的健壮性,仍然会面临需要进行类型检查的情景。那么使用什么方法呢?很容易想到,使用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)
,以获取正确的结果。
酷客网相关文章:
评论前必须登录!
注册