type()和isinstance()有什么区别?
type()和isinstance()有什么区别?
这两个代码片段之间有什么区别?
使用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()
以下是翻译内容:
下面是一个示例,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
对于子类也是成立的。
还可以参见:如何在 Python 中比较对象的类型?
总结其他(已经很好的)回答的内容,isinstance
能够支持继承(派生类的实例也是基类的实例),而检查 type
的等式则不支持继承(它要求类型相同,拒绝子类型的实例,即子类实例)。
通常,在 Python 中,当然希望代码支持继承(因为继承非常方便,停止使用继承会很糟糕!),所以 isinstance
比检查 type
的等式更好,因为它无缝支持继承。
这并不是说 isinstance
很好,注意,它只是比检查类型的等式更好。正常的、符合 Python 风格的首选解决方案几乎总是“鸭子类型”:尝试将参数用作某种所需类型,使用 try
/except
语句进行操作,捕获可能发生的所有异常,以确保参数实际上是该类型(或任何其他很好地模仿它的鸭子类型),并在 except
子句中尝试其他事情(假设参数是其他某种类型)。
basestring
是一种特殊情况,它是一种内置类型,仅存在于让你使用 isinstance
(str
和 unicode
都是 basestring
的子类)。字符串是序列(你可以循环、索引、切片它们,...),但通常你想将它们视为“标量”类型,这有点不方便(但是是一个相当频繁的用例),将所有种类的字符串(以及可能是其他标量类型,即你无法循环的类型)一种方式处理,所有容器(列表、集合、字典,...)另一种方式,basestring
加上 isinstance
可以帮助你做到这一点——这种习惯用法的总体结构如下:
if isinstance(x, basestring) return treatasscalar(x) try: return treatasiter(iter(x)) except TypeError: return treatasscalar(x)
你可以说 basestring
是一个抽象基类("ABC")——它没有为子类提供任何具体的功能,而是作为一个“标记”存在,主要用于 isinstance
。这个概念在 Python 中显然是一个日益增长的概念,因为PEP 3119引入了它的一般化,已被接受并从 Python 2.6 和 3.0 开始实现。
该PEP明确指出,尽管ABC通常可以替代鸭子类型,但通常没有太大的压力这样做(请参见此处)。近期Python版本中实现的ABC确实提供了额外的好处: isinstance
(和 issubclass
)现在可以意味着不仅仅是“[派生类的]实例”(特别是,任何类都可以与ABC“注册”,以便它将显示为子类,其实例为ABC的实例);并且ABC也可以通过模板方法设计模式应用以非常自然的方式为实际子类提供额外的便利(请参见这里和这里[[part II]],了解有关TM DP的更多信息,包括Python中的一般和具体内容,独立于ABC)。
对于 Python 2.6 提供的 ABC 支持的底层机制,请参见此处;对于它们的 3.1 版本,非常相似,请参见此处。在这两个版本中,标准库模块collections(这是 3.1 版本,非常相似的 2.6 版本,请参见此处)提供了几个有用的 ABC。
对于这个答案的目的,ABC 的关键是要记住(除了 TM DP 功能可能比诸如UserDict.DictMixin这样的混合类更自然之外),它们使 isinstance
(和 issubclass
)比它们在 Python 2.5 及之前版本中更具吸引力和普遍性(在 Python 2.6 及其之后的版本中),因此相比之下,使检查类型相等成为近期 Python 版本中更糟糕的做法。