文章来源:Type()和isinstance()有什么区别? - 代码领悟code05.com
提问:Python中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
的相等性则没有(它要求类型的标识并拒绝子类型的实例,又名子类)。
通常,在Python中,您希望您的代码支持继承,当然(由于继承非常方便,因此阻止使用您的代码使用它会很糟糕!),所以isinstance
比检查type
s的身份更糟糕,因为它无缝地支持继承。
这并不是说isinstance
是_好的_,请注意—它只是_比检查类型的相等性更少坏_。 正常的,Pythonic的,首选的解决方案几乎总是"鸭子类型":尝试使用参数_,好像_它是某种期望的类型,在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中显然是一个不断增长的概念,因为PEP3119引入了它的泛化,被接受并从Python2.6和3.0开始实施。
PEP清楚地表明,虽然Abc通常可以代替鸭子打字,但通常没有很大的压力(见here)。 然而,在最近的Python版本中实现的abc确实提供了额外的好处:isinstance
(和issubclass
)现在不仅仅意味着"[一个]派生类的实例"(特别是,任何类都可以用ABC"注册",以便它将显示为子类,其实例作为ABC的实例);并且Abc还可以通过模板方法设计模式应用程序以非常自然的方式为实际子类提供额外的便利(参见here和这里[[第二部分]]有关tm dp的更多信息,一般情况下,特别是在python中,独立于abcs)。
有关Python2.6中提供的ABC支持的底层机制,请参阅here;对于他们的3.1版本,非常相似,请参阅here。 在这两个版本中,标准库模块集合(这是3.1版本—对于非常相似的2.6版本,请参阅here)提供了几个有用的Abc。
为了这个答案的目的,保留关于Abc的关键事情(除了可以说更自然的放置TM DP功能,与UserDict等mixin类的经典Python替代方案相比。DictMixin)是他们使isinstance
(和issubclass
)比以前(在2.5及之前)更具吸引力和普及性(在Python2.6中),因此,相比之下,在最近的Python版本中,检查类型相等比以前更糟糕。