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

原文由 abbot 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 435
2 个回答

总结其他(已经很好!)答案的内容, 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 use isinstance (both str and 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 还可以通过模板方法设计模式应用程序以非常自然的方式为实际子类提供额外的便利(有关 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 版本中进行练习,而不是以前。

原文由 Alex Martelli 发布,翻译遵循 CC BY-SA 3.0 许可协议

这是一个示例,其中 isinstance 实现了 type 无法实现的功能:

 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 也适用于子类。

另请参阅: How to compare type of an object in Python?

原文由 Peter 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题