Python интернирует строки?

В Java явно объявленные строки интернируются JVM, поэтому последующие объявления одной и той же строки приводят к двум указателям на один и тот же экземпляр String, а не к двум отдельным (но идентичным) строкам.

Например:

public String baz() {
    String a = "astring";
    return a;
}

public String bar() {
    String b = "astring"
    return b;
}

public void main() {
    String a = baz()
    String b = bar()
    assert(a == b) // passes
}

Мой вопрос заключается в том, делает ли CPython (или любая другая среда выполнения Python) то же самое для строк? Например, если у меня есть какой-то класс:

class example():
    def __init__():
        self._inst = 'instance' 

И создайте 10 экземпляров этого класса, будет ли у каждого из них переменная экземпляра, ссылающаяся на одну и ту же строку в памяти, или я получу 10 отдельных строк?

3 ответа

Решение

Это называется интернированием, и да, Python делает это в некоторой степени для более коротких строк, создаваемых как строковые литералы. См. Об изменении идентификатора неизменяемой строки Python для некоторого обсуждения.

Стажировка зависит от времени выполнения, для него нет стандарта. Стажировка - это всегда компромисс между использованием памяти и стоимостью проверки, если вы создаете одну и ту же строку. Есть встроенная функция intern(), чтобы вызвать проблему, если вы так склонны, которая документирует, что некоторые из стажировочных Python делают для вас автоматически:

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

Обратите внимание, что Python 3 переместил intern() функция к sys модуль.

Довольно простой способ узнать это с помощью id(), Однако, как упоминает @MartijnPieters, это зависит от времени выполнения.

class example():

    def __init__(self):
        self._inst = 'instance'

for i in xrange(10):
    print id(example()._inst)

Некоторые строки интернированы в python. По мере компиляции кода Python интернируются идентификаторы, например, имена переменных, имена функций, имена классов.

Строки, соответствующие правилам идентификаторов, которые начинаются с подчеркивания или строки и содержат только подчеркивание, строку и число, интернируются:

a="hello"
b="hello"

Поскольку строки неизменяемы, python разделяет здесь ссылки на память и

a is b ===> True

Но если бы у нас было

a="hello world"
b="hello world"

поскольку "hello world" не соответствует правилам идентификаторов, a и b не интернируются.

a is b  ===> False

Вы можете интернировать тех, у кого sys.intern(). используйте этот метод, если в вашем коде много повторений строк.

a=sys.intern("hello world")
b=sys.intern("hello world")

теперь a равно b ===> True

  • Все строки длины 0 и длины 1 интернированы.
  • Строки интернируются во время компиляции ('wtf' будет интернирован, но ''.join(['w', 't', 'f'] не интернируется)
  • Строки, которые не состоят из букв ASCII, цифр или подчеркиваний, не интернируются. Это объясняет, почему "WTF!" не был интернирован из-за!

https://www.codementor.io/satwikkansal/do-you-really-think-you-know-strings-in-python-fnxh8mtha

Выше статья объясняет интернирование строк в Python. Есть некоторые исключения, которые четко определены в статье.

Другие вопросы по тегам