Czy Python ma pulę wszystkich ciągów znaków i czy są tam (ciągi) singletony?Czy łańcuchy są zestawiane w Pythonie
dokładniej w poniższym kodzie jeden lub dwa ciągi powstały w pamięci:
a = str(num)
b = str(num)
?
Czy Python ma pulę wszystkich ciągów znaków i czy są tam (ciągi) singletony?Czy łańcuchy są zestawiane w Pythonie
dokładniej w poniższym kodzie jeden lub dwa ciągi powstały w pamięci:
a = str(num)
b = str(num)
?
Struny są niezmienne w Pythonie, więc realizacja może zdecydować, czy stażysta (który to termin często wiąże się z C# co oznacza, że niektóre łańcuchy są przechowywane w puli) lub nie.
W twoim przykładzie dynamicznie tworzysz ciągi. CPython robi nie zawsze zajrzeć do puli, aby wykryć, czy ciąg znaków już tam jest - nie ma to również sensu, ponieważ najpierw trzeba zarezerwować pamięć w celu utworzenia ciągu, a następnie porównać ją z zawartością puli (nieefektywną) na długie struny).
Ale dla ciągów o długości 1, CPython wygląda na basenie (por "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;
}
...
Więc:
a = str(num)
b = str(num)
print a is b # <-- this will print False in most cases (but try str(1) is str(1))
Jednak przy użyciu stale ciągi bezpośrednio w kodzie, CPython używa tej samej instancji łańcucha:
a = "text"
b = "text"
print a is b # <-- this will print True
@Andidog: Jeśli CPython nie zagląda do puli, aby sprawdzić, czy ciąg znaków już tam jest, to dlaczego print a is b wyświetla wartość true, gdy liczba jest równa 5? – Brian
@Brian: Przepraszam, to było trochę niedokładne. Zmieniono moją odpowiedź, aby wyjaśnić sposób, w jaki CPython ją implementuje. – AndiDog
Dobra odpowiedź. Jedynym szczegółem, który chciałbym dodać jest to, że Python ma 'intern()' – keturn
Struny nie są ogólnie internowane. W twoim przykładzie zostaną utworzone dwa ciągi (z wyjątkiem wartości z przedziału od 0 do 9). Aby to sprawdzić możemy użyć operatora is
aby sprawdzić, czy dwa ciągi są takie same obiektu:
>>> str(1056) is str(1056)
False
co następująco: w [1] X = ul (5) w [2]: Y = ul (5) W [3]: identyfikator (x) Z [3]: 3077925280L W [4]: id (y) Out [4]: 3077925280L ? – gruszczy
gruszczy: To dobre pytanie. Jest to szczególny przypadek, który dotyczy tylko liczb od 0 do 9.Generalnie jednak stwierdzenie nie jest prawdziwe. Wyjaśniłem moją odpowiedź. –
Od 0 do 9 to konkretny przypadek określonego kompilatora (choć wprawdzie jest to kompilator używany przez większość użytkowników). Inne kompilatory mogą wybrać inną liczbę wstępnie zdefiniowanych ciągów. – Brian
Generalnie ciągi nie są internowany w Pythonie, ale one czasami wydają się być:
>>> str(5) is str(5)
True
>>> str(50) is str(50)
False
To nie jest rzadkością w Pythonie, gdzie wspólne obiekty mogą być zoptymalizowane w taki sposób, że te nie są niezwykłe:
>>> int(5+0) is int(5+0)
True
>>> int(50+0) is int(50+0)
True
>>> int(500+0) is int(500+0)
False
Pamiętaj, że wszystkie te szczegóły będą się różnić między implementacjami Pythona, a nawet między wersjami tej samej implementacji.
Dla celów referencyjnych ciągi nie mogą być pojedynczymi literami. Singleton jest klasą, dla której może istnieć tylko jedna instancja, a ta instancja musi być dostępna globalnie. Można (miejmy nadzieję) mieć wiele instancji klasy 'str'; dlatego nie jest to singleton. – zneak
Koncepcja, której szukasz, to string interning: http://en.wikipedia.org/wiki/String_interning –
@zneak Dziękujemy za komentarz. Miałem na myśli coś takiego jak value-singleton (interakcja z pulami lub stringami to właściwe słowo - http://en.wikipedia.org/wiki/String_interning). –