10

インタラクティブなPythonセッションでのみ発生するこの奇妙な動作に遭遇しましたが、スクリプトを記述して実行したときは発生しませんでした。

文字列はPythonでは不変のデータ型であるため、次のようになります。

>>> s2='string'
>>> s1='string'
>>> s1 is s2
True

さて、奇妙な部分:

>>> s1='a string'
>>> s2='a string'
>>> s1 is s2
False

文字列に空白があると、この動作が発生することを確認しました。これをスクリプトに入れて実行すると、どちらの場合も結果はTrueになります。

誰かがこれについての手がかりを持っていますか?ありがとう。

編集:

さて、上記の質問と回答はいくつかのアイデアを与えます。ここに別の実験があります:

>>> s2='astringbstring'
>>> s1='astringbstring'
>>> s1 is s2
True

この場合、文字列は間違いなくより長くなりますが'a string'、それでも同じ識別子を持っています。

4

1 に答える 1

6

訂正してくれた@eryksunに感謝します!

これはinterning、Pythonのメカニズム呼び出しが原因です。

「インターンされた」文字列のテーブルに文字列を入力し、インターンされた文字列を返します。これは文字列自体またはコピーです。文字列のインターンは、ディクショナリルックアップのパフォーマンスを少し向上させるのに役立ちます。ディクショナリ内のキーがインターンされ、ルックアップキーがインターンされている場合、キー比較(ハッシュ後)は、文字列比較の代わりにポインタ比較によって実行できます。通常、Pythonプログラムで使用される名前は自動的にインターンされ、モジュール、クラス、またはインスタンスの属性を保持するために使用されるディクショナリにはインターンされたキーがあります。

バージョン2.3で変更:インターンされた文字列は不滅ではありません(Python 2.2以前のように)。恩恵を受けるには、intern()の戻り値への参照を保持する必要があります。

CPythonは、特定の文字列(1文字の文字列、キーワード、スペースが割り当てられていない文字列)を自動的にインターンして、検索速度と比較速度を向上させます'dog' is 'dog'。たとえば、完全な文字列比較ではなく、ポインター比較になります。ただし、すべての(より長い)文字列の自動インターンには、常に実行可能とは限らないより多くのメモリが必要であるため、同じIDを共有しない場合があり、結果がid()異なります。たとえば、次のようになります。

# different id when not assigned
In [146]: id('dog')
Out[146]: 4380547672

In [147]: id('dog')
Out[147]: 4380547552

# if assigned, the strings will be interned (though depends on implementation)
In [148]: a = 'dog'

In [149]: b = 'dog'

In [150]: id(a)
Out[150]: 4380547352

In [151]: id(b)
Out[151]: 4380547352

In [152]: a is b
Out[152]: True

整数の場合、少なくとも私のマシンでは、CPythonは自動的に最大256を自動的にインターンします。

In [18]: id(256)
Out[18]: 140511109257408

In [19]: id(256)
Out[19]: 140511109257408

In [20]: id(257)
Out[20]: 140511112156576

In [21]: id(257)
Out[21]: 140511110188504

@eryksunのおかげで更新:この場合、CPythonはスペースのない文字列のみをインターンする'a string'ため、文字列はインターンされません。たとえば、ASCII文字、数字、アンダースコアなど、私が即座に想定した長さのためではありません。

詳細については、こちらのAlexMartelliの回答を参照することもできます。

于 2013-03-03T03:54:54.007 に答える