2012-04-04 9 views
12

なぜ() is()が真であるのに、(0,) is (0,)が偽であるのですか?Pythonの "is"文とタプル

私はそれらが同じオブジェクトであると思っていました。しかし、私は明らかに何かを欠いている。

+10

'is'は、それらがメモリ内の同じオブジェクトであることを意味します。明らかにCPythonは空のタプルのコピーを1つしか持たないが、内容を持つタプルに新しいタプルを作る。 – Dougal

+0

同じタプルのメモリ内で同じ場所を使うことができるように見えますが、不変なので見てください。しかし、おそらく理由がありません。 – rectangletangle

+0

@ RectangleTangle、同じタプルを見つけるには効率的な方法が必要です。どのようにすればよいか考えてみてください –

答えて

12

isステートメントの両側が同じメモリアドレスを共有しているかどうかをテストします。 ()はかなり頻繁に発生するように、それはそれは実際に(ちょうど0から255までの整数、空の文字列、空のリストなどなど)のPythonインタプリタによってシングルトンとして扱われ、基本的にid(a) == id(b)

>>> print id(()), id(()) 
30085168 30085168 
>>> print id((0,)), id((0,)) 
38560624 38676432 
>>> 

の省略形です。 (0,)(0,)をインタープリタと比較すると、それらは実際にはメモリ内の異なる変数です。それらが変更可能な場合は、最初のものを変更でき、2番目のものは変更されないため、同じではありません(a is not b)。

+9

空リストはシングルトンではありません。それらは変更可能ですので、あなたは**それぞれの[]を見て、新しいリストを作成したいと思っています!また、そのような一時オブジェクトに 'id'を使うことに注意してください。私のシステムで '(id([])、id([]))'をREPLに入力すると '(48511432L、48511432L)'が返されますが、それはちょうど最初のリストが 'id 'された後にゴミとして捨てられました、そして、2番目は、解放されたメモリのこの便利な空リストサイズの穴に割り当てられました。 'id'値は、オブジェクトが' id'値より長く存続することを保証しない限り、潜在的に無意味です。 – Ben

+0

@Ben、名前にリストを割り当てる(これは比較の最後になります)、その潜在的な問題は解決されますか? – rectangletangle

+0

@RectangleTangleまさに正しい。 – Ben

5

is同一性ではなく同一性のテスト。つまり、Pythonはオブジェクトが存在するメモリアドレスを単純に比較します。「同じオブジェクトに対して2つの名前がありますか?

通常、Pythonは各タプルを異なるメモリロケーションに書き込みます。
interningはほとんどの場合、文字列リテラルでのみ発生します。

3

Dougalがコメントで述べたように、isは、比較している2つのものが同じ場所にあることをテストします。数字、文字列、ブール値、空のタプルなどの場合、Pythonはデフォルトでオブジェクトを再利用します(インターン)ので、isはしばしば==と同じ動作をします。これはまた、文字列のようなより複雑なデータ型ではなく、メモリポインタを比較することによっていくらかのパフォーマンスの向上が得られることを意味します。

あなたのケースのタプル(不変であっても)やリスト、さらに空リストの[]などの場合、Pythonは別のメモリ位置に新しいオブジェクトを作成し、isは同じ動作をしませんway as as ==

2つのタプルを値で比較しようとしている場合は、==を比較するとよいでしょう。

+1

Pythonに同等の文字列と数値の複数のバージョンを作成させるのはかなり簡単です。 Pythonはそれらをインターンにすることを約束していません。メモリを節約するために選択するかもしれないので、 'is'の振る舞いはこれらのオブジェクトに対して予測できなくなります。したがって、文字列を比較するために 'is'を使用すると、プログラムの動作がこの問題に対応できないことがわかっている制御された場所でのみ使用しない限り、コードに微妙なバグを導入する危険性が高まります。一般的に不変オブジェクトは 'is'ではなく' == 'と比較されるべきです。 – Ben

+0

@Ben、 'aはbかa == bでも動作しませんか?しかし、2番目の比較は、得られたパフォーマンスを無効にする可能性があります。 – rectangletangle

+1

@RectangleTangleに依存します。 'a'が通常' b'でなければ、ほとんどの時間を無駄にしてしまいます。短いCループを保存するために複数のPythonレベルの操作を使用しても、大きな文字列をそれ自体と比較するのが一般的でない限り、大きな利益となる可能性はありません。私がテストしているものが*意味的に*等価で、テストしているものが*意味的に*同一であるときには '=='を使用します。理論的には、文字列の比較が非常に遅いプログラムで大きなボトルネックになることがわかった場合、私は戻ってこれらのいくつかを置き換えることができましたが、これは私には起こりませんでした。 – Ben

関連する問題