回答:
他の(すでに良い!)回答の内容を要約するisinstance
と、継承に対応します(派生クラスのインスタンスも基本クラスのインスタンスです)が等しいかtype
どうかを確認します(型の同一性を要求し、インスタンスを拒否します)サブタイプ、別名サブクラス)。
通常は、Pythonで、あなたはサポートの継承にあなたのコードをしたい、(継承は非常に便利であることから、それを使用してからあなたを使用してコードを停止するために悪いだろう!)もちろん、そうisinstance
の身元チェックするよりも少ない悪いですtype
、それシームレスにサポートしているので、sが継承。
それisinstance
は良いことではありません、心に留めておいてください。型の等価性をチェックするよりも悪いことではありません。通常のPythonicで推奨される解決策は、ほぼ常に「ダックタイピング」です。ある種の望ましい型であるかのように引数を使用してみてください。引数が実際にそうでなかった場合に発生する可能性のあるすべての例外をキャッチするtry
/ except
ステートメントでそれを実行してくださいタイプ(または他の任意のタイプをうまくダックで模倣する;-)、そしてexcept
句で他のことを試してください(引数を「あたかも」他のタイプのように使用して)。
basestring
ある、しかし、存在は非常に特殊なケース組み込みタイプのみ使用できるようにisinstance
(両方str
とunicode
サブクラスをbasestring
)。文字列はシーケンスです(ループし、インデックスを付け、スライスすることもできます...)が、通常は「スカラー」型として扱いたいと思います。文字列(そしておそらく他のスカラー型、つまりループできないもの)を1つの方法で、すべてのコンテナー(リスト、セット、ディクショナリなど)を別の方法で、そして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から実装されて以来、Pythonで明らかに成長しています。
PEPは、ABCがダックタイピングの代わりになることがよくある一方で、一般的にそれを行うための大きなプレッシャーはないことを明らかにしています(ここを参照)。ただし、最近のPythonバージョンに実装されたABCは、さらに優れた機能を提供します。isinstance
(およびissubclass
)は、「[派生クラス]のインスタンス」以上のものを意味するようになりました(特に、任意のクラスをABCに「登録」して、サブクラスとして表示し、そのインスタンスをABCのインスタンスとして表示します); ABCは、テンプレートメソッドのデザインパターンアプリケーションを介して、実際のサブクラスに非常に自然な方法で追加の利便性を提供することもできます(ABCとは関係なく、一般的に、具体的にはPythonでのTM DPの詳細については、こことここ [[パートII]]を参照してください)。 。
Python 2.6で提供されるABCサポートの基本的な仕組みについては、こちらを参照してください。非常によく似た3.1バージョンについては、こちらを参照してください。どちらのバージョンでも、標準ライブラリモジュールコレクション(3.1バージョンです。非常に類似した2.6バージョンについては、こちらを参照してください)は、いくつかの便利なABCを提供します。
この回答の目的のために、ABCについて保持する重要な点は(UserDict.DictMixinなどのミックスインクラスの従来のPythonの代替と比較して、TM DP機能の間違いなくより自然な配置を超えて)、それらがisinstance
(およびissubclass
)はるかに多くなることです(Python 2.6以降では)以前よりも魅力的で普及しているため(2.5以前)、そのため、対照的に、最近のPythonバージョンでは、型の等価性のチェックを、以前よりもさらに悪い方法にしています。
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でオブジェクトのタイプを比較する方法?
type
使用し、推奨されませんisinstance
一見代わりに」。たとえば、私が欲しかったのは正確にtype()
チェックすることでしたが、そのため、しばらくの間、誤解されました(そして少しデバッグする必要がありました)。
type()
としないケースに出くわしましたisinstance()
。1つは良くありません。彼らは別のものです。
isinstance()
とtype()
Pythonの違いは?
による型チェック
isinstance(obj, Base)
サブクラスのインスタンスと複数の可能なベースを許可します:
isinstance(obj, (Base1, Base2))
一方、型チェック
type(obj) is Base
参照されるタイプのみをサポートします。
補足として、is
おそらくより適切です
type(obj) == Base
クラスはシングルトンだからです。
Pythonでは、通常、引数に任意の型を許可し、それを期待どおりに処理します。オブジェクトが期待どおりに動作しない場合は、適切なエラーが発生します。これは多型として知られており、アヒルのタイピングとしても知られています。
def function_of_duck(duck):
duck.quack()
duck.swim()
上記のコードが機能する場合、引数はアヒルであると推定できます。したがって、アヒルの実際のサブタイプである他のものを渡すことができます:
function_of_duck(mallard)
またはそれはアヒルのように機能します:
function_of_duck(object_that_quacks_and_swims_like_a_duck)
私たちのコードはまだ機能します。
ただし、明示的に型チェックを行うことが望ましい場合があります。おそらく、さまざまな種類のオブジェクトを扱うために賢明なことがあるでしょう。たとえば、Pandas Dataframeオブジェクトは、辞書またはレコードから構築できます。このような場合、コードは、適切に処理できるように、取得する引数のタイプを知る必要があります。
したがって、質問に答えるには:
isinstance()
とtype()
Pythonの違いは?違いを示すことができます:
type
関数が特定の種類の引数(コンストラクターの一般的な使用例)を受け取った場合、特定の動作を保証する必要があるとしましょう。次のようなタイプをチェックすると:
def foo(data):
'''accepts a dict to construct something, string support in future'''
if type(data) is not dict:
# we're only going to test for dicts for now
raise ValueError('only dicts are supported for now')
サブクラスであるdictを渡そうとするとdict
(可能な限り、コードがLiskov Substitutionの原則に従うことを期待している場合は、そのサブタイプをタイプに置き換えることができます)、コードが壊れます!:
from collections import OrderedDict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
エラーが発生します!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
ValueError: argument must be a dict
isinstance
しかし、を使用するとisinstance
、Liskov Substitutionをサポートできます!:
def foo(a_dict):
if not isinstance(a_dict, dict):
raise ValueError('argument must be a dict')
return a_dict
foo(OrderedDict([('foo', 'bar'), ('fizz', 'buzz')]))
戻り値 OrderedDict([('foo', 'bar'), ('fizz', 'buzz')])
実際に、私たちはさらに良いことができます。collections
は、さまざまなタイプに最小限のプロトコルを適用する抽象基本クラスを提供します。私たちのケースでは、Mapping
プロトコルのみを期待している場合、次のことができ、コードはさらに柔軟になります。
from collections import Mapping
def foo(a_dict):
if not isinstance(a_dict, Mapping):
raise ValueError('argument must be a dict')
return a_dict
タイプを使用して複数のクラスをチェックすることができることに注意してください
type(obj) in (A, B, C)
はい、型の等価性をテストできますが、これらの型のみを明確に許可しない限り、上記の代わりに、制御フローに複数のベースを使用します。
isinstance(obj, (A, B, C))
違いは、やはり、isinstance
Liskov置換と呼ばれるプロパティであるプログラムを壊さずに親の代わりに使用できるサブクラスをサポートすることです。
ただし、さらに良いのは、依存関係を逆にし、特定のタイプをまったくチェックしないことです。
したがって、サブクラスの置換をサポートする必要があるため、インスタンスの正確なクラスを本当に知る必要がない限り、ほとんどの場合、型チェックを避け、型チェックをtype
優先isinstance
する必要があります。
isinstance(instance, y)
て使用するyour_module.pyがありfrom v.w.x import y
、そのチェックをインポートしたが、インスタンス化instance
するfrom x import y
と、yがyour_module.pyにインポートされた方法の代わりに使用された場合、同じクラスであっても、isinstanceチェックは失敗します。
pythonのドキュメントによると、ここにステートメントがあります:
8.15。型—組み込み型の名前
Pythonの2.2以降では、などの工場機能を内蔵
int()
し、str()
また、対応するタイプの名前です。
したがって、isinstance()
を優先する必要がありますtype()
。
実際の使用法の違いは、それらの処理方法booleans
です。
True
そしてFalse
ちょうどそれが平均キーワードである1
と0
pythonで。したがって、
isinstance(True, int)
そして
isinstance(False, int)
どちらも戻りTrue
ます。両方のブール値は整数のインスタンスです。type()
ただし、より賢いです。
type(True) == int
を返しますFalse
。
実際の違いについては、で確認できますcode
が、のデフォルトの動作の実装は見つかりませんisinstance()
。
ただし、__ instancecheck__に従って、同様のabc .__ instancecheck__を取得できます。
上からabc.__instancecheck__
、以下のテストを使用した後:
# file tree
# /test/__init__.py
# /test/aaa/__init__.py
# /test/aaa/aa.py
class b():
pass
# /test/aaa/a.py
import sys
sys.path.append('/test')
from aaa.aa import b
from aa import b as c
d = b()
print(b, c, d.__class__)
for i in [b, c, object]:
print(i, '__subclasses__', i.__subclasses__())
print(i, '__mro__', i.__mro__)
print(i, '__subclasshook__', i.__subclasshook__(d.__class__))
print(i, '__subclasshook__', i.__subclasshook__(type(d)))
print(isinstance(d, b))
print(isinstance(d, c))
<class 'aaa.aa.b'> <class 'aa.b'> <class 'aaa.aa.b'>
<class 'aaa.aa.b'> __subclasses__ []
<class 'aaa.aa.b'> __mro__ (<class 'aaa.aa.b'>, <class 'object'>)
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aaa.aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasses__ []
<class 'aa.b'> __mro__ (<class 'aa.b'>, <class 'object'>)
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'aa.b'> __subclasshook__ NotImplemented
<class 'object'> __subclasses__ [..., <class 'aaa.aa.b'>, <class 'aa.b'>]
<class 'object'> __mro__ (<class 'object'>,)
<class 'object'> __subclasshook__ NotImplemented
<class 'object'> __subclasshook__ NotImplemented
True
False
私はこの結論を得ますtype
:
# according to `abc.__instancecheck__`, they are maybe different! I have not found negative one
type(INSTANCE) ~= INSTANCE.__class__
type(CLASS) ~= CLASS.__class__
の場合isinstance
:
# guess from `abc.__instancecheck__`
return any(c in cls.__mro__ or c in cls.__subclasses__ or cls.__subclasshook__(c) for c in {INSTANCE.__class__, type(INSTANCE)})
ところでrelative and absolutely import
、使用を混合しない方が良いですabsolutely import
、project_dirから使用してください(によって追加sys.path
)
str
とunicode
(あなただけをチェックできる場所basestring
)には、複数のタイプに対してチェックするためにタプルを使用することができます。かどうかを確認するにsomething
は、int
またはをstr
使用しますisinstance(something, (int, str))
。