type() 和 isinstance() 有什么区别? [英] What are the differences between type() and isinstance()?

查看:41
本文介绍了type() 和 isinstance() 有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这两个代码片段有什么区别?

What are the differences between these two code fragments?

使用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 的相等性则不是(它要求类型的标识并拒绝子类型的实例,AKA 子类).

To summarize the contents of other (already good!) answers, isinstance caters for inheritance (an instance of a derived class is an instance of a base class, too), while checking for equality of type does not (it demands identity of types and rejects instances of subtypes, AKA subclasses).

通常,在 Python 中,您当然希望您的代码支持继承(因​​为继承是如此方便,阻止使用您的代码使用它会很糟糕!),所以 isinstance 是比检查 type 的身份要好,因为它无缝支持继承.

Normally, in Python, you want your code to support inheritance, of course (since inheritance is so handy, it would be bad to stop code using yours from using it!), so isinstance is less bad than checking identity of types because it seamlessly supports inheritance.

并不是说isinstance,请注意——它只是比检查类型相等性要好.正常的、Pythonic 的首选解决方案几乎总是鸭子类型":尝试使用参数就好像它是某种所需的类型,在 try/except 语句捕获所有可能出现的异常,如果参数实际上不是该类型(或任何其他类型很好地模仿它;-),并且在 except 子句中, 尝试别的东西(使用好像"它是其他类型的参数).

It's not that isinstance is good, mind you—it's just less bad than checking equality of types. The normal, Pythonic, preferred solution is almost invariably "duck typing": try using the argument as if it was of a certain desired type, do it in a try/except statement catching all exceptions that could arise if the argument was not in fact of that type (or any other type nicely duck-mimicking it;-), and in the except clause, try something else (using the argument "as if" it was of some other type).

basestring is,然而,这是一个非常特殊的情况——一种内置类型,它存在,让您可以使用isinstance(strunicode 子类 basestring).字符串是序列(您可以遍历它们、索引它们、切片它们,...),但您通常希望将它们视为标量"类型——处理各种字符串(也可能是其他标量类型,即不能循环的类型)一种方式,所有容器(列表、集合、字典等)以另一种方式,以及 basestringisinstance 可以帮助你做到这一点——这个习语的整体结构类似于:

basestring is, however, quite a special case—a builtin type that exists only to let you use isinstance (both str and unicode subclass basestring). Strings are sequences (you could loop over them, index them, slice them, ...), but you generally want to treat them as "scalar" types—it's somewhat incovenient (but a reasonably frequent use case) to treat all kinds of strings (and maybe other scalar types, i.e., ones you can't loop on) one way, all containers (lists, sets, dicts, ...) in another way, and basestring plus isinstance helps you do that—the overall structure of this idiom is something like:

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 开始实现.

You could say that basestring is an Abstract Base Class ("ABC")—it offers no concrete functionality to subclasses, but rather exists as a "marker", mainly for use with isinstance. The concept is obviously a growing one in Python, since PEP 3119, which introduces a generalization of it, was accepted and has been implemented starting with Python 2.6 and 3.0.

PEP 明确指出,虽然 ABCs 通常可以替代鸭子打字,但通常没有太大的压力来做到这一点(参见 此处).然而,在最近的 Python 版本中实现的 ABC 确实提供了额外的好处:isinstance(和 issubclass)现在可以意味着不仅仅是[一个] 派生类的实例"(在特别是,任何类都可以在 ABC 中注册",以便它显示为子类,并且其实例显示为 ABC 的实例);并且 ABC 还可以通过模板方法设计模式应用以一种非常自然的方式为实际的子类提供额外的便利(参见 此处此处 [[部分II]] 有关 TM DP 的更多信息,一般而言,特别是在 Python 中,独立于 ABC).

The PEP makes it clear that, while ABCs can often substitute for duck typing, there is generally no big pressure to do that (see here). ABCs as implemented in recent Python versions do however offer extra goodies: isinstance (and issubclass) can now mean more than just "[an instance of] a derived class" (in particular, any class can be "registered" with an ABC so that it will show as a subclass, and its instances as instances of the ABC); and ABCs can also offer extra convenience to actual subclasses in a very natural way via Template Method design pattern applications (see here and here [[part II]] for more on the TM DP, in general and specifically in Python, independent of ABCs).

有关 Python 2.6 中提供的 ABC 支持的底层机制,请参阅此处;对于它们的 3.1 版本,非常相似,请参见此处.在这两个版本中,标准库模块 collections(即 3.1 版本— 对于非常相似的 2.6 版本,请参见 此处) 提供了几个有用的 ABC.

For the underlying mechanics of ABC support as offered in Python 2.6, see here; for their 3.1 version, very similar, see here. In both versions, standard library module collections (that's the 3.1 version—for the very similar 2.6 version, see here) offers several useful ABCs.

就这个答案而言,保留 ABCs 的关键是(除了可以说是 TM DP 功能的更自然的位置,与混合类的经典 Python 替代品(例如 UserDict.DictMixin) 是他们制作 isinstance(和 issubclass) 比过去(在 2.5 及之前)更具吸引力和普遍性(在 Python 2.6 及以后的版本中),因此,相比之下,在最近的 Python 版本中,检查类型相等性是一种更糟糕的做法.它曾经是.

For the purpose of this answer, the key thing to retain about ABCs (beyond an arguably more natural placement for TM DP functionality, compared to the classic Python alternative of mixin classes such as UserDict.DictMixin) is that they make isinstance (and issubclass) much more attractive and pervasive (in Python 2.6 and going forward) than they used to be (in 2.5 and before), and therefore, by contrast, make checking type equality an even worse practice in recent Python versions than it already used to be.

这篇关于type() 和 isinstance() 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆