10

一部の不変クラスでは、 が既存のインスタンスを返す場合があることを知り__new__ましintた。strtuple

しかし、次の 2 つのスニペットの動作が異なるのはなぜでしょうか?

末尾にスペースがある場合:

>>> a = 'string '
>>> b = 'string '
>>> a is b
False

スペースなし:

>>> c = 'string'
>>> d = 'string'
>>> c is d
True

スペースが違いをもたらすのはなぜですか?

4

2 に答える 2

16

これは、CPython 実装が文字列リテラルをキャッシュする方法の癖です。同じ内容の文字列リテラルは、同じ文字列オブジェクトを参照できますが、そうである必要はありません。Python 識別子で許可されている文字のみが含まれているため、そうでない'string'場合は自動的にインターンされます。それが彼らが選んだ基準である理由はわかりませんが、そうです。Python のバージョンや実装が異なると、動作が異なる場合があります。'string ''string'

CPython 2.7 ソース コードのstringobject.h28 行目:

文字列のインターン (ob_sstate) は、指定された値を持つ文字列オブジェクトが 1 つだけ存在することを確認しようとするため、等価テストは 1 つのポインター比較になります。これは通常、Python 識別子に「似ている」文字列に制限されていますが、組み込みの intern() を使用して任意の文字列のインターンを強制できます。

これを行うコードは次のObjects/codeobject.cとおりです。

/* Intern selected string constants */
for (i = PyTuple_Size(consts); --i >= 0; ) {
    PyObject *v = PyTuple_GetItem(consts, i);
    if (!PyString_Check(v))
        continue;
    if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
        continue;
    PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
}

また、インターンは、Python バイトコード コンパイラによる文字列リテラルのマージとは別のプロセスであることに注意してください。aコンパイラにとのb割り当てを一緒にコンパイルさせると (たとえば、モジュールまたは に配置することによって) 、 と が同じ文字列になることがif True:わかります。ab

于 2014-01-18T11:13:06.143 に答える
5

この動作は一貫しておらず、他の人が言及しているように、実行されている Python のバリアントに依存します。より深い議論については、この質問を参照してください。

同じオブジェクトが使用されていることを確認したい場合は、適切な名前の によって文字列のインターンを強制できinternます。

インターン(...) インターン(文字列) -> 文字列

``Intern'' the given string.  This enters the string in the (global)
table of interned strings whose purpose is to speed up dictionary lookups.
Return the string itself or the previously interned string object with the
same value.
>>> a = 'string '
>>> b = 'string '
>>> id(a) == id(b)
False
>>> a = intern('string ')
>>> b = intern('string ')
>>> id(a) == id(b)
True

Python3 では、 intern を明示的にインポートする必要があることに注意してくださいfrom sys import intern

于 2014-01-18T11:20:07.643 に答える