「is」キーワードはPythonでどのように実装されていますか?
-
24-10-2019 - |
質問
... is
文字列の平等に使用できるキーワード。
>>> s = 'str'
>>> s is 'str'
True
>>> s is 'st'
False
両方を試しました __is__()
と __eq__()
しかし、彼らはうまくいきませんでした。
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __is__(self, s):
... return self.s == s
...
>>>
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work
False
>>>
>>> class MyString:
... def __init__(self):
... self.s = 'string'
... def __eq__(self, s):
... return self.s == s
...
>>>
>>> m = MyString()
>>> m is 'ss'
False
>>> m is 'string' # <--- Expected to work, but again failed
False
>>>
解決
文字列をテストします is
文字列がインターンされている場合にのみ機能します。あなたが何をしていて明示的に何をしているのか本当にわからない限り インターン あなたがすべき文字列 一度もない 使用する is
文字列に。
is
のテスト 身元, 、 いいえ 平等. 。つまり、Pythonは、オブジェクトが存在するメモリアドレスを単純に比較することを意味します。 is
基本的に「同じオブジェクトに2つの名前がありますか?」という質問に答えます。 - それは意味がありません。
例えば、 ("a" * 100) is ("a" * 100)
は 間違い. 。通常、Pythonは各文字列を異なるメモリの位置に書き込み、インターンはほとんど文字列リテラルに対して起こります。
他のヒント
is
オペレーターは比較に相当します id(x)
値。 id
現在、比較としてポインターを使用するために実装されています。したがって、過負荷はできません is
それ自体、そしてあなたはオーバーロードすることができません id
また。
だから、あなたはできません。 Pythonでは珍しいですが、そこにあります。
Python is
キーワードテストオブジェクトのID。文字列の平等をテストするために使用しないでください。 Pythonの実装は、多くの非常に高レベルの言語の実装と同様に、文字列の「インターン」を実行するため、頻繁に機能するように思えるかもしれません。つまり、文字列リテラルと値は内部的にハッシュされたリストに保持され、同一のものは同じオブジェクトへの参照としてレンダリングされます。 (これは、Python文字列が不変であるため可能です)。
ただし、実装の詳細と同様に、これに依存してはいけません。平等をテストする場合は、==演算子を使用してください。本当にオブジェクトのアイデンティティをテストしたい場合は、使用してください is
---そして、私はあなたが文字列オブジェクトのアイデンティティを気にする必要があるケースを思いつくのに苦労します。残念ながら、前述のインターンのために、2つの文字列が何らかの形で「意図的に」同一のオブジェクト参照であるかどうかを確認することはできません。
is
キーワードはオブジェクトを比較します(または、むしろ、2つの参照が同じオブジェクトにあるかどうかを比較します)。
それは、なぜあなた自身の実装を提供するメカニズムがないのかと思います。
Pythonは文字列を「巧妙に」保存するため、弦で時々動作します。
>>> a = "string"
>>> b = "string"
>>> a is b
True
>>> c = "str"+"ing"
>>> a is c
True
簡単な「コピー」の例で、参照とデータの比較を見ることができます。
>>> a = {"a":1}
>>> b = a
>>> c = a.copy()
>>> a is b
True
>>> a is c
False
bytecodeをめちゃくちゃにすることを恐れていない場合は、傍受してパッチすることができます COMPARE_OP
と 8 ("is")
比較されるオブジェクトのフック関数を呼び出すという議論。見る dis
起動のためのモジュールドキュメント。
傍受することを忘れないでください __builtin__.id()
誰かがそうするなら id(a) == id(b)
それ以外の a is b
.
文字列変数を文字列値と2つの文字列変数を「 - 」で開始する場合、2つの文字列変数を比較できません。私のPythonバージョンは2.6.6です
>>> s = '-hi'
>>> s is '-hi'
False
>>> s = '-hi'
>>> k = '-hi'
>>> s is k
False
>>> '-hi' is '-hi'
True
'is'はオブジェクトのアイデンティティを比較しますが、==は値を比較します。
例:
a=[1,2]
b=[1,2]
#a==b returns True
#a is b returns False
p=q=[1,2]
#p==q returns True
#p is q returns True
過負荷はできません is
オペレーター。過負荷になりたいのはです ==
オペレーター。これは、aを定義することで実行できます __eq__
クラスのメソッド。
身元比較を使用しています。 == おそらくあなたが望むものです。これの例外は、1つのアイテムと別のアイテムがまったく同じオブジェクトであり、同じメモリ位置であるかどうかを確認する場合です。例では、アイテムは他のタイプ(my_string)とは異なる(文字列)とは異なるため、アイテムは同じではありません。また、SomeClassのようなものはありません。__is__
Pythonで(もちろん、自分でそこに置いていない限り)。ある場合は、オブジェクトを比較します は メモリの場所を単純に比較するために信頼できません。
私が最初に遭遇したとき は キーワード、それも私を混乱させました。私はそれを考えていただろう は そして==は違いはありませんでした。彼らは、多くのオブジェクトで通訳から同じ出力を生成しました。このタイプの仮定は、実際にはまさにそれです は...のためです。それは「ねえ、これらの2つのオブジェクトを間違えないでください。それらは異なっています。」それは本質的に(それが私をまっすぐにしてくれた誰であれ)言った。文言は大きく異なりますが、1つのポイント==もう一方の点。
いくつかの役立つ例と、時々混乱する違いを助けるためのいくつかのテキストのために訪れる python.orgのメールホストからのドキュメント 「ダニー・ユ」によって書かれた
または、それがオフラインの場合は、を使用します 非公開のパステビン 私はそれが体で作られました。
彼らが、約20程度の青い月(青い月が実際のイベントです)で、どちらもダウンしている場合、コードの例を引用します
###
>>> my_name = "danny"
>>> your_name = "ian"
>>> my_name == your_name
0 #or False
###
###
>>> my_name[1:3] == your_name[1:3]
1 #or True
###
###
>>> my_name[1:3] is your_name[1:3]
0
###
アサーションエラーは簡単に発生する可能性があります は オブジェクトを比較しながらキーワード。たとえば、オブジェクト a と b 同じ値を保持し、同じメモリアドレスを共有する場合があります。したがって、
>>> a == b
に評価します
True
しかし、場合
>>> a is b
に評価します
False
おそらくチェックする必要があります
>>> type(a)
と
>>> type(b)
これらは異なる場合があり、失敗の理由です。