Строки объединены в Python - PullRequest
10 голосов
/ 26 марта 2010

Есть ли в Python пул всех строк и есть ли они (строки) синглетоны?

Точнее, в следующем коде в памяти были созданы одна или две строки:

a = str(num)
b = str(num) 

Ответы [ 4 ]

19 голосов
/ 26 марта 2010

Строки неизменны в Python, поэтому реализация может решить, следует ли интернировать (это термин часто ассоциируется с C #, что означает, что некоторые строки хранятся в пуле) или нет.

В вашем примере вы динамически создаете строки. CPython не всегда проверяет пул, чтобы определить, есть ли уже строка - это также не имеет смысла, потому что сначала нужно зарезервировать память для создания строки, а затем сравнить ее содержимое пула (неэффективно для длинных строк).

Но для строк длины 1 CPython просматривает пул (см. "Stringobject.c"):

static PyStringObject *characters[UCHAR_MAX + 1];

...

PyObject *
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
{

...

    if (size == 1 && str != NULL &&
    (op = characters[*str & UCHAR_MAX]) != NULL)
    {
        #ifdef COUNT_ALLOCS
            one_strings++;
        #endif

        Py_INCREF(op);
        return (PyObject *)op;
    }

...

Итак:

a = str(num)
b = str(num)
print a is b # <-- this will print False in most cases (but try str(1) is str(1))

Но при использовании строк constant непосредственно в коде CPython использует тот же экземпляр строки:

a = "text"
b = "text"
print a is b # <-- this will print True
5 голосов
/ 26 марта 2010

Как правило, строки не интернированы в Python, но иногда они выглядят так:

>>> str(5) is str(5)
True
>>> str(50) is str(50)
False

Это не редкость в Python, где обычные объекты могут быть оптимизированы не так, как необычные:

>>> int(5+0) is int(5+0)
True
>>> int(50+0) is int(50+0)
True
>>> int(500+0) is int(500+0)
False

И имейте в виду, что все эти виды деталей будут различаться между реализациями Python и даже между версиями одной и той же реализации.

1 голос
/ 26 марта 2010

Строки не интернированы вообще.В вашем примере будут созданы две строки (за исключением значений от 0 до 9).Чтобы проверить это, мы можем использовать оператор is, чтобы увидеть, являются ли две строки одним и тем же объектом:

>>> str(1056) is str(1056)
False
0 голосов
/ 07 сентября 2018

константа пула в python различает малый целочисленный пул и большой целочисленный пул, а малый целочисленный пул находится в диапазоне [-5, 257); и другие целые числа в большом целочисленном пуле. В Cython if определяет связанный список для хранения этих данных, где выборка данных становится очень удобной и быстрой.

# ifndef NSMALLPOSINTS
    # define NSMALLPOSINTS 257
# endif

# ifndef NSMALLNEGINTS
    # define NSMALLNEGINTS 5
# endif

# if NSMALLPOSINTS + NSMALLNEGINTS > 0
    static PyIntObject * small_ints[NSMALLPOSINTS + NSMALLNEGINTS];
# endif

Кстати: целое число 257 может быть незнакомым; если два объекта, которые имеют одинаковые значения, находятся в одном и том же поле, их адрес может быть или не совпадать, это зависит от контекста процесса; тогда как, если они находятся в разных полях, их адреса должны быть разными

и, кстати, в соответствии с типом строки, Cython также обеспечивает постоянный пул, что длина строки должна быть одна, тогда как это может быть не тот же объект

a = str(11)
b = str(11)
print a == b      # True 
print a is b      # False

c = str("A")
d = str("A")   
print c == d    # True
print c is d    # True

aa = 12
bb = 12
print aa == bb    # True
print aa is bb    # True

cc = 333
dd = 333
print cc == dd    # True
print cc is dd    # False

Сравнивая их адреса, прозрачно получаю передовые решения

...