[PYTHON] La valeur de retour de len ou unichr peut changer selon qu'il s'agit de UCS-2 ou UCS-4.

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.

Comportement dans les options de construction UCS-2

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

Trouvez le nombre de caractères en tenant compte de UCS-2

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)

Générez des caractères à partir de points de code avec UCS-2 à l'esprit

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

La valeur de retour de len ou unichr peut changer selon qu'il s'agit de UCS-2 ou UCS-4.
En Python, changez le comportement de la méthode en fonction de la façon dont elle est appelée
Attention à la valeur de retour de __len__
Une raison simple pour laquelle la valeur de retour de round (2.675,2) est de 2,67 en python (elle devrait être de 2,68 en réalité ...)
À propos de la valeur de retour de pthread_mutex_init ()
À propos de la valeur de retour de l'histogramme.
Technologie de base qui détermine facilement si la valeur est "oui" ou "non"
Modifions automatiquement la palette de couleurs d'iTerm2 en fonction de l'heure de la journée
Changer l'ordre de PostgreSQL dans Heroku
Comment la référence du tableau python change en fonction de la présence ou de l'absence d'indices
Si branche en fonction de l'existence ou non d'un élément spécifique dans la liste
La valeur de pyTorch torch.var () n'est pas distribuée
Changer la résolution d'Ubuntu s'exécutant sur VirtualBox
[Python Data Frame] Lorsque la valeur est vide, remplissez-la avec la valeur d'une autre colonne.
Valeur de retour de quit () -Y a-t-il quelque chose retourné par la "fonction qui termine tout"?
[Est-ce explosif!?] Configuration pour utiliser la version GPU de Tensorflow sous OSX
rsync Le comportement change en fonction de la présence ou de l'absence de la barre oblique de la source de copie
J'ai essayé de faciliter la modification du paramètre du proxy authentifié sur Jupyter