Bei der Arbeit mit Python 2.7 frage ich mich, welchen wirklichen Vorteil die Verwendung des Typs unicode
anstelle von hat str
, da beide anscheinend Unicode-Zeichenfolgen enthalten können. Gibt es einen besonderen Grund, außer Unicode-Codes in unicode
Strings mit dem Escape- Zeichen setzen zu können \
?:
Ausführen eines Moduls mit:
# -*- coding: utf-8 -*-
a = 'á'
ua = u'á'
print a, ua
Ergebnisse in: á, á
BEARBEITEN:
Weitere Tests mit der Python-Shell:
>>> a = 'á'
>>> a
'\xc3\xa1'
>>> ua = u'á'
>>> ua
u'\xe1'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> ua
u'\xe1'
Die unicode
Zeichenfolge scheint also mit latin1
anstatt codiert zu sein, utf-8
und die Rohzeichenfolge wird mit utf-8
? Codiert . Ich bin jetzt noch verwirrter! : S.
unicode
, es ist nur eine Abstraktion von Unicode-Zeichen;unicode
kannstr
mit etwas Codierung (zButf-8
) konvertiert werden .Antworten:
unicode
ist für den Umgang mit Text gedacht . Text ist eine Folge von Codepunkten, die größer als ein einzelnes Byte sein können . Text kann codiert in einer bestimmten Codierung den Text als unformatierten Bytes darzustellen (zutf-8
,latin-1
...).Beachten Sie, dass
unicode
nicht codiert ist ! Die von Python verwendete interne Darstellung ist ein Implementierungsdetail, und Sie sollten sich nicht darum kümmern, solange sie die gewünschten Codepunkte darstellen kann.Im Gegensatz dazu ist
str
in Python 2 eine einfache Folge von Bytes . Es stellt keinen Text dar!Sie können sich
unicode
eine allgemeine Darstellung eines Textes vorstellen, der auf viele verschiedene Arten in eine Folge von Binärdaten codiert werden kann, die über dargestellt werdenstr
.Hinweis: In Python 3
unicode
wurde in umbenanntstr
und es gibt einen neuenbytes
Typ für eine einfache Folge von Bytes.Einige Unterschiede, die Sie sehen können:
Beachten Sie, dass
str
Sie bei der Verwendung ein untergeordnetes Steuerelement für die einzelnen Bytes einer bestimmten Codierungsdarstellung haben, währendunicode
Sie die Steuerung nur auf Codepunktebene steuern können. Zum Beispiel können Sie Folgendes tun:Was vorher gültig war UTF-8, ist nicht mehr. Mit einer Unicode-Zeichenfolge können Sie nicht so arbeiten, dass die resultierende Zeichenfolge keinen gültigen Unicode-Text enthält. Sie können einen Codepunkt entfernen, einen Codepunkt durch einen anderen Codepunkt ersetzen usw., aber Sie können nicht mit der internen Darstellung herumspielen.
quelle
unicode
wir Objekte serialisieren , müssen wir sie vermutlich zuerst explizitencode()
in das richtige Codierungsformat bringen, da wir nicht wissen, welches intern zur Darstellung desunicode
Werts verwendet wird.unicode
Objekt dekodieren zu können .unicode
die nicht verschlüsselt ist, ist einfach falsch. UTF-16 / UCS-2 und UTF-32 / UCS-4 sind ebenfalls Codierungen ... und in Zukunft werden möglicherweise weitere davon erstellt. Nur weil Sie sich nicht um die Implementierungsdetails kümmern sollten (und das sollten Sie auch nicht!), Bedeutet dies nicht, dass dieseunicode
nicht codiert sind. Das ist es natürlich. Ob es möglich ist.decode()
, ist eine ganz andere Geschichte.unicode
interne Darstellung des Objekts kann beliebig sein, einschließlich einer nicht standardmäßigen. Insbesondere in Python3 +unicode
wird eine nicht standardmäßige interne Darstellung verwendet, die sich auch in Abhängigkeit von den enthaltenen Daten ändert. Als solches ist es keine Standardcodierung . Unicode als Textstandard definiert nur Codepunkte, die eine abstrakte Darstellung von Text darstellen. Es gibt unzählige Möglichkeiten, Unicode im Speicher zu codieren, einschließlich des Standards utf-X usw. Python verwendet seinen eigenen Weg für die Effizienz.unicode
Objekt zu tun , da weder UTF-16 noch UTF-32 verwendet werden. Es wird eine Ad-hoc-Darstellung verwendet. Wenn Sie die Daten in tatsächliche Bytes codieren möchten, müssen Sie sie verwendenencode
. Außerdem: Die Sprache schreibt nicht vor, wieunicode
implementiert werden soll, sodass unterschiedliche Versionen oder Implementierungen von Python unterschiedliche interne Darstellungen haben können (und haben ).Unicode und Codierungen sind völlig unterschiedliche, nicht miteinander verbundene Dinge.
Unicode
Weist jedem Zeichen eine numerische ID zu:
Daher weist Unicode A die Nummer 0x41, á 0xE1 und Д 0x414 zu.
Sogar der kleine Pfeil →, den ich verwendet habe, hat seine Unicode-Nummer, es ist 0x2192. Und selbst Emojis haben ihre Unicode-Nummern, 😂 ist 0x1F602.
Sie können die Unicode-Nummern aller Zeichen in dieser Tabelle nachschlagen . Insbesondere die ersten drei Zeichen oben findet hier , Pfeil die hier und die Emojis hier .
Diese von Unicode allen Zeichen zugewiesenen Nummern werden als Codepunkte bezeichnet .
Der Zweck all dessen ist es, ein Mittel bereitzustellen, um sich eindeutig auf jedes Zeichen zu beziehen. Wenn ich zum Beispiel über 😂 spreche, anstatt zu sagen "Sie wissen, dieses lachende Emoji mit Tränen" , kann ich einfach sagen: Unicode-Codepunkt 0x1F602 . Einfacher, oder?
Beachten Sie, dass Unicode-Codepunkte normalerweise mit einem führenden Format formatiert
U+
werden und der hexadezimale numerische Wert auf mindestens 4 Stellen aufgefüllt wird. Die obigen Beispiele wären also U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602.Unicode-Codepunkte reichen von U + 0000 bis U + 10FFFF. Das sind 1.114.112 Zahlen. 2048 dieser Zahlen für verwendet werden Surrogate , so verbleiben 1.112.064. Dies bedeutet, dass Unicode 1.112.064 verschiedenen Zeichen eine eindeutige ID (Codepunkt) zuweisen kann. Noch sind nicht alle diese Codepunkte einem Zeichen zugeordnet, und Unicode wird kontinuierlich erweitert (z. B. wenn neue Emojis eingeführt werden).
Es ist wichtig, sich daran zu erinnern, dass Unicode lediglich jedem Zeichen eine numerische ID (Codepunkt) zuweist, um eine einfache und eindeutige Bezugnahme zu ermöglichen.
Kodierungen
Ordnen Sie Zeichen Bitmustern zu.
Diese Bitmuster werden verwendet, um die Zeichen im Computerspeicher oder auf der Festplatte darzustellen.
Es gibt viele verschiedene Codierungen, die verschiedene Teilmengen von Zeichen abdecken. Im englischsprachigen Raum sind die häufigsten Codierungen die folgenden:
ASCII
Ordnet 128 Zeichen (Codepunkte U + 0000 bis U + 007F) Bitmustern der Länge 7 zu.
Beispiel:
Sie können alle Zuordnungen in dieser Tabelle sehen .
ISO 8859-1 (auch bekannt als Latin-1)
Ordnet 191 Zeichen (Codepunkte U + 0020 bis U + 007E und U + 00A0 bis U + 00FF) Bitmustern der Länge 8 zu.
Beispiel:
Sie können alle Zuordnungen in dieser Tabelle sehen .
UTF-8
Karten 1.112.064 Zeichen (alle Unicode vorhandene Code Punkte) Bitmustern beiden Längen 8, 16, 24 oder 32 Bits (das heißt, 1, 2, 3 oder 4 Bytes).
Beispiel:
Die Art und Weise UTF-8 kodiert Zeichen Bitfolgen ist sehr gut beschrieben hier .
Unicode und Codierungen
Anhand der obigen Beispiele wird deutlich, wie nützlich Unicode ist.
Wenn ich zum Beispiel Latin-1 bin und meine Kodierung von á erklären möchte, muss ich nicht sagen:
Aber ich kann nur sagen:
Und wenn ich UTF-8 bin, kann ich sagen:
Und jedem ist eindeutig klar, welchen Charakter wir meinen.
Nun zu der oft auftretenden Verwirrung
Es ist wahr, dass manchmal das Bitmuster einer Codierung, wenn Sie es als Binärzahl interpretieren, mit dem Unicode-Codepunkt dieses Zeichens identisch ist.
Beispielsweise:
Natürlich wurde dies aus Bequemlichkeitsgründen absichtlich so angeordnet. Aber Sie sollten es als reinen Zufall betrachten . Das Bitmuster, das zur Darstellung eines Zeichens im Speicher verwendet wird, ist in keiner Weise an den Unicode-Codepunkt dieses Zeichens gebunden.
Niemand sagt, dass Sie eine Bitfolge wie 11100001 als Binärzahl interpretieren müssen. Betrachten Sie es einfach als die Folge von Bits, mit denen Latin-1 das Zeichen á codiert .
Zurück zu Ihrer Frage
Die von Ihrem Python-Interpreter verwendete Codierung ist UTF-8 .
In Ihren Beispielen ist Folgendes vor sich:
Beispiel 1
Im Folgenden wird das Zeichen á in UTF-8 codiert. Daraus ergibt sich die Bitfolge 11000011 10100001, die in der Variablen gespeichert wird
a
.Wenn Sie sich den Wert von ansehen
a
, wird sein Inhalt 11000011 10100001 als Hexadezimalzahl 0xC3 0xA1 formatiert und wie folgt ausgegeben'\xc3\xa1'
:Beispiel 2
Im Folgenden wird der Unicode-Codepunkt von á, der U + 00E1 ist, in der Variablen
ua
gespeichert (wir wissen nicht, welches Datenformat Python intern verwendet, um den Codepunkt U + 00E1 im Speicher darzustellen, und es ist für uns unwichtig):Wenn Sie sich den Wert von ansehen
ua
, sagt Python, dass er den Codepunkt U + 00E1 enthält:Beispiel 3
Das Folgende codiert den Unicode-Codepunkt U + 00E1 (der das Zeichen á darstellt) mit UTF-8, was zu dem Bitmuster 11000011 10100001 führt. Wiederum wird dieses Bitmuster für die Ausgabe als Hexadezimalzahl 0xC3 0xA1 dargestellt:
Beispiel 4
Das Folgende codiert den Unicode-Codepunkt U + 00E1 (der das Zeichen á darstellt) mit Latin-1, was zum Bitmuster 11100001 führt. Für die Ausgabe wird dieses Bitmuster als Hexadezimalzahl 0xE1 dargestellt, die zufällig mit der Initiale identisch ist Codepunkt U + 00E1:
Es gibt keine Beziehung zwischen dem Unicode-Objekt
ua
und der Latin-1-Codierung. Dass der Codepunkt von á U + 00E1 ist und die Latin-1-Codierung von á 0xE1 ist (wenn Sie das Bitmuster der Codierung als Binärzahl interpretieren), ist ein reiner Zufall.quelle
Ihr Terminal ist zufällig auf UTF-8 konfiguriert.
Die Tatsache, dass der Druck
a
funktioniert, ist ein Zufall; Sie schreiben rohe UTF-8-Bytes in das Terminal.a
ist ein Wert der Länge zwei , der zwei Bytes enthält, Hex-Werte C3 und A1, währendua
ein Unicode-Wert der Länge eins ist , der einen Codepunkt U + 00E1 enthält.Dieser Längenunterschied ist ein Hauptgrund für die Verwendung von Unicode-Werten. Sie können die Anzahl der Textzeichen in einer Byte-Zeichenfolge nicht einfach messen . Die
len()
Zeichenfolge gibt an, wie viele Bytes verwendet wurden und nicht, wie viele Zeichen codiert wurden.Sie können den Unterschied sehen , wenn Sie kodieren den Unicode - Wert für verschiedene Ausgabecodierung:
Beachten Sie, dass die ersten 256 Codepunkte des Unicode-Standards mit dem Latin 1-Standard übereinstimmen, sodass der U + 00E1-Codepunkt als Byte mit dem Hex-Wert E1 in Latin 1 codiert wird.
Darüber hinaus verwendet Python Escape-Codes in Darstellungen von Unicode- und Byte-Zeichenfolgen, und niedrige Codepunkte, die nicht als ASCII gedruckt werden können, werden ebenfalls mit
\x..
Escape-Werten dargestellt. Aus diesem Grund sieht eine Unicode-Zeichenfolge mit einem Codepunkt zwischen 128 und 255 genauso aus wie die Latin 1-Codierung. Wenn Sie eine Unicode-Zeichenfolge mit Codepunkten jenseits von U + 00FF haben,\u....
wird stattdessen eine andere Escape-Sequenz mit einem vierstelligen Hex-Wert verwendet.Es sieht so aus, als ob Sie den Unterschied zwischen Unicode und einer Codierung noch nicht vollständig verstehen. Bitte lesen Sie die folgenden Artikel, bevor Sie fortfahren:
Das absolute Minimum Jeder Softwareentwickler muss unbedingt über Unicode und Zeichensätze (keine Ausreden!) Von Joel Spolsky Bescheid wissen
Das Python Unicode HOWTO
Pragmatischer Unicode von Ned Batchelder
quelle
\xe1
in Latein 1.Wenn Sie a als Unicode definieren, sind die Zeichen a und á gleich. Ansonsten zählt á als zwei Zeichen. Versuchen Sie es mit len (a) und len (au). Darüber hinaus benötigen Sie möglicherweise die Codierung, wenn Sie mit anderen Umgebungen arbeiten. Wenn Sie beispielsweise md5 verwenden, erhalten Sie unterschiedliche Werte für a und ua
quelle