Каковы правила для интернирования строк cpython?

В python 3.5 можно предсказать, когда мы получим интернированную строку или когда мы получим копию? После прочтения нескольких ответов по этой проблеме я нашел этот наиболее полезным, но все же не полным. Затем я просмотрел Документы Python, но интернирование не гарантируется по умолчанию

Обычно имена, используемые в программах Python, автоматически интернированы, а словари, используемые для хранения атрибутов модуля, класса или экземпляра, имеют интернированные ключи.

Итак, мой вопрос касается внутренних условий intern(), то есть принятия решений (будь то статический строковый литерал или нет): почему одна и та же часть кода работает в одной системе, а не на другом, и какие правила автор ответ на указанная тема означает, что

правила для того, когда это происходит, довольно запутаны

Ответ 1

Вы думаете, что есть правила?

Единственным правилом для интернирования является то, что возвращаемое значение intern интернировано. Все остальное зависит от капризов того, кто решил, что какой-то фрагмент кода должен или не должен делать интернирование. Например, "left" получает интернированный PyCodeNew:

/* Intern selected string constants */
for (i = PyTuple_GET_SIZE(consts); --i >= 0; ) {
    PyObject *v = PyTuple_GetItem(consts, i);
    if (!all_name_chars(v))
        continue;
    PyUnicode_InternInPlace(&PyTuple_GET_ITEM(consts, i));
}

"Правило" здесь состоит в том, что строковый объект в co_consts объекта кода Python получает интернированный, если он состоит исключительно из символов ASCII, которые являются законными в идентификаторе Python. "left" получает интернированный, но "as,df" не будет, а "1234" будет интернирован, даже если идентификатор не может начинаться с цифры. Хотя идентификаторы могут содержать символы, отличные от ASCII, эти символы по-прежнему отклоняются этой проверкой. Фактические идентификаторы никогда не проходят через этот код; они получают безоговорочно интернированные несколько строк, ASCII или нет. Этот код может быть изменен, и есть много других кодов, которые делают интернированные или интернирующие вещи.

Просить нас о "правилах" для интернирования строк, как просить метеоролога о том, что такое правила, идет ли дождь на вашей свадьбе. Мы можем рассказать вам довольно много о том, как это работает, но вам это не будет очень полезно, и вы всегда будете получать сюрпризы.

Ответ 2

Из того, что я понял из сообщения, которое вы связали:

Когда вы используете if a == b, вы проверяете, является ли значение a значением b, тогда как при использовании if a is b вы проверяете, являются ли теги a и b одинаковыми объект (или совместно использовать одно и то же место в памяти).

Теперь python ставит постоянные строки (определенные "blabla" ). Итак:

>>> a = "abcdef"
>>> a is "abcdef"
True

Но когда вы делаете:

>>> a = "".join([chr(i) for i in range(ord('a'), ord('g'))])
>>> a
'abcdef'
>>> a is "abcdef"
False

В языке программирования C использование строки с "" сделает ее const char *. Я думаю, что это то, что здесь происходит.