Das Standard-Python 2 von Mac OS X basiert auf UCS-2, daher unterscheiden sich die von den Standardfunktionen len und unichr zurückgegebenen Werte von denen in UCS-4, das in der Linux-Distribution weit verbreitet ist. Es gibt.
Wenn die Build-Option UCS-2 ist und U + 10000 und nachfolgende Zeichen enthält, kann len nicht so verwendet werden, wie es ist, um die Anzahl der Zeichen zu bestimmen. Selbst wenn es von Homebrew installiert wird, wird es von USC-2 gebaut.
Verwenden Sie den Wert von sys.maxunicode, um festzustellen, ob UCS-2 für die Erstellungsoption angegeben wurde.
>>> import sys
>>> 0xFFFF == sys.maxunicode
True
Das Anwenden von len auf die folgende Zeichenfolge (U + 20BB7 U + 91CE U + 5BB6) führt zu einem Rückgabewert von 4.
>>> str = u'?Noya'
>>> 4 == len(str)
True
Die interne Darstellung von U + 20BB7 ist das Ersatzpaar U + D842 U + DFB7.
>>> 0xD842 == ord(str[0])
True
>>> 0xDFB7 == ord(str[1])
True
Lassen Sie uns die Anzahl der Zeichen ermitteln, wenn man bedenkt, dass der Bereich des oberen Ersatzes von U + D800 bis U + DBFF reicht. Berücksichtigen Sie der Einfachheit halber keine Fälle, in denen der obere oder untere Ersatz isoliert ist. Mit UCS-4 können Sie for-Schleifen verwenden.
# -*- coding: utf-8 -*-
import sys
def utf8_len(str):
length = 0
if sys.maxunicode > 0xFFFF:
for c in str:
length += 1
return length
code_units = len(str)
pos = 0
cp = -1
while pos < code_units:
cp = ord(str[pos])
length += 1
if cp > 0xD7FF and 0xDC00 > cp:
pos += 2
else:
pos += 1
return length
Versuchen wir es noch einmal mit der vorherigen Zeichenfolge.
str = u'?Noya'
print(3 == utf8_len(str))
Als Übung ändern wir den Code ein wenig und definieren eine Funktion, die Rückrufe Zeichen für Zeichen anwendet.
# -*- coding: utf-8 -*-
import sys
def utf8_each_char(str, func):
if sys.maxunicode > 0xFFFF:
for c in str:
func(c)
else:
code_units = len(str)
pos = 0
buf = ''
cp = -1
while pos < code_units:
buf =str[pos]
cp = ord(buf)
if cp > 0xD7FF and 0xDC00 > cp:
buf += str[pos+1]
func(buf)
pos += 2
else:
func(buf)
pos += 1
Lassen Sie uns jeweils ein Zeichen anzeigen. Um print mit einem Lambda-Ausdruck zu verwenden, müssen Sie print_function am Anfang der Datei importieren.
from __future__ import print_function
str = u'?Noya'
f = lambda c: print(c)
utf8_each_char(str, f)
Die USC-2-Einschränkung akzeptiert auch unichr, das Zeichen aus Codepunkt-Ganzzahlen generiert, und akzeptiert keine 0x10000 und nachfolgende Ganzzahlen.
>>> unichr(0x20BB7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
Unicode-Escape-Sequenzen sind von UCS-2 nicht betroffen.
>>> print(u"\U00020BB7")
?
Das Folgende ist eine Definition einer Benutzerfunktion, die die Einschränkungen von UCS-2 berücksichtigt.
# -*- coding: utf-8 -*-
import sys
def utf8_chr(cp):
if 0xFFFF < sys.maxunicode or cp < 0x10000:
return unichr(cp)
cp -= 0x10000
high = cp >> 10 | 0xD800
low = cp & 0x3FF | 0xDC00
return unichr(high) + unichr(low)
print(utf8_chr(0x20BB7))
print(utf8_chr(0x91CE))
Recommended Posts