2014-09-27 8 views
8

W jaki sposób ciąg znaków Unicode jest dosłownie reprezentowany w pamięci Pythona?W jaki sposób Unicode jest wewnętrznie reprezentowany w Pythonie?

Na przykład mogłem zwizualizować 'abc' jako odpowiednik bajtów ASCII w pamięci. Integer można uważać za komplementarną reprezentację dwójki. Jednak u'\u2049', mimo że jest reprezentowana w UTF-8 jako '\xe2\x81\x89' - 3 bajtów długości, w jaki sposób wizualizować literalny punkt kodowy u'\u2049' w pamięci?

Czy istnieje szczególny sposób, w jaki jest przechowywany w pamięci? Czy Python 2 i Python 3 traktują to inaczej?

Kilka Podobne pytania dla każdego, ciekawy:

1) How are these strings represented internally in Python interpreter ? I don't understand

2) What is internal representation of string in Python 3.x

Odpowiedz

10

Python 2 i Python 3.0-3.2 zastosowanie zarówno UCS2 * lub UCS4 znaków Unicode, co oznacza, że albo użyć 2 bajty lub 4 bajty dla dla każdego znaku. Który jest wybierany jest opcją kompilacji.

\u2049 następnie reprezentowane zarówno \x49\x20 lub \x20\x49 lub \x49\x20\x00\x00 lub \x00\x00\x20\x49 w zależności od natywnej kolejności bajtów w systemie i jeżeli UCS2 lub UCS4 było zrywane. Znaki ASCII w łańcuchu Unicode nadal używają 2 lub 4 bajty na znak.

Python 3.3 przełącza się na nową wewnętrzną reprezentację, używając najbardziej zwartej formy potrzebnej do przedstawienia wszystkich znaków w łańcuchu. Wybrano 1 bajt, 2 bajty lub 4 bajty. Tekst ASCII i Latin-1 używa tylko 1 bajta na znak, pozostałe znaki BMP wymagają 2 bajtów, a następnie 4 bajty.

Aby uzyskać pełne informacje o tych reprezentacjach, zobacz PEP-393: Flexible String Representation.


* Technicznie gromadzeniu UCS-2 używa UTF-16, jak znaki nie-BMP UTF-16 zastępcze kodować 4 bajty (2 UTF-16 znaków) każda. Jednak dokumentacja Pythona nadal określa to jako UCS2.

Powoduje to nieoczekiwane zachowanie, takie jak len() dla łańcuchów unicode innych niż BMP, które są dłuższe niż liczba zawartych znaków.

+2

Aby sprawdzić, czy masz "wąską" (UCS2) lub "szeroką" (UCS4) kompilację, sprawdź sys.maxunicode. 65535 oznacza wąski, 1114111 oznacza szeroki. –

+0

Myślę, że technicznie, to UTF-16 lub UTF-32, nie UCS2 lub UCS4, ponieważ zastępcze pary są używane w wąskich kompilacjach, co czyni je UTF-16. –

+0

@NedBatchelder: w rzeczy samej, nie wiem, dlaczego dokumentacja nadal jest zgodna z UCS. –