Unicode และการเข้ารหัสเป็นสิ่งที่แตกต่างกันโดยสิ้นเชิงไม่เกี่ยวข้องกัน
Unicode
กำหนดรหัสตัวเลขให้กับอักขระแต่ละตัว:
ดังนั้น Unicode จึงกำหนดหมายเลข 0x41 ให้กับ A, 0xE1 ถึงáและ 0x414 ให้กับД
แม้แต่ลูกศรเล็ก ๆ →ที่ฉันใช้ก็มีหมายเลข Unicode นั่นคือ 0x2192 และแม้แต่อิโมจิก็มีหมายเลข Unicode ด้วย😂คือ 0x1F602
คุณสามารถค้นหาหมายเลข Unicode ของอักขระทั้งหมดในตารางนี้ โดยเฉพาะอย่างยิ่งคุณสามารถหาตัวละครทั้งสามดังกล่าวข้างต้นเป็นครั้งแรกที่นี่ที่ลูกศรที่นี่และอีโมจิที่นี่
ตัวเลขเหล่านี้ได้รับมอบหมายให้ทุกตัวอักษรโดย Unicode จะเรียกว่าจุดรหัส
จุดประสงค์ของทั้งหมดนี้คือเพื่อให้วิธีการอ้างถึงตัวละครแต่ละตัวอย่างชัดเจน ตัวอย่างเช่นถ้าผมพูดเกี่ยวกับ😂แทนที่จะพูดว่า"คุณรู้ว่านี้อิโมจิหัวเราะด้วยน้ำตา"ผมสามารถเพียงแค่บอกว่ารหัส Unicode จุด 0x1F602 ง่ายกว่าใช่มั้ย?
โปรดทราบว่าโดยทั่วไปจุดรหัส Unicode จะถูกจัดรูปแบบด้วยU+
เลขนำหน้าจากนั้นค่าตัวเลขฐานสิบหกจะมีตัวเลขอย่างน้อย 4 หลัก ตัวอย่างข้างต้นจะเป็น U + 0041, U + 00E1, U + 0414, U + 2192, U + 1F602
จุดรหัส Unicode มีตั้งแต่ U + 0000 ถึง U + 10FFFF นั่นคือ 1,114,112 ตัวเลข 2048 ของตัวเลขเหล่านี้ใช้สำหรับตัวแทนดังนั้นจึงยังคงมี 1,112,064 ซึ่งหมายความว่า Unicode สามารถกำหนด ID เฉพาะ (จุดรหัส) ให้กับอักขระที่แตกต่างกัน 1,112,064 ตัว ยังไม่ได้กำหนดจุดรหัสเหล่านี้ทั้งหมดให้กับอักขระและ Unicode จะขยายออกไปเรื่อย ๆ (เช่นเมื่อมีการนำอิโมจิใหม่มาใช้)
สิ่งสำคัญที่ต้องจำไว้คือ Unicode ทั้งหมดคือการกำหนด ID ตัวเลขที่เรียกว่าจุดรหัสให้กับอักขระแต่ละตัวเพื่อการอ้างอิงที่ง่ายและไม่คลุมเครือ
การเข้ารหัส
แมปอักขระกับรูปแบบบิต
รูปแบบบิตเหล่านี้ใช้เพื่อแสดงอักขระในหน่วยความจำคอมพิวเตอร์หรือบนดิสก์
มีการเข้ารหัสที่แตกต่างกันมากมายซึ่งครอบคลุมชุดย่อยของอักขระต่างๆ ในโลกที่ใช้ภาษาอังกฤษการเข้ารหัสที่พบบ่อยที่สุดมีดังต่อไปนี้:
แมปอักขระ 128 ตัว (จุดรหัส U + 0000 ถึง U + 007F) เป็นรูปแบบบิตของความยาว 7
ตัวอย่าง:
คุณสามารถดูการแมปทั้งหมดในตารางนี้
จับคู่อักขระ 191 ตัว (โค้ดชี้ U + 0020 ถึง U + 007E และ U + 00A0 ถึง U + 00FF) เป็นรูปแบบบิตที่มีความยาว 8
ตัวอย่าง:
- ก→ 01100001 (0x61)
- á→ 11100001 (0xE1)
คุณสามารถดูการแมปทั้งหมดในตารางนี้
แมปอักขระ 1,112,064 ตัว (จุดรหัส Unicode ที่มีอยู่ทั้งหมด) เป็นรูปแบบบิตที่มีความยาว 8, 16, 24 หรือ 32 บิต (นั่นคือ 1, 2, 3 หรือ 4 ไบต์)
ตัวอย่าง:
- ก→ 01100001 (0x61)
- á→ 11000011 10100001 (0xC3 0xA1)
- ≠→ 11100010 10001001 10100000 (0xE2 0x89 0xA0)
- 😂→ 11110000 10011111 10011000 10000010 (0xF0 0x9F 0x98 0x82)
วิธีที่ตัวละคร UTF-8 ถอดรหัสสตริงบิตอธิบายไว้อย่างดีที่นี่
Unicode และการเข้ารหัส
เมื่อดูจากตัวอย่างข้างต้นจะเห็นได้ชัดเจนว่า Unicode มีประโยชน์อย่างไร
ตัวอย่างเช่นถ้าฉันเป็นภาษาละติน -1และฉันต้องการอธิบายการเข้ารหัสของฉันฉันไม่จำเป็นต้องพูดว่า:
"ฉันเข้ารหัสว่า a ด้วย aigu (หรือที่คุณเรียกแถบที่เพิ่มขึ้นนั้น) เป็น 11100001"
แต่ฉันสามารถพูดได้ว่า:
"ฉันเข้ารหัส U + 00E1 เป็น 11100001"
และถ้าฉันเป็นUTF-8ฉันสามารถพูดได้ว่า:
"ฉันฉันเข้ารหัส U + 00E1 เป็น 11000011 10100001"
และทุกคนก็ชัดเจนอย่างชัดเจนว่าเราหมายถึงตัวละครใด
ตอนนี้ความสับสนที่เกิดขึ้นบ่อยๆ
เป็นเรื่องจริงที่บางครั้งรูปแบบบิตของการเข้ารหัสหากคุณตีความว่าเป็นเลขฐานสองจะเหมือนกับจุดรหัส Unicode ของอักขระนี้
ตัวอย่างเช่น:
- ASCII encodes เป็น 1100001 ซึ่งคุณสามารถตีความเป็นจำนวนฐานสิบหก0x61และจุดรหัส Unicode ของเป็นU + 0061
- Latin-1 ถอดรหัสáเป็น 11100001 ซึ่งคุณสามารถตีความเป็นเลขฐานสิบหก0xE1และจุดรหัส Unicode ของáเป็นU + 00E1
แน่นอนว่าสิ่งนี้ถูกจัดเรียงไว้เช่นนี้โดยมีวัตถุประสงค์เพื่อความสะดวก แต่คุณควรมองไปที่มันเป็นเรื่องบังเอิญที่บริสุทธิ์ รูปแบบบิตที่ใช้แทนอักขระในหน่วยความจำจะไม่เชื่อมโยงกับจุดรหัส Unicode ของอักขระนี้
ไม่มีใครบอกว่าคุณต้องตีความสตริงบิตเช่น 11100001 เป็นเลขฐานสอง เพียงแค่มองไปที่มันเป็นลำดับของบิตที่ Latin-1 ใช้การเข้ารหัสอักขระá
กลับไปที่คำถามของคุณ
การเข้ารหัสที่ใช้โดยล่ามหลามของคุณเป็นUTF-8
นี่คือสิ่งที่เกิดขึ้นในตัวอย่างของคุณ:
ตัวอย่าง 1
ต่อไปนี้เข้ารหัสอักขระáใน UTF-8 ผลนี้ในสตริงบิต 11000011 10100001 a
ซึ่งถูกบันทึกไว้ในตัวแปร
>>> a = 'á'
เมื่อคุณดูค่าของa
เนื้อหา 11000011 10100001 จะถูกจัดรูปแบบเป็นเลขฐานสิบหก 0xC3 0xA1 และเอาต์พุตเป็น'\xc3\xa1'
:
>>> a
'\xc3\xa1'
ตัวอย่าง 2
ต่อไปนี้จะบันทึกจุดรหัส Unicode ของáซึ่งก็คือ U + 00E1 ในตัวแปรua
(เราไม่รู้ว่า Python รูปแบบข้อมูลใดใช้เป็นการภายในเพื่อแทนจุดรหัส U + 00E1 ในหน่วยความจำและไม่สำคัญสำหรับเรา):
>>> ua = u'á'
เมื่อคุณดูค่าของua
Python จะบอกคุณว่ามีจุดรหัส U + 00E1:
>>> ua
u'\xe1'
ตัวอย่างที่ 3
ต่อไปนี้เข้ารหัสจุดรหัส Unicode U + 00E1 (แทนอักขระá) ด้วย UTF-8 ซึ่งส่งผลให้เกิดรูปแบบบิต 11000011 10100001 อีกครั้งสำหรับเอาต์พุตรูปแบบบิตนี้จะแสดงเป็นเลขฐานสิบหก 0xC3 0xA1:
>>> ua.encode('utf-8')
'\xc3\xa1'
ตัวอย่างที่ 4
ต่อไปนี้เข้ารหัส Unicode code point U + 00E1 (แทนอักขระá) ด้วย Latin-1 ซึ่งให้ผลลัพธ์เป็นรูปแบบบิต 11100001 สำหรับเอาต์พุตรูปแบบบิตนี้จะแสดงเป็นเลขฐานสิบหก 0xE1 ซึ่งโดยบังเอิญจะเหมือนกับค่าเริ่มต้น จุดรหัส U + 00E1:
>>> ua.encode('latin1')
'\xe1'
ไม่มีความสัมพันธ์ระหว่างวัตถุ Unicode ua
และการเข้ารหัส Latin-1 จุดรหัสของáคือ U + 00E1 และการเข้ารหัสภาษาละติน -1 ของáคือ 0xE1 (หากคุณตีความรูปแบบบิตของการเข้ารหัสเป็นเลขฐานสอง) เป็นเรื่องบังเอิญอย่างแท้จริง
unicode
มันเป็นเพียงนามธรรมของอักขระ Unicodeunicode
สามารถแปลงเป็นstr
ด้วยการเข้ารหัสบางอย่าง (เช่นutf-8
)