2015-03-17 8 views
5

In Python 2.7:Python ritorna lunghezza di 2 per la singola stringa di caratteri Unicode

In [2]: utf8_str = '\xf0\x9f\x91\x8d' 
In [3]: print(utf8_str) 

In [4]: unicode_str = utf8_str.decode('utf-8') 
In [5]: print(unicode_str) 
    
In [6]: unicode_str 
Out[6]: u'\U0001f44d' 
In [7]: len(unicode_str) 
Out[7]: 2 

Dal unicode_str contiene solo un singolo punto di codice Unicode (0x0001f44d), perché fa len(unicode_str) ritorno 2 invece di 1?

risposta

14

tuo binario Python è stato compilato con il supporto UCS-2 (un stretto build) ed internamente nulla al di fuori del BMP (Basic Multilingual Plane) è rappresentato utilizzando un surrogate pair.

Ciò significa che tali codici si presentano come 2 caratteri quando si richiede la lunghezza.

Dovrai ricompilare il binario Python per usare UCS-4, invece, se questo importa (./configure --enable-unicode=ucs4 permetterà di esso), o l'aggiornamento a Python 3.3 o più recente, dove Python's Unicode support was overhauled di utilizzare un tipo Unicode a larghezza variabile che commuta tra ASCII, UCS-2 e UCS-4 come richiesto dai codepoint contenuti.

Su Python versioni 2.7 e 3.0 - 3.2, è possibile rilevare quale tipo di build si dispone controllando il sys.maxunicode value; sarà 2^16-1 == 65535 == 0xFFFF per una build UCS-2 stretta, 1114111 == 0x10FFFF per una versione UCS-4 ampia. In Python 3.3 e fino a è sempre impostato su 1114111.

Demo:

# Narrow build 
$ bin/python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")' 
65535 2 [u'\ud83d', u'\udc4d'] 
# Wide build 
$ python -c 'import sys; print sys.maxunicode, len(u"\U0001f44d"), list(u"\U0001f44d")' 
1114111 1 [u'\U0001f44d'] 
+0

è possibile utilizzare 'sys.maxunicode' su Python 3 anche. È implicito, ma vale la pena indicarlo esplicitamente 'len (u '\ U0001f44d') == 1' su Python 3.3+ (o una versione larga di Python 2) – jfs

+0

@JFSebastian: certo, ma a partire da 3.3 è una costante lì, poiché Python 3.3 e versioni successive passano in modo trasparente tra ASCII, UCS-2 e una memoria UCS-4 per le stringhe, come richiesto. E tu davvero non vuoi usare Python <3.3 comunque. –

+0

Non esiste una distinzione stretta/ampia su Python 3.3+ (la rappresentazione interna non è esposta - non ti interessa cosa usi python internamente). Il punto che potresti usare 'sys.maxunicode' indipendentemente dalla versione. – jfs

Problemi correlati