Кодировки и Unicode — кратко
Кодировки и Unicode — кратко
До сих пор мы работали со строками, не задумываясь, как символы хранятся в памяти компьютера. Но при работе с файлами, сетью, базами данных и нелатинскими текстами вопрос кодировок становится практически важным. В этом уроке разберём основы.
Что такое кодировка
Компьютер хранит только числа (биты). Чтобы хранить текст, каждому символу назначается числовой код. Кодировка — это таблица соответствия «символ → число».
Исторически существовало много разных кодировок: ASCII (128 символов, латиница и цифры), KOI8-R, Windows-1251 (русский), Latin-1... При смешении кодировок возникал «кракозябр» — неправильное отображение символов.
Unicode и UTF-8
Unicode — универсальный стандарт, покрывающий все письменные системы мира. Каждому символу присвоен уникальный кодовый пункт (code point) в виде числа от 0 до 1 114 111.
UTF-8 — самая распространённая кодировка для хранения Unicode-текста. Символы латиницы занимают 1 байт, кириллица — 2 байта, редкие символы — 3-4 байта.
Python 3 использует Unicode по умолчанию. Строки str — это последовательности кодовых пунктов Unicode. Это значит, что Вы можете работать с любым языком без лишних усилий:
greeting = "Привет, 世界! مرحبا"
print(greeting) # работает без проблем
print(len(greeting)) # 17 (символы, не байты)
Функции ord() и chr()
ord(char) возвращает числовой код символа (code point):
print(ord("A")) # 65
print(ord("а")) # 1072 (кириллическая 'а')
print(ord("€")) # 8364
print(ord("😊")) # 128522
chr(code) — обратная операция: число → символ:
print(chr(65)) # A
print(chr(1072)) # а
print(chr(8364)) # €
print(chr(128522)) # 😊
Эти функции полезны при шифровании, работе с ASCII-искусством и манипуляции символами:
# Сдвиг каждого символа на 1 (простейший шифр):
def shift(text, n):
return "".join(chr(ord(c) + n) for c in text)
print(shift("Hello", 1)) # Ifmmp
Байты и строки: bytes vs str
В Python 3 строка str и байтовая строка bytes — разные типы:
s = "Привет" # str — Unicode строка
b = b"Hello" # bytes — байтовая строка (только ASCII)
print(type(s)) # <class 'str'>
print(type(b)) # <class 'bytes'>
Кодирование (encode): str → bytes:
s = "Привет"
encoded = s.encode("utf-8")
print(encoded) # b'\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82'
print(len(encoded)) # 12 байт (каждая буква = 2 байта в UTF-8)
Декодирование (decode): bytes → str:
decoded = encoded.decode("utf-8")
print(decoded) # Привет
Если указать неправильную кодировку — получите UnicodeDecodeError:
# encoded.decode("ascii") # UnicodeDecodeError — кириллица не влезает в ASCII
Работа с файлами и кодировками
При открытии файла Python принимает кодировку текстового файла. Если не указать явно — используется системная по умолчанию (обычно UTF-8 на Linux/Mac, cp1251 на Windows). Лучше указывать явно:
# Запись:
with open("file.txt", "w", encoding="utf-8") as f:
f.write("Привет, мир!")
# Чтение:
with open("file.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content) # Привет, мир!
Если файл открыть с неправильной кодировкой — получите UnicodeDecodeError или искажённый текст.
Unicode в Python: практические советы
1. Всегда явно указывайте кодировку при открытии файлов (encoding="utf-8").
2. Нормализация Unicode: один и тот же символ может иметь разные кодовые представления. Используйте unicodedata.normalize() при сравнении:
import unicodedata
s1 = "café" # е + комбинированный акцент
s2 = "café" # другое представление
print(s1 == s2) # может быть False!
print(unicodedata.normalize("NFC", s1) == unicodedata.normalize("NFC", s2)) # True
3. Проверка символа: unicodedata.category() возвращает категорию символа Unicode.
Распространённые кодировки
| Кодировка | Применение |
|---|---|
utf-8 | Универсальная, рекомендуется всегда |
utf-16 | Windows, некоторые форматы документов |
ascii | Только 127 символов латиницы |
cp1251 | Windows кириллица (устаревшая) |
latin-1 | Западноевропейские языки |
Проверь себя
Чему равна длина строки "abc" в символах и в байтах UTF-8?
s = "abc"
print(len(s)) # 3 символа
print(len(s.encode("utf-8"))) # 3 байта (латиница = 1 байт в UTF-8)
s2 = "абв"
print(len(s2)) # 3 символа
print(len(s2.encode("utf-8"))) # 6 байт (кириллица = 2 байта)
Итог
- Unicode — стандарт для всех символов мира; UTF-8 — самая распространённая кодировка.
- Python 3
str— Unicode по умолчанию; работает с любым языком. ord(c)→ числовой код символа;chr(n)→ символ по коду.str.encode("utf-8")→bytes;bytes.decode("utf-8")→str.- Всегда указывайте
encoding="utf-8"при открытии файлов. UnicodeDecodeError— сигнал неправильной кодировки.
Модуль 7 завершён! Вы глубоко разобрались со строками: срезы, поиск, методы, форматирование и Unicode. В следующем модуле переходим к функциям — главному инструменту организации кода.