Le Python 2 standard de Mac OS X est construit sur UCS-2, de sorte que les valeurs renvoyées par les fonctions standard len et unichr sont différentes de celles de UCS-4, qui est largement utilisée dans la distribution Linux. Il y a.
Si l'option de construction est UCS-2 et qu'elle contient U + 10000 et les caractères suivants, vous ne pouvez pas utiliser len tel quel pour déterminer le nombre de caractères. Même s'il est installé par homebrew, il sera construit par USC-2.
Utilisez la valeur de sys.maxunicode pour voir si UCS-2 a été spécifié pour l'option de construction.
>>> import sys
>>> 0xFFFF == sys.maxunicode
True
L'application de len à la chaîne suivante (U + 20BB7 U + 91CE U + 5BB6) entraîne une valeur de retour de 4.
>>> str = u'?Noya'
>>> 4 == len(str)
True
La représentation interne de U + 20BB7 est la paire de substitution U + D842 U + DFB7.
>>> 0xD842 == ord(str[0])
True
>>> 0xDFB7 == ord(str[1])
True
Trouvons le nombre de caractères, considérant que la plage du substitut supérieur va de U + D800 à U + DBFF. Par souci de simplicité dans le code, ne considérez pas les cas où le substitut supérieur ou inférieur est isolé. Avec UCS-4, vous pouvez utiliser des boucles for.
# -*- 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
Essayons à nouveau la chaîne précédente.
str = u'?Noya'
print(3 == utf8_len(str))
En guise d'exercice, modifions un peu le code et définissons une fonction qui applique des rappels caractère par caractère.
# -*- 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
Affiche un caractère à la fois. Pour utiliser print avec une expression lambda, vous devez importer print_function au début du fichier.
from __future__ import print_function
str = u'?Noya'
f = lambda c: print(c)
utf8_each_char(str, f)
La contrainte USC-2 accepte également unichr, qui génère des caractères à partir d'entiers de point de code, et n'accepte pas 0x10000 et les entiers suivants.
>>> unichr(0x20BB7)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
Les séquences d'échappement Unicode ne sont pas affectées par UCS-2.
>>> print(u"\U00020BB7")
?
Ce qui suit est une définition d'une fonction utilisateur qui prend en compte les restrictions de UCS-2.
# -*- 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