2010-03-25 14 views
8

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) 

?

+4

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

+10

Koncepcja, której szukasz, to string interning: http://en.wikipedia.org/wiki/String_interning –

+0

@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). –

Odpowiedz

16

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 
+0

@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

+0

@Brian: Przepraszam, to było trochę niedokładne. Zmieniono moją odpowiedź, aby wyjaśnić sposób, w jaki CPython ją implementuje. – AndiDog

+3

Dobra odpowiedź. Jedynym szczegółem, który chciałbym dodać jest to, że Python ma 'intern()' – keturn

1

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 
+1

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

+0

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ź. –

+0

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

5

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.

Powiązane problemy