Unicode e le codifiche sono cose completamente diverse e non correlate.
Unicode
Assegna un ID numerico a ogni carattere:
- 0x41 → A
- 0xE1 → á
- 0x414 → Д
Quindi, Unicode assegna il numero 0x41 ad A, 0xE1 a á e 0x414 a Д.
Anche la piccola freccia → che ho usato ha il suo numero Unicode, è 0x2192. E anche gli emoji hanno i loro numeri Unicode, 😂 è 0x1F602.
Puoi cercare i numeri Unicode di tutti i caratteri in questa tabella . In particolare, puoi trovare i primi tre caratteri qui sopra , la freccia qui e l'emoji qui .
Questi numeri assegnati a tutti i caratteri da Unicode sono chiamati punti di codice .
Lo scopo di tutto ciò è fornire un mezzo per fare riferimento in modo inequivocabile a ciascun personaggio. Ad esempio, se sto parlando di 😂, invece di dire "sai, questa emoji che ride con le lacrime" , posso semplicemente dire, punto di codice Unicode 0x1F602 . Più facile, vero?
Tieni presente che i punti di codice Unicode sono generalmente formattati con un'interlinea U+
, quindi il valore numerico esadecimale viene riempito di almeno 4 cifre. Quindi, gli esempi precedenti sarebbero U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602.
I punti del codice Unicode vanno da U + 0000 a U + 10FFFF. Questo è 1.114.112 numeri. 2048 di questi numeri vengono utilizzati per i surrogati , quindi rimangono 1.112.064. Ciò significa che Unicode può assegnare un ID univoco (punto di codice) a 1.112.064 caratteri distinti. Non tutti questi punti di codice sono ancora assegnati a un carattere e Unicode viene esteso continuamente (ad esempio, quando vengono introdotti nuovi emoji).
La cosa importante da ricordare è che tutto ciò che Unicode fa è assegnare un ID numerico, chiamato punto di codice, a ciascun carattere per un riferimento facile e univoco.
Codifiche
Mappare i caratteri su schemi di bit.
Questi modelli di bit vengono utilizzati per rappresentare i caratteri nella memoria del computer o su disco.
Esistono molte codifiche diverse che coprono diversi sottoinsiemi di caratteri. Nel mondo anglofono, le codifiche più comuni sono le seguenti:
Mappa 128 caratteri (punti di codice da U + 0000 a U + 007F) a schemi di bit di lunghezza 7.
Esempio:
Puoi vedere tutte le mappature in questa tabella .
Mappa 191 caratteri (punti di codice da U + 0020 a U + 007E e da U + 00A0 a U + 00FF) a schemi di bit di lunghezza 8.
Esempio:
- a → 01100001 (0x61)
- á → 11100001 (0xE1)
Puoi vedere tutte le mappature in questa tabella .
Mappe 1,112,064 caratteri (tutti i punti codice Unicode esistenti) ai modelli di bit di ciascuna lunghezza 8, 16, 24, o 32 bit (cioè, 1, 2, 3, o 4 byte).
Esempio:
- a → 01100001 (0x61)
- á → 11000011 10100001 (0xC3 0xA1)
- ≠ → 11100010 10001001 10100000 (0xE2 0x89 0xA0)
- 😂 → 11110000 10011111 10011000 10000010 (0xF0 0x9F 0x98 0x82)
Il modo in cui UTF-8 codifica i caratteri in stringhe di bit è descritto molto bene qui .
Unicode e codifiche
Guardando gli esempi precedenti, diventa chiaro quanto sia utile Unicode.
Ad esempio, se sono Latin-1 e voglio spiegare la mia codifica di á, non ho bisogno di dire:
"Codifico che a con un aigu (o comunque tu chiami quella barra crescente) come 11100001"
Ma posso solo dire:
"Codifico U + 00E1 come 11100001"
E se sono UTF-8 , posso dire:
"Io, a mia volta, codifico U + 00E1 come 11000011 10100001"
Ed è inequivocabilmente chiaro a tutti quale personaggio intendiamo.
Ora alla confusione che spesso sorge
È vero che a volte lo schema di bit di una codifica, se lo interpreti come un numero binario, è lo stesso del punto di codice Unicode di questo carattere.
Per esempio:
- ASCII codifica a come 1100001, che puoi interpretare come il numero esadecimale 0x61 e il punto di codice Unicode di a è U + 0061 .
- Latin-1 codifica á come 11100001, che puoi interpretare come il numero esadecimale 0xE1 , e il punto di codice Unicode di á è U + 00E1 .
Naturalmente, questo è stato organizzato in questo modo apposta per comodità. Ma dovresti considerarla una pura coincidenza . Lo schema di bit utilizzato per rappresentare un carattere in memoria non è legato in alcun modo al punto di codice Unicode di questo carattere.
Nessuno dice nemmeno che devi interpretare una stringa di bit come 11100001 come numero binario. Considerala come la sequenza di bit che Latin-1 usa per codificare il carattere á .
Torna alla tua domanda
La codifica usata dal tuo interprete Python è UTF-8 .
Ecco cosa sta succedendo nei tuoi esempi:
Esempio 1
Quanto segue codifica il carattere á in UTF-8. Ciò risulta nella stringa di bit 11000011 10100001, che viene salvata nella variabile a
.
>>> a = 'á'
Quando guardi il valore di a
, il suo contenuto 11000011 10100001 è formattato come numero esadecimale 0xC3 0xA1 e restituito come '\xc3\xa1'
:
>>> a
'\xc3\xa1'
Esempio 2
Quanto segue salva il punto di codice Unicode di á, che è U + 00E1, nella variabile ua
(non sappiamo quale formato dati Python utilizza internamente per rappresentare il punto di codice U + 00E1 in memoria, e per noi non è importante):
>>> ua = u'á'
Quando guardi il valore di ua
, Python ti dice che contiene il punto di codice U + 00E1:
>>> ua
u'\xe1'
Esempio 3
Quanto segue codifica il punto di codice Unicode U + 00E1 (che rappresenta il carattere á) con UTF-8, che risulta nella sequenza di bit 11000011 10100001. Di nuovo, per l'output questa sequenza di bit è rappresentata come numero esadecimale 0xC3 0xA1:
>>> ua.encode('utf-8')
'\xc3\xa1'
Esempio 4
Quanto segue codifica il punto di codice Unicode U + 00E1 (che rappresenta il carattere á) con Latin-1, che risulta nel modello di bit 11100001. Per l'output, questo modello di bit è rappresentato come il numero esadecimale 0xE1, che per coincidenza è lo stesso dell'iniziale punto di codice U + 00E1:
>>> ua.encode('latin1')
'\xe1'
Non esiste alcuna relazione tra l'oggetto Unicode ua
e la codifica Latin-1. Che il punto di codice di á è U + 00E1 e la codifica Latin-1 di á è 0xE1 (se si interpreta il modello di bit della codifica come un numero binario) è una pura coincidenza.
unicode
, è solo un'astrazione del carattere Unicode;unicode
può essere convertito instr
con alcune codifiche (ad esempioutf-8
).