`isinstance(x, y)`和`x.__class__ == y`的区别
`isinstance(x, y)`和`x.__class__ == y`的区别
这两段代码片段之间有什么区别?
使用 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
在这个例子中,一个卡车对象是一个车辆,但你会得到这个结果:
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
好,注意,只是比检查类型的等式不那么坏。正常的、Pythonic的、首选的解决方案几乎总是“鸭子类型”:尝试将参数用作某种所需类型,使用try
/except
语句捕获参数实际上不是该类型(或任何其他优雅地模拟鸭子的类型)时可能出现的所有异常,并在except
子句中尝试其他方法(用参数“as if”它是某种其他类型)。
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也可以通过模板方法设计模式应用非常自然地为实际子类提供额外的便利(有关模板方法模式的更多信息,请参见这里和这里 [[第二部分]],关于TM DP的一般和特定的Python,与ABC无关)。
有关Python 2.6中提供的ABC支持的基本机制,请参见这里;对于它们的3.1版本,非常相似,请参见这里。在两个版本中,标准库模块collections(这是3.1版本-对于非常相似的2.6版本,请参见这里)提供了几个有用的ABC。
为了回答这个问题,需要记住有关ABC的关键事情(除了在TM DP功能上与传统Python替代品(如UserDict.DictMixin)相比更自然的放置之外)是,它们使得在Python 2.6及以后版本中广泛使用isinstance(和issubclass),比以前更有吸引力和普遍性,因此相比之下,使得在最近的Python版本中检查类型相等性的做法更糟糕。