这两个代码片段之间有什么区别?

使用类型:

import types

if type(a) is types.DictType:
    do_something()
if type(b) in types.StringTypes:
    do_something_else()

使用isinstance:

if isinstance(a, dict):
    do_something()
if isinstance(b, str) or isinstance(b, unicode):
    do_something_else()

当前回答

后者是首选的,因为它将正确处理子类。事实上,由于isinstance()的第二个参数可能是一个元组,因此可以更容易地编写示例:

if isinstance(b, (str, unicode)):
    do_something_else()

或者,使用basestring抽象类:

if isinstance(b, basestring):
    do_something_else()

其他回答

Python中isinstance()和type()之间的区别?

类型检查方式

isinstance(obj, Base)

允许子类实例和多个可能的基:

isinstance(obj, (Base1, Base2))

而类型检查

type(obj) is Base

仅支持引用的类型。


作为旁注,这可能比

type(obj) == Base

因为类是单独的。

避免类型检查-使用多态性(duck类型)

在Python中,通常您希望允许任何类型的参数,将其视为预期的类型,如果对象的行为不符合预期,则会引发适当的错误。这被称为多态性,也称为鸭子型。

def function_of_duck(duck):
    duck.quack()
    duck.swim()

如果上面的代码有效,我们可以假设我们的参数是鸭子。因此,我们可以在其他方面传递鸭子的实际子类型:

function_of_duck(mallard)

或者像鸭子一样工作:

function_of_duck(object_that_quacks_and_swims_like_a_duck)

我们的代码仍然有效。

然而,在某些情况下,需要显式类型检查。也许您对不同的对象类型有一些明智的做法。例如,Pandas Dataframe对象可以从字典或记录中构造。在这种情况下,您的代码需要知道获取的参数类型,以便正确处理。

因此,要回答这个问题:

Python中isinstance()和type()之间的区别?

请允许我演示一下区别:

type

假设如果函数获得某种参数(构造函数的常见用例),则需要确保某种行为。如果检查以下类型:

def foo(data):
    '''accepts a dict to construct something, string support in future'''
    if type(data) is not dict:
        # we're only going to test for dicts for now
        raise ValueError('only dicts are supported for now')

如果我们试图传入一个dict,它是dict的子类(如果我们希望我们的代码遵循Liskov替换的原则,那么子类可以替换类型),我们的代码就会中断!:

from collections import OrderedDict

foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))

引发错误!

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in foo
ValueError: argument must be a dict

不稳定性

但如果我们使用isinstance,我们可以支持Liskov Substitution!:

def foo(a_dict):
    if not isinstance(a_dict, dict):
        raise ValueError('argument must be a dict')
    return a_dict

foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))

return OrderedDict([('fo','bar'),('fizz','buzz')])

抽象基类

事实上,我们可以做得更好。集合提供抽象基类,这些抽象基类为各种类型强制执行最小协议。在我们的情况下,如果我们只期望Mapping协议,我们可以执行以下操作,我们的代码变得更加灵活:

from collections import Mapping

def foo(a_dict):
    if not isinstance(a_dict, Mapping):
        raise ValueError('argument must be a dict')
    return a_dict

对评论的回应:

需要注意的是,类型可以用于使用(A,B,C)中的类型(obj)检查多个类

是的,您可以测试类型的相等性,但不要使用上述方法,而是使用控制流的多个基,除非您只允许这些类型:

isinstance(obj, (A, B, C))

不同之处再次在于,isinstance支持子类,这些子类可以替换父类而不破坏程序,这一特性称为Liskov替换。

但更好的是,颠倒依赖关系,根本不检查特定类型。

结论

因此,由于我们希望支持替换子类,在大多数情况下,我们希望避免使用类型进行类型检查,而更喜欢使用isinstance进行类型检查-除非您确实需要知道实例的精确类。

后者是首选的,因为它将正确处理子类。事实上,由于isinstance()的第二个参数可能是一个元组,因此可以更容易地编写示例:

if isinstance(b, (str, unicode)):
    do_something_else()

或者,使用basestring抽象类:

if isinstance(b, basestring):
    do_something_else()

实际用法的不同之处在于它们如何处理布尔值:

True和False只是python中表示1和0的关键字。因此

isinstance(True, int)

and

isinstance(False, int)

两者都返回True。两个布尔值都是整数的实例。然而,type()更聪明:

type(True) == int

返回False。

type()和isinstance()之间的区别

type()->返回对象的类型

isinstance()->返回布尔值

一般来说,isinstance是一种“更”优雅的检查对象是否属于某种“类型”的方法(因为您知道继承链)。

另一方面,如果您不知道继承链,需要进行pick,请选择类型(x)==。。。

类型的另一个有趣的例子是检查bool

----Case bool----

print(type(True) == int) # False
print(type(False) == int) # False
print(type(True) == bool) # True
print(type(False) == bool) # True

print(isinstance(True, int)) # True
print(isinstance(True, int)) # True



----Case inheritance----
class A:
    x=1

class B(A):
    x=2

class C(B):
    x=3
    
var1 = A()
var2 = B()
var3 = C()

print(type(var1)) # <class '__main__.A'>
print(type(var1) == A) # True
print(type(var2) == A) # False
print(type(var3) == A) # False

print(isinstance(var1, A)) # True
print(isinstance(var2, A)) # True
print(isinstance(var3, A)) # True



print(type(var2)) # <class '__main__.B'>
print(type(var1) == B) # False
print(type(var2) == B) # True
print(type(var3) == B) # False

print(isinstance(var1, B)) # False
print(isinstance(var2, B)) # True
print(isinstance(var3, B)) # True



print(type(var3)) # <class '__main__.C'>
print(type(var1) == C) # False
print(type(var2) == C) # False
print(type(var3) == C) # True

print(isinstance(var1, C)) # False
print(isinstance(var2, C)) # False
print(isinstance(var3, C)) # True

下面是一个例子,isinstance实现了类型无法实现的功能:

class Vehicle:
    pass

class Truck(Vehicle):
    pass

在本例中,卡车对象是车辆,但您将看到:

isinstance(Vehicle(), Vehicle)  # returns True
type(Vehicle()) == Vehicle      # returns True
isinstance(Truck(), Vehicle)    # returns True
type(Truck()) == Vehicle        # returns False, and this probably won't be what you want.

换句话说,对于子类也是如此。

另请参阅:如何比较Python中对象的类型?