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

В python 3.5 можно ли предсказать, когда мы получим интернированную строку или когда мы получим копию? Прочитав несколько ответов о переполнении стека по этому вопросу, я обнаружил, что -sometimes-produce/1504848#1504848">этот самый полезный, но все же не исчерпывающий. Затем я просмотрел документы Python, но интернирование не гарантируется. по умолчанию

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

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

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


person Community    schedule 04.03.2016    source источник
comment
Просто используйте == и забудьте об этом. В любом случае это детали реализации.   -  person wim    schedule 04.03.2016
comment
@erip Я думаю, что ОП знает об этом. После прохождения шаблона этот вопрос, кажется, касается правил интернирования.   -  person timgeb    schedule 04.03.2016
comment
Если вы действительно хотите узнать о различиях в реализации, вероятно, имеет смысл указать версии Python, установленные в обеих системах.   -  person Lev Levitsky    schedule 04.03.2016
comment
@wim Я не хочу забывать, я хочу учиться и понимать.   -  person    schedule 04.03.2016
comment
@LevLevitsky Спасибо за редактирование вопроса, чтобы он был более актуальным.   -  person    schedule 05.03.2016
comment
Тогда не могли бы вы прояснить свой вопрос и удалить всю не относящуюся к делу преамбулу о ==? Ваш вопрос, когда строка будет интернирована в cpython? Обратите внимание, что это больше не вопрос о python, потому что язык python может даже не иметь интернирования строк.   -  person wim    schedule 05.03.2016
comment
@wim Я бы с удовольствием, но мой опыт работы с Python не очень высок, поэтому вы можете отредактировать вопрос самостоятельно, как вы его видите.   -  person    schedule 05.03.2016
comment
Хорошо, я отредактирую. Но я не уверен, что именно ваш вопрос, потому что это немного бессвязно. Вы спрашиваете, когда строка будет интернирована в cpython? примечание: вам следует добавить конкретную версию, потому что существует множество сборок python3.   -  person wim    schedule 05.03.2016
comment
@wim Да, когда строка будет интернирована в cpython   -  person    schedule 05.03.2016
comment
Единственное правило состоит в том, что возвращаемое значение intern интернировано. Все остальное — это трясина деталей реализации, непоследовательная, потому что нет смысла быть последовательной.   -  person user2357112 supports Monica    schedule 05.03.2016
comment
Я отредактировал содержание, чтобы не поощрять такие бесполезные ответы, которые привлекал этот вопрос (те, которые не говорят вам ничего, чего вы еще не знаете). Если вы не думаете, что это улучшение, не стесняйтесь откатывать.   -  person wim    schedule 05.03.2016
comment
@wim Спасибо за рефакторинг, я ценю вашу помощь   -  person    schedule 05.03.2016


Ответы (2)


Думаете, существуют правила?

Единственное правило интернирования состоит в том, что возвращаемое значение 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 или нет. Этот код может быть изменен, и есть много другого кода, который выполняет интернирование или что-то подобное интернированию.

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

person user2357112 supports Monica    schedule 04.03.2016

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

Когда вы используете 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 *. Я думаю, что это то, что происходит здесь.

person Rolbrok    schedule 04.03.2016