7

演算子は2つのオブジェクトのisメモリアドレスを比較し、Trueそれらが同じである場合は戻ります。では、なぜ文字列では確実に機能しないのでしょうか。 コード#1

>>> a = "poi"
>>> b = "poi"
>>> a is b
True

コード#2

>>> ktr = "today is a fine day"
>>> ptr = "today is a fine day"
>>> ktr is ptr
False

内容は同じですが、異なるメモリアドレスに存在する2つの文字列を作成しました。is演算子の出力に一貫性がないのはなぜですか?

4

4 に答える 4

6

文字列のインターンと関係があると思います。本質的には、一部の操作のパフォーマンスを向上させるために、個別の文字列のコピーを1つだけ保存するという考え方です。

基本的に、機能する理由a is bは、(ご想像のとおり)どちらの場合もPythonによって参照される不変の文字列が1つあるためです。文字列が大きい場合(およびおそらく私が理解していない他のいくつかの要因)、これは実行されません。そのため、2番目の例ではFalseが返されます。

編集:そして実際、奇妙な振る舞いはインタラクティブな環境の副作用のようです。同じコードをPythonスクリプトに配置すると、両方ともTruea is bを返します。ktr is ptr

a="poi"
b="poi"
print a is b  # Prints 'True'

ktr = "today is a fine day"
ptr = "today is a fine day"
print ktr is ptr  # Prints 'True'

Pythonがソースファイルを解析し、その中の重複する文字列リテラルを探すのは簡単なので、これは理にかなっています。文字列を動的に作成すると、スクリプト内でも動作が異なります。

a="p" + "oi"
b="po" + "i"
print a is b  # Oddly enough, prints 'True'

ktr = "today is" + " a fine day"
ptr = "today is a f" + "ine day"
print ktr is ptr  # Prints 'False'

それでもTrueになる理由についてa is bは、割り当てられた文字列が、インターンされたコレクションをすばやく検索できるほど小さいのに、もう1つはそうではないのではないでしょうか。

于 2012-10-25T05:38:23.900 に答える
3

isアイデンティティテストです。小さい一部の文字列(キャッシュのため)では機能しますが、大きい他の文字列では機能しません。strはptrではないので。[ありがとうエリクソン]

このコードを参照してください:

>>> import dis
>>> def fun():
...   str = 'today is a fine day'
...   ptr = 'today is a fine day'
...   return (str is ptr)
...
>>> dis.dis(fun)
  2           0 LOAD_CONST               1 ('today is a fine day')
              3 STORE_FAST               0 (str)

  3           6 LOAD_CONST               1 ('today is a fine day')
              9 STORE_FAST               1 (ptr)

  4          12 LOAD_FAST                0 (str)
             15 LOAD_FAST                1 (ptr)
             18 COMPARE_OP               8 (is)
             21 RETURN_VALUE

>>> id(str)
26652288
>>> id(ptr)
27604736
#hence this comparison returns false: ptr is str

strとのIDptrが異なることに注意してください。

しかし:

>>> x = "poi"
>>> y = "poi"
>>> id(x)
26650592
>>> id(y)
26650592
#hence this comparison returns true : x is y

xとyのIDは同じです。したがってis、演算子は「等式」ではなく「ID」で動作します

Pythonが同一の文字列に異なるメモリ位置を割り当てる時期と理由については、以下のリンクを参照してください(質問も読んでください)。

Pythonはいつ同じ文字列に新しいメモリを割り当てますか

またsys.intern、python3.xとinternpython2.xでは、文字列のサイズに関係なく、同じメモリ位置に文字列を割り当てるのに役立ちます。

于 2012-10-25T05:33:17.853 に答える
2

isと同じではありません==

基本的にis、2つのオブジェクトが同じであるかどうかを確認し、==それらのオブジェクトの値を比較します(Pythonのすべての文字列と同様に、文字列はオブジェクトです)。

したがって、is見ているオブジェクトが本当にわかっている場合(つまり、オブジェクトを作成した場合、またはNone質問のコメントが指摘しているように比較している場合)、2つの変数がまったく同じものを参照しているかどうかを知りたい場合に使用する必要があります。メモリ内のオブジェクト。

ただし、あなたの例では、strPythonが舞台裏で処理しているオブジェクトを見ているので、Pythonがどのように機能するかを深く掘り下げないと、何を期待できるかわかりません。intsまたはsでも同じ問題が発生しfloatます。他の答えは「舞台裏」のもの(文字列インターン)を説明するのに良い仕事をしますが、日常のプログラミングではほとんどそれについて心配する必要はありません。

于 2012-10-25T05:34:36.313 に答える
1

これはCPython固有の最適化であることに注意してください。コードを移植可能にしたい場合は、それを避ける必要があります。たとえば、PyPyでは

>>>> a = "hi"
>>>> b = "hi"
>>>> a is b
False

同様のことが小さな整数でも起こることも指摘する価値があります

>>> a = 12
>>> b = 12
>>> a is b
True

他の実装にはこの最適化が含まれていない可能性があるため、これも信頼すべきではありません。

于 2012-10-25T06:26:01.063 に答える