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. Есть некоторые исключения, которые четко определены в статье.