这两个代码片段有什么区别?
使用 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()
原文由 abbot 发布,翻译遵循 CC BY-SA 4.0 许可协议
总结其他(已经很好!)答案的内容,
isinstance
迎合继承(派生类 的 实例也是基类的实例),同时检查type
的相等性---
没有(它要求类型的标识并拒绝子类型的实例,AKA 子类)。通常,在 Python 中,您当然希望您的代码支持继承(由于继承非常方便,因此阻止使用您的代码使用它会很糟糕!),所以
isinstance
不如检查type
s 的身份,因为它无缝支持继承。请注意,这并不是说
isinstance
_很好_——它只是 比 检查类型的相等性要好。正常的、Pythonic 的首选解决方案几乎总是“鸭子类型”:尝试使用参数 ,就好像 它是某种所需类型一样,在try
/except
语句中执行如果参数实际上不是该类型(或任何其他类型很好地模仿它;-),则可能出现的所有异常,并且在except
子句中,尝试其他方法(使用参数“as如果”它是其他类型的)。basestring
is , however, quite a special case—a builtin type that exists only to let you useisinstance
(bothstr
andunicode
子类basestring
)。字符串是序列(你可以循环它们,索引它们,切片它们,……),但你通常希望将它们视为“标量”类型——处理各种类型的字符串有点不方便(但相当频繁的用例)字符串(可能还有其他标量类型,即不能循环的)一种方式,所有容器(列表,集合,字典,…)另一种方式,以及basestring
加上isinstance
帮助你做到这一点——这个成语的整体结构是这样的:你可以说
basestring
是一个 _抽象基类_(“ABC”)——它不为子类提供具体功能,而是作为“标记”存在,主要用于isinstance
.这个概念在 Python 中显然是一个不断发展的概念,因为 PEP 3119 引入了它的泛化,被接受并从 Python 2.6 和 3.0 开始实施。PEP 明确指出,虽然 ABC 通常可以替代鸭式打字,但这样做通常没有太大的压力(请参阅 此处)。然而,在最近的 Python 版本中实现的 ABC 确实提供了额外的好处:
isinstance
(和issubclass
)现在不仅仅意味着“[一个]派生类的实例”(特别是,任何类都可以在 ABC 中“注册”,以便将其显示为子类,并将其实例显示为 ABC 的实例);和 ABC 还可以通过模板方法设计模式应用程序以非常自然的方式为实际子类提供额外的便利(有关 TM DP 的更多信息,请参阅 此处 和 此处[[part II]],一般而言,特别是在 Python 中,独立于 ABC) .有关 Python 2.6 中提供的 ABC 支持的底层机制,请参见 此处;对于他们的 3.1 版本,非常相似,请参见 此处。在这两个版本中,标准库模块 集合(即 3.1 版本——非常相似的 2.6 版本,请参见 此处)提供了几个有用的 ABC。
就这个答案而言,保留关于 ABC 的关键(除了可以说是 TM DP 功能更自然的位置,与诸如 UserDict.DictMixin 之类的 mixin 类的经典 Python 替代方案相比)是它们使
isinstance
(和issubclass
)比以前(在 Python 2.6 和以后的版本中)更具吸引力和普遍性(在 2.5 和之前的版本中),因此,相比之下,检查类型相等性变得更糟在最近的 Python 版本中进行练习,而不是以前。