代码之家  ›  专栏  ›  技术社区  ›  abbot

type()和isinstance()有什么区别?

  •  1540
  • abbot  · 技术社区  · 16 年前

    使用 type :

    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()
    
    8 回复  |  直到 3 年前
        1
  •  1103
  •   Uyghur Lives Matter    8 年前

    总结其他(已经很好了!)答案的内容, isinstance 迎合继承(派生类的实例 是一个 基类的实例),同时检查 type 没有(它要求类型的身份,并拒绝子类型的实例,即AKA子类)。

    通常,在Python中,你当然希望你的代码支持继承(因为继承非常方便,所以阻止使用你的代码使用它是不好的!),所以

    并非如此 请注意,这只是 而不是检查类型的相等性。通常,Python式的首选解决方案几乎总是“鸭子打字”:尝试使用参数 这是某种想要的类型,用一种 try / except

    basestring 然而,这是一个相当特殊的情况,即存在一种内置类型 让你使用 (两者 str unicode 子类 基线 ).字符串是序列(你可以对它们进行循环、索引、切片等),但你通常希望将它们视为“标量”类型。以一种方式处理各种字符串(可能还有其他标量类型,即你不能循环的类型),以另一种方式处理所有容器(列表、集合、字典等),这有点不方便(但是一个相当频繁的用例) 基线

    if isinstance(x, basestring)
      return treatasscalar(x)
    try:
      return treatasiter(iter(x))
    except TypeError:
      return treatasscalar(x)
    

    基线 是一个 抽象基类 (“ABC”)它没有为子类提供具体的功能,而是作为一个“标记”存在,主要用于 是实例 这个概念在Python中显然是一个不断发展的概念,因为 PEP 3119 引入了它的泛化,被接受并从Python 2.6和3.0开始实现。

    政治公众人物明确表示,虽然ABC通常可以代替鸭子打字,但通常没有太大的压力(见 here 是实例 (以及 issubclass )现在可以不仅仅意味着“派生类的[实例]”(特别是,任何类都可以在ABC中“注册”,这样它就会显示为子类,其实例也会显示为ABC的实例);ABC还可以通过模板方法设计模式应用程序以非常自然的方式为实际的子类提供额外的便利(参见 here here

    有关Python 2.6中提供的ABC支持的底层机制,请参阅 here 关于它们的3.1版本,非常相似,请参见 here 在这两个版本中,标准库模块 collections (这是非常相似的2.6版本的3.1版本,请参阅 here )提供了几个有用的ABC。

    UserDict.DictMixin 是实例 (以及 问题等级 )与过去(2.5及之前)相比,它们(在Python 2.6及以后)更具吸引力和普遍性,因此,相比之下,在最近的Python版本中,检查类型相等性比以前更糟糕。

        2
  •  287
  •   Community Mohan Dere    9 年前

    这里有一个例子 isinstance type

    class Vehicle:
        pass
    
    class Truck(Vehicle):
        pass
    

    Truck 对象是 Vehicle ,但你会得到这个:

    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.
    

    换言之, isinstance()

    How to compare type of an object in Python?

        3
  •  78
  •   Aaron Hall    7 年前

    差异 isinstance() type()

    类型检查

    isinstance(obj, Base)
    

    isinstance(obj, (Base1, Base2))
    

    而类型检查

    type(obj) is Base
    

    仅支持引用的类型。


    is 可能比

    type(obj) == Base
    

    因为班级都是单身。

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

    如果上面的代码有效,我们可以假设我们的论点是一只鸭子。因此,我们可以在其他事物中传递鸭子的实际子类型:

    function_of_duck(mallard)
    

    function_of_duck(object_that_quacks_and_swims_like_a_duck)
    

    然而,在某些情况下,需要显式地键入check。 也许你对不同的对象类型有一些明智的事情要做。例如,Pandas Dataframe对象可以从字典中构造出来

    那么,回答这个问题:

    差异 is实例()

    请允许我演示一下区别:

    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 (如果我们希望我们的代码遵循以下原则,我们应该能够做到这一点 Liskov Substitution ,该子类型可以替换类型)我们的代码中断了!:

    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

    但如果我们使用 是实例 ,我们可以支持利斯科夫替换!:

    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')]))
    

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

    抽象基类

    collections 提供抽象基类,为各种类型强制执行最低协议。在我们的情况下,如果我们只期望 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
    

    应该注意的是,type可用于检查多个类,使用 type(obj) in (A, B, C)

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

    不同之处在于 是实例 支持可以在不破坏程序的情况下替换父类的子类,这是一种称为Liskov替换的属性。

    不过,更好的是,反转您的依赖关系,根本不检查特定类型。

    类型 更喜欢用以下方式进行类型检查 是实例

        4
  •  58
  •   Esparta Palma John Millikin    12 年前

    isinstance()

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

    basestring

    if isinstance(b, basestring):
        do_something_else()
    
        5
  •  11
  •   Grijesh Chauhan Anand Krishnan    12 年前

    booleans :

    True False 只是意味着 1 0 在python中。因此,

    isinstance(True, int)
    

    isinstance(False, int)
    

    两者都回来了 两个布尔值都是整数的实例。 type()

    type(True) == int
    

    回报 .

        6
  •  0
  •   Cheney    8 年前

    8.15. types — Names for built-in types

    从Python 2.2开始,内置 int() str() 也是

    所以 isinstance() 应优先于 type() .