oop - pytho isinstance( ) 和type( ) 之间的差异

  显示原文与译文双语对照的内容

这两个代码Fragment之间的区别是什么? 哪个方法被认为更 Pythonic?

使用 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()

这似乎是已经讨论了编辑: 链接

时间:

这就是为什么 isinstancetype 更好的原因:


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.

换句话说,对于子类来说,isinstance 是真的。

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

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


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

或者,使用 basestring 抽象类:


if isinstance(b, basestring):
 do_something_else()

根据 python 文档,下面是一个声明:

8.15.键入内置类型的—名称

从 python 2.2开始,内置的工厂函数如 int()str() 也是相应类型的名称。

因此,isinstance() 应该优于 type()

我是针对这个问题的典型答案:

isinstance() 之间的差异和 type()

在 python 中,通常要允许参数的任何类型,如预期的那样对待它,如果对象没有按预期方式运行,它将引发一个适当的错误。 但是,在某些情况下,需要显式地 type-check 。

请允许我演示差异:

type

假设你需要确保你的函数得到了某种类型的参数( 构造函数的公共 use-case ) 。 如果你检查这样的类型:


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

如果我们尝试传递一个 dict ( 如果保持子类型替换的坚实原则,我们应该能够将类型替换为类型) 子类的dict,我们的代码会中断


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

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


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-checking和喜欢与 isinstance type-checking 。

...