python判断变量数据类型时,建议使用isinstance()方法代替type(). 进行类型检查首先想到的就是用type(),但是Type在某些特定情况下判断类型存在问题,今天就来说下type在python类型判断时的坑。
例子: int类型判断
>>> import types>>> type(2017)==types.IntTypeTrue
Python2.7中的types类型:
types.BooleanType # bool类型types.BufferType # buffer类型types.BuiltinFunctionType # 内建函数,比如len()types.BuiltinMethodType # 内建方法,指的是类中的方法types.ClassType # 类类型types.CodeType # 代码块类型types.ComplexType # 复数类型types.DictProxyType # 字典代理类型types.DictType # 字典类型types.DictionaryType # 字典备用的类型types.EllipsisTypetypes.FileType # 文件类型types.FloatType # 浮点类型types.FrameTypetypes.FunctionType # 函数类型types.GeneratorType types.GetSetDescriptorTypetypes.InstanceType # 实例类型types.IntType # int类型types.LambdaType # lambda类型types.ListType # 列表类型types.LongType # long类型types.MemberDescriptorTypetypes.MethodType # 方法类型types.ModuleType # module类型types.NoneType # None类型types.NotImplementedTypetypes.ObjectType # object类型types.SliceTypehtypes.StringType # 字符串类型types.StringTypes types.TracebackType types.TupleType # 元组类型types.TypeType # 类型本身types.UnboundMethodTypetypes.UnicodeType types.XRangeType
Python3.x中的types类型:
types.BuiltinFunctionTypetypes.BuiltinMethodTypetypes.CodeTypetypes.DynamicClassAttributetypes.FrameTypetypes.FunctionTypetypes.GeneratorTypetypes.GetSetDescriptorTypetypes.LambdaTypetypes.MappingProxyTypetypes.MemberDescriptorTypetypes.MethodTypetypes.ModuleTypetypes.SimpleNamespacetypes.TracebackTypetypes.new_classtypes.prepare_class
Python3.x进行了类型的精简
isinstance(object, classinfo)
object表示实例,classinfo可以是直接或间接类名、基本类型或者有它们组成的元组。
基本用法
>>> isinstance(1, int)True>>> >>> isinstance('pythontab.com', (str, int)) # 是其中一种即可True>>> isinstance(100, (str, int)) # 是其中一种即可True
上面type的例子可以表示为:
>>> import types>>> isinstance(2017,int)True
我们来看一下下面的例子。
import typesclass UserInt(int): def __init__(self, val=0): self.val = int(val)i = 1n = UserInt(2)print(type(i) is type(n))
上面的代码输出:False
这就说明i和n的类型是不一样的,而实际上UserInt是继承自int的,所以这个判断是存在问题的,当我们对Python内建类型进行扩展的时候,type返回的结果就不够准确了。我们再看一个例子。
class ca: passclass cb: passa = ca()b = cb()print (type(a) is type(b))
代码的输出结果: True
注意: 这个例子仅仅针对Python2.x版本, Python3.x版本中会返回Flase,不存在该问题
type比较的结果a和b的类型是一样的,结果明显是不准确的。在old-style class中,任意instance的type都是'instance'。所以绝对不能用type来判断其类型。
另外这个问题又与Python的思想有关,正常情况下不应该编写代码检查类型的,而应该直接假设被操作的instance具有你希望的属性,否则抛出异常。即使需要检查类型,也应该用isinstance来判断,这样你期望类型的subclass也能正常被处理(比如,一个函数需要处理Message类型,那么它应该也能处理Message的子类型MyMessage,所以应该使用isinstance(arg,Message)这样来判断而不是type(arg) == Message来判断)
结论:
尽量不要使用type()方法,多使用isinstance(),这样可以减少错误。