web-dev-qa-db-ja.com

'is'キーワードはPythonでどのように実装されていますか?

...文字列の等価性に使用できる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
>>>
_
59
Srikanth

isを使用した文字列のテストは、文字列がインターンされている場合にのみ機能します。あなたが何をしているのか本当に明確にわかっていない限り、そして明示的に interned すべき文字列neverは文字列にisを使用します。

isは、identityではなく、identityをテストします。つまり、Pythonはオブジェクトが存在するメモリアドレスを単に比較します。isは基本的に「同じオブジェクトに2つの名前がありますか?」センス。

例えば、 ("a" * 100) is ("a" * 100)Falseです。通常、Pythonは各文字列を異なるメモリ位置に書き込みます。ほとんどの場合、文字列リテラルではインターンが発生します。

123
Jochen Ritzel

is演算子は、id(x)値の比較と同等です。 idは現在、比較としてポインターを使用するために実装されています。したがって、is自体をオーバーロードすることはできません。また、idをオーバーロードすることもできません。

だから、できません。 Pythonでは珍しいですが、そこにあります。

20
Phil H

Python isキーワードはオブジェクトの同一性をテストします。文字列の同等性をテストするために使用しないでください。Pythonつまり、文字列リテラルと値は内部的にハッシュリストに保持され、同一のものは同じオブジェクトへの参照としてレンダリングされます(これは、 Python文字列は不変です)。

ただし、実装の詳細と同様に、これに依存しないでください。等しいかどうかをテストする場合は、==演算子を使用します。オブジェクトIDを本当にテストしたい場合は、isを使用してください---そして、文字列オブジェクトIDを気にする必要があるケースを思い付くのは難しいでしょう。残念ながら、前述のインターンのために、2つの文字列が何らかの形で「意図的に」同一のオブジェクト参照であるかどうかを当てにすることはできません。

16
Jim Dennis

isキーワードは、オブジェクトを比較します(または、2つの参照が同じオブジェクトに対するものである場合に比較します)。

これが、独自の実装を提供するメカニズムがない理由です。

Pythonは文字列を '巧妙に'格納するため、2つの同一の文字列を作成すると1つのオブジェクトに格納されるため、文字列で動作することがあります。

>>> 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
8
pycruft

バイトコードの混乱を恐れない場合は、COMPARE_OPをインターセプトし、8 ("is")引数でパッチを適用して、比較対象のオブジェクトでフック関数を呼び出すことができます。開始についてはdisモジュールのドキュメントをご覧ください。

また、誰かがa is bの代わりに__builtin__.id()を実行する場合は、id(a) == id(b)を傍受することも忘れないでください。

5
toriningen

文字列が「-」で始まる場合、文字列変数と文字列値および2つの文字列変数との比較に失敗します。 My Pythonバージョンは2.6.6

>>> s = '-hi'
>>> s is '-hi'
False 
>>> s = '-hi'
>>> k = '-hi'
>>> s is k 
False
>>> '-hi' is '-hi'
True
2
Hughe

'is'はオブジェクトIDを比較しますが、==は値を比較します。

例:

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
2
Karthik C

is演算子をオーバーロードすることはできません。オーバーロードしたいのは==演算子。これは、__eq__クラスのメソッド。

1
iform

アイデンティティ比較を使用しています。 ==はおそらくあなたが望むものです。例外は、あるアイテムと別のアイテムが同じオブジェクトであり、同じメモリ位置にあるかどうかを確認する場合です。あなたの例では、アイテムのタイプは同じではありません。1つは他のタイプ(文字列)とは異なるタイプ(my_string)であるためです。また、someclass .__is__ in python(もちろん、自分でそこに置いていない限り)。もしあれば、オブジェクトをisは、メモリの場所を単純に比較するだけでは信頼できません。

最初にisキーワードに遭遇したとき、それも私を混乱させました。 isと==に違いはないと思っていたでしょう。彼らは多くのオブジェクトでインタプリタから同じ出力を生成しました。このタイプの仮定は、実際にはis...の目的です。それはpython同等の「ねえ、これら2つのオブジェクトを間違えないでください。違います。」」です。これは基本的に[私をまっすぐにした人]が言ったことです。しかし、1つのポイント==もう1つのポイント。

いくつかの役に立つ例と時々混乱を招く違いを助けるためのテキストについては、 python.orgのメールホストからのドキュメント "Danny Yoo"によって書かれました。

または、オフラインの場合は、 リストにないペーストビン を使用します。

それらが約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
###
1
Twisted Code

アサーションエラーは、オブジェクトの比較中にisキーワードを使用すると簡単に発生する可能性があります。たとえば、オブジェクトaおよびbは同じ値を保持し、同じメモリアドレスを共有します。したがって、

>>> a == b

評価するつもりです

True

しかし、もし

>>> a is b

に評価する

False

おそらく確認する必要があります

>>> type(a)

そして

>>> type(b)

これらは異なる場合があり、失敗の理由です。

0
unixia