一尘不染

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

python

这两个代码片段之间有什么区别?使用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()

阅读 490

收藏
2020-02-08

共1个答案

一尘不染

总结答案的内容,isinstance迎合继承(派生类的实例也是基类的实例),而检查的相等性type则不(要求类型的标识并拒绝实例)子类型,又称为AKA子类)。

通常,在Python中,你当然希望你的代码支持继承(因​​为继承非常方便,因此停止使用你的代码来使用它会很糟糕!),因此isinstance它比检查types的身份要糟糕得多,因为它无缝地支持s遗产。

这并不是说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。自从引入PEP 3119(引入了它的概括)以来,该概念显然在Python中正在不断发展。自从2.6和3.0开始,PEP 3119被接受并实现。

PEP清楚地表明,尽管ABC通常可以代替鸭类打字,但这样做通常没有太大的压力(请参阅此处)。然而,在最近的Python版本中实现的ABC确实提供了额外的好处:(isinstanceissubclass)现在的含义不仅仅是“派生类的一个实例”(尤其是,任何类都可以在ABC中“注册”,以便它可以显示为子类,其实例显示为ABC实例);并且ABC还可以通过Template Method设计模式应用程序以一种非常自然的方式为实际子类提供额外的便利(有关TM DP的更多信息,请参见此处和此处的 [[Part II]],有关Python的更多信息,特别是在Python中,与ABC无关) 。

有关Python 2.6中提供的ABC支持的基本机制,请参见此处;其3.1版本非常相似,请参见此处。在这两个版本中,标准库模块集合(即3.1版本-对于非常相似的2.6版本,请参见此处)都提供了一些有用的ABC。

出于这个答案的目的,保留ABC的关键之处(与TM DP功能的经典Python替代方法(如UserDict.DictMixin相比,TM DP功能的布局自然可以说是更自然的))是,它们使isinstance(和issubclass)具有更多的优势。 (在Python 2.6及更高版本中)比以前(在2.5及更低版本中)更具吸引力和普遍性,因此,相比之下,使类型相等性检查在最近的Python版本中比以前更加糟糕。

2020-02-08