Pytthon:type函数和 isinstance 函数及区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pytthon:type函数和 isinstance 函数及区别相关的知识,希望对你有一定的参考价值。

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

if type(a) is types.ListType:

    所有的基本类型对应的名称都可以在types模块中找得到,如types.BooleanType、types.IntType等等,在安装目录下lib文件夹里,名为types.py。实现方法很简单,把对应的类型赋值给变量。源代码如下:

import sys

# Iterators in Python aren‘t a matter of type but of protocol.  A large
# and changing number of builtin types implement *some* flavor of
# iterator.  Don‘t check the type!  Use hasattr to check for both
# "__iter__" and "next" attributes instead.

NoneType = type(None)
TypeType = type
ObjectType = object

IntType = int
LongType = long
FloatType = float
BooleanType = bool
try:
    ComplexType = complex
except NameError:
    pass

StringType = str

# StringTypes is already outdated.  Instead of writing "type(x) in
# types.StringTypes", you should use "isinstance(x, basestring)".  But
# we keep around for compatibility with Python 2.2.
try:
    UnicodeType = unicode
    StringTypes = (StringType, UnicodeType)
except NameError:
    StringTypes = (StringType,)

BufferType = buffer

TupleType = tuple
ListType = list
DictType = DictionaryType = dict

def _f(): pass
FunctionType = type(_f)
LambdaType = type(lambda: None)         # Same as FunctionType
CodeType = type(_f.func_code)

def _g():
    yield 1
GeneratorType = type(_g())

class _C:
    def _m(self): pass
ClassType = type(_C)
UnboundMethodType = type(_C._m)         # Same as MethodType
_x = _C()
InstanceType = type(_x)
MethodType = type(_x._m)

BuiltinFunctionType = type(len)
BuiltinMethodType = type([].append)     # Same as BuiltinFunctionType

ModuleType = type(sys)
FileType = file
XRangeType = xrange

try:
    raise TypeError
except TypeError:
    tb = sys.exc_info()[2]
    TracebackType = type(tb)
    FrameType = type(tb.tb_frame)
    del tb

SliceType = slice
EllipsisType = type(Ellipsis)

DictProxyType = type(TypeType.__dict__)
NotImplementedType = type(NotImplemented)

# For Jython, the following two types are identical
GetSetDescriptorType = type(FunctionType.func_code)
MemberDescriptorType = type(FunctionType.func_globals)

del sys, _f, _g, _C, _x                           # Not for export

__all__ = list(n for n in globals() if n[:1] != ‘_‘)

    然而,使用type()函数并不是意味着可以高枕无忧了,看看下面的例子就明白了。下面的例子用户类UserInt继承int类型实现定制化,它不支持操作符+=,代码如下:

#coding=utf-8
import types
class UserInt(int):
    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):
        raise NotImplementedError("not support opeation")
    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

输出结果如下:

0

2

2

False

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

再看下面一个例子

class A:
    pass

a = A()
class B:
    pass

b = B()
print type(a) == type(b)

输出结果是True,并不是False,上面两个类是古典类,在古典类中,任意类的实例的type()返回结果都是<type ‘instance‘>。这种情况下使用type()函数确定两个变量类型是否相同,那么得到的结果会截然相反的。

    对于内建基本类型来说,用type()进行类检查可能没有问题,但是在某些特定情况就不行了。那么究竟怎样约束用户的输入类型从而使之与我们期望的类型一致呢?如果类型有对应的工厂函数,可以使用工厂函数对类型做相应转换,如list(),str(),否则可以使用isinstance()函数来检查。原型如下

 isinstance(object, classinfo)

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

>>>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),就可以获得正确结果。



以上是关于Pytthon:type函数和 isinstance 函数及区别的主要内容,如果未能解决你的问题,请参考以下文章

python-内置函数-

23反射进阶

迭代器

Python - - 面向对象 - - 面向对象进阶

python迭代器

聊聊ClassLoader