What are the differences between type() and isinstance()? [duplicate] Ask Question

What are the differences between type() and isinstance()? [duplicate] Ask Question

What are the differences between these two code snippets?

Using type:

import types

if type(a) is types.DictType:
    do_something()
if type(b) in types.StringTypes:
    do_something_else()

Using isinstance:

if isinstance(a, dict):
    do_something()
if isinstance(b, str) or isinstance(b, unicode):
    do_something_else()

ベストアンサー1

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

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.

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

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.

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)。しかし、最近の Python バージョンで実装された ABC には、追加の機能があります。isinstance(およびissubclass) は、単なる「派生クラスのインスタンス」以上の意味を持つようになりました (特に、任意のクラスを ABC に「登録」して、サブクラスとして表示し、そのインスタンスを ABC のインスタンスとして表示することができます)。また、ABC は、テンプレート メソッド設計パターンの適用を通じて、実際のサブクラスに非常に自然な方法で追加の利便性を提供することもできます (ここそしてここ[[パート II]] では、ABC とは関係なく、一般的な TM DP と Python 特有の TM DP について詳しく説明します。

Python 2.6で提供されるABCサポートの基本的な仕組みについては、以下を参照してください。ここ; 3.1バージョンについては、非常に似ています。ここどちらのバージョンでも、標準ライブラリモジュールコレクション(これは3.1バージョンです。非常によく似た2.6バージョンについては、ここ) はいくつかの便利な ABC を提供します。

この回答の目的のために、ABCについて覚えておくべき重要なことは(TM DP機能の配置がPythonの古典的な代替手段であるmixinクラスに比べてより自然であるということ以外に)ユーザー辞書.辞書ミックスインisinstance) の最大の問題は、(および) が (Python 2.6 以降では) 以前 (2.5 以前) よりもはるかに魅力的かつ普及していることですissubclass。そのため、対照的に、型の等価性をチェックすることは、最近の Python バージョンでは以前よりもさらに悪い習慣になっています。

おすすめ記事