Bekerja dengan Python 2.7, saya bertanya-tanya apa keuntungan nyata yang ada dalam menggunakan tipe unicode
daripada str
, karena keduanya tampaknya dapat menahan string Unicode. Apakah ada alasan khusus selain mampu mengatur kode Unicode di unicode
string menggunakan char melarikan diri \
?:
Menjalankan modul dengan:
# -*- coding: utf-8 -*-
a = 'á'
ua = u'á'
print a, ua
Hasil dalam: á, á
EDIT:
Lebih banyak pengujian menggunakan shell Python:
>>> a = 'á'
>>> a
'\xc3\xa1'
>>> ua = u'á'
>>> ua
u'\xe1'
>>> ua.encode('utf8')
'\xc3\xa1'
>>> ua.encode('latin1')
'\xe1'
>>> ua
u'\xe1'
Jadi, unicode
string tersebut tampaknya dikodekan menggunakan latin1
alih-alih utf-8
dan string mentah dikodekan menggunakan utf-8
? Saya bahkan lebih bingung sekarang! : S
unicode
, ini hanya abstraksi dari karakter unicode;unicode
dapat diubah menjadistr
dengan beberapa pengkodean (misalnyautf-8
).Jawaban:
unicode
dimaksudkan untuk menangani teks . Teks adalah urutan poin kode yang mungkin lebih besar dari satu byte . Teks dapat dikodekan dalam pengkodean tertentu untuk mewakili teks sebagai byte mentah (misalnyautf-8
,latin-1
...).Perhatikan bahwa
unicode
tidak dikodekan ! Representasi internal yang digunakan oleh python adalah detail implementasi, dan Anda tidak boleh mempedulikannya selama representasi tersebut dapat mewakili poin kode yang Anda inginkan.Sebaliknya
str
di Python 2 adalah urutan byte biasa . Itu tidak mewakili teks!Anda dapat menganggapnya
unicode
sebagai representasi umum dari beberapa teks, yang dapat dikodekan dengan berbagai cara menjadi urutan data biner yang direpresentasikan melaluistr
.Catatan: Dalam Python 3,
unicode
diubah namanya menjadistr
dan adabytes
tipe baru untuk urutan byte biasa.Beberapa perbedaan yang bisa Anda lihat:
Perhatikan bahwa menggunakan
str
Anda memiliki kontrol tingkat yang lebih rendah pada byte tunggal dari representasi pengkodean tertentu, sementara menggunakanunicode
Anda hanya dapat mengontrol pada tingkat titik kode. Misalnya, Anda dapat melakukan:Apa yang sebelumnya UTF-8 valid, sekarang tidak lagi. Menggunakan string unicode Anda tidak dapat beroperasi sedemikian rupa sehingga string yang dihasilkan bukan teks unicode yang valid. Anda dapat menghapus titik kode, mengganti titik kode dengan titik kode yang berbeda, dll. Tetapi Anda tidak dapat mengacaukan representasi internal.
sumber
unicode
objek, saya rasa pertama-tama kita harus secara eksplisitencode()
memasukkannya ke format pengkodean yang tepat, karena kita tidak tahu mana yang digunakan secara internal untuk mewakiliunicode
nilainya.unicode
objek.unicode
tidak dikodekan salah. UTF-16 / UCS-2 dan UTF-32 / UCS-4 juga merupakan penyandiaksaraan ... dan di masa mendatang lebih banyak lagi yang mungkin akan dibuat. Intinya adalah, hanya karena Anda tidak perlu peduli tentang detail implementasi (dan, memang, Anda tidak boleh!), Tetap tidak berarti ituunicode
tidak dikodekan. Tentu saja. Apakah itu bisa.decode()
'd adalah cerita yang sama sekali berbeda.unicode
representasi internal objek dapat berupa apa pun yang diinginkannya, termasuk yang non-standar. Secara khusus di python3 +unicode
tidak menggunakan representasi internal non-standar yang juga berubah tergantung pada data yang ada. Karena itu, ini bukan pengkodean standar . Unicode sebagai standar teks hanya mendefinisikan titik kode yang merupakan representasi abstrak dari teks, ada banyak cara untuk menyandikan unicode dalam memori termasuk standar utf-X dll. Python menggunakan caranya sendiri untuk efisiensi.unicode
, karena tidak menggunakan UTF-16, atau UTF-32. Ini menggunakan representasi ad hoc, dan jika Anda ingin menyandikan data ke dalam byte aktual, Anda harus menggunakanencode
. Juga: bahasa tidak mengamanatkan bagaimanaunicode
diimplementasikan, sehingga versi atau implementasi yang berbeda dari python dapat (dan memang memiliki ) representasi internal yang berbeda.Unicode dan pengkodean sama sekali berbeda, hal-hal yang tidak terkait.
Unicode
Menetapkan ID numerik untuk setiap karakter:
Jadi, Unicode memberikan angka 0x41 ke A, 0xE1 ke á, dan 0x414 ke Д.
Bahkan panah kecil → yang saya gunakan memiliki nomor Unicode-nya, 0x2192. Dan bahkan emoji memiliki nomor Unicode, 😂 adalah 0x1F602.
Anda dapat mencari nomor Unicode dari semua karakter di tabel ini . Secara khusus, Anda dapat menemukan tiga karakter pertama di atas di sini , panah di sini , dan emoji di sini .
Nomor-nomor ini ditetapkan ke semua karakter oleh Unicode disebut poin kode .
Tujuan dari semua ini adalah untuk menyediakan sarana untuk secara jelas mengacu pada setiap karakter. Misalnya kalau saya ngomongin 😂, daripada bilang "kamu tahu, emoji tertawa ini berlinang air mata" , saya cukup bilang, titik kode Unicode 0x1F602 . Lebih mudah, bukan?
Perhatikan bahwa titik kode Unicode biasanya diformat dengan awalan
U+
, kemudian nilai numerik heksadesimal ditambahkan ke setidaknya 4 digit. Jadi, contoh di atas adalah U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602.Poin kode unicode berkisar dari U + 0000 hingga U + 10FFFF. Itu adalah 1.114.112 angka. 2048 dari angka-angka ini digunakan sebagai pengganti , jadi masih ada 1.112.064. Ini berarti, Unicode dapat menetapkan ID unik (titik kode) ke 1.112.064 karakter berbeda. Belum semua poin kode ini ditetapkan ke sebuah karakter, dan Unicode diperpanjang terus menerus (misalnya, saat emoji baru diperkenalkan).
Hal penting yang harus diingat adalah bahwa semua yang dilakukan Unicode adalah menetapkan ID numerik, yang disebut titik kode, ke setiap karakter untuk referensi yang mudah dan tidak ambigu.
Pengodean
Memetakan karakter ke pola bit.
Pola bit ini digunakan untuk mewakili karakter dalam memori komputer atau pada disk.
Ada banyak pengkodean berbeda yang mencakup himpunan bagian karakter yang berbeda. Di dunia berbahasa Inggris, penyandiaksaraan yang paling umum adalah sebagai berikut:
ASCII
Peta karakter 128 (poin kode U + 0000 untuk U + 007F) ke pola bit panjang 7.
Contoh:
Anda dapat melihat semua pemetaan di tabel ini .
ISO 8859-1 (alias Latin-1)
Peta karakter 191 (kode poin U + 0020 untuk U + 007E dan U + 00A0 untuk U + 00FF) ke pola bit panjang 8.
Contoh:
Anda dapat melihat semua pemetaan di tabel ini .
UTF-8
Maps 1.112.064 karakter (semua yang ada Unicode kode poin) ke pola bit baik panjang 8, 16, 24, atau 32 bit (yaitu, 1, 2, 3, atau 4 byte).
Contoh:
Cara UTF-8 mengkodekan karakter menjadi string bit dijelaskan dengan sangat baik di sini .
Unicode dan Encoding
Melihat contoh di atas, menjadi jelas bagaimana Unicode berguna.
Misalnya, jika saya Latin-1 dan saya ingin menjelaskan pengkodean saya untuk á, saya tidak perlu mengatakan:
Tapi saya hanya bisa mengatakan:
Dan jika saya UTF-8 , saya dapat mengatakan:
Dan sangat jelas bagi semua orang karakter mana yang kami maksud.
Sekarang untuk kebingungan yang sering timbul
Memang benar bahwa terkadang pola bit pengkodean, jika Anda menafsirkannya sebagai bilangan biner, sama dengan titik kode Unicode dari karakter ini.
Sebagai contoh:
Tentu saja, ini sengaja diatur seperti ini untuk kenyamanan. Tetapi Anda harus melihatnya sebagai kebetulan belaka . Pola bit yang digunakan untuk merepresentasikan karakter dalam memori tidak terikat dengan cara apa pun ke titik kode Unicode dari karakter ini.
Bahkan tidak ada yang mengatakan bahwa Anda harus menafsirkan string bit seperti 11100001 sebagai bilangan biner. Lihat saja sebagai urutan bit yang digunakan Latin-1 untuk menyandikan karakter á .
Kembali ke pertanyaan Anda
Pengkodean yang digunakan oleh penerjemah Python Anda adalah UTF-8 .
Inilah yang terjadi dalam contoh Anda:
Contoh 1
Berikut ini mengkodekan karakter á dalam UTF-8. Ini menghasilkan string bit 11000011 10100001, yang disimpan dalam variabel
a
.Saat Anda melihat nilai
a
, isinya 11000011 10100001 diformat sebagai nomor hex 0xC3 0xA1 dan keluarannya sebagai'\xc3\xa1'
:Contoh 2
Yang berikut ini menyimpan titik kode Unicode dari á, yaitu U + 00E1, dalam variabel
ua
(kami tidak tahu format data mana yang digunakan Python secara internal untuk mewakili titik kode U + 00E1 dalam memori, dan itu tidak penting bagi kami):Saat Anda melihat nilai
ua
, Python memberi tahu Anda bahwa itu berisi titik kode U + 00E1:Contoh 3
Kode berikut menyandikan titik kode Unicode U + 00E1 (mewakili karakter á) dengan UTF-8, yang menghasilkan pola bit 11000011 10100001. Sekali lagi, untuk keluaran, pola bit ini direpresentasikan sebagai nomor hex 0xC3 0xA1:
Contoh 4
Berikut ini menyandikan titik kode Unicode U + 00E1 (mewakili karakter á) dengan Latin-1, yang menghasilkan pola bit 11100001. Untuk keluaran, pola bit ini direpresentasikan sebagai angka hex 0xE1, yang kebetulan sama dengan awal titik kode U + 00E1:
Tidak ada hubungan antara objek Unicode
ua
dan pengkodean Latin-1. Titik kode á adalah U + 00E1 dan pengkodean Latin-1 dari á adalah 0xE1 (jika Anda menafsirkan pola bit pengkodean sebagai bilangan biner) adalah murni kebetulan.sumber
Terminal Anda kebetulan dikonfigurasi ke UTF-8.
Fakta bahwa percetakan
a
adalah suatu kebetulan; Anda menulis byte UTF-8 mentah ke terminal.a
adalah nilai panjang dua , berisi dua byte, nilai hex C3 dan A1, sedangkanua
nilai unicode panjang satu , berisi titik kode U + 00E1.Perbedaan panjang ini adalah salah satu alasan utama untuk menggunakan nilai Unicode; Anda tidak dapat dengan mudah mengukur jumlah karakter teks dalam string byte; yang
len()
dari string byte memberitahu Anda berapa banyak byte yang digunakan, bukan berapa banyak karakter yang dikodekan.Anda dapat melihat perbedaannya saat mengenkode nilai unicode ke enkode keluaran yang berbeda:
Perhatikan bahwa 256 titik kode pertama dari standar Unicode cocok dengan standar Latin 1, sehingga titik kode U + 00E1 dikodekan ke Latin 1 sebagai byte dengan nilai hex E1.
Selain itu, Python menggunakan kode escape dalam representasi unicode dan string byte, dan poin kode rendah yang tidak dapat dicetak ASCII juga direpresentasikan menggunakan
\x..
nilai escape. Inilah sebabnya mengapa string Unicode dengan titik kode antara 128 dan 255 terlihat hanya seperti Latin 1 encoding. Jika Anda memiliki string unicode dengan titik kode di luar U + 00FF, urutan pelolosan yang berbeda\u....
digunakan sebagai gantinya, dengan nilai hex empat digit.Sepertinya Anda belum sepenuhnya memahami apa perbedaan antara Unicode dan pengkodean. Harap baca artikel berikut sebelum Anda melanjutkan:
Minimum Mutlak Setiap Pengembang Perangkat Lunak Sepenuhnya, Secara Positif Harus Diketahui Tentang Unicode dan Kumpulan Karakter (Tanpa Alasan!) Oleh Joel Spolsky
The Python Unicode HOWTO
Unicode Pragmatis oleh Ned Batchelder
sumber
\xe1
dalam bahasa Latin 1.Saat Anda mendefinisikan a sebagai unicode, karakter a dan á sama. Jika tidak, dihitung sebagai dua karakter. Coba len (a) dan len (au). Selain itu, Anda mungkin perlu memiliki pengkodean saat bekerja dengan lingkungan lain. Misalnya jika Anda menggunakan md5, Anda mendapatkan nilai yang berbeda untuk a dan ua
sumber