Программирование на Python требует внимания ко многим деталям, особенно когда речь идет о работе с текстом.

Управляющие символы

В Python некоторые последовательности символов, начинающиеся с обратного слэша (\), интерпретируются особым образом. Такие последовательности называют управляющими символами или escape-последовательностями. Они необходимы для задания специфичных действий в тексте, таких как перенос строки, табуляция или возврат каретки.

Основные управляющие символы

Управляющий символ

Назначение

\n (от англ. newline – новая строка)

Перенос строки

\t (от англ. tab – табуляция)

Добавление табуляции (отступа)

\r (от англ. return – вернуться)

Возврат каретки в начало строки

\b (от англ. backspace – пробел назад)

Удаление последнего символа

Символ переноса строки (\n) позволяет вывести на экран несколько строк текста без использования дополнительных вызовов функции print():

poem = "Духовной жаждою томим,\nВ пустыне мрачной я влачился."
print(poem)

Здесь символ \n указывает Python, что после "Духовной жаждою томим," следует перейти на новую строку:

Духовной жаждою томим,
В пустыне мрачной я влачился.

Символ добавления табуляции (\t) полезен, когда необходимо добавить отступ, например, для выравнивания столбцов при выводе таблицы:

countries = "Страна\tСтолица\nРоссия\tМосква\nКитай\tПекин"
print(countries)

При выводе такой строки на экран каждый столбец «Страна-Столица» отделен отступом:

Страна  Столица
Россия  Москва
Китай   Пекин

Символ возврата каретки (\r) перемещает курсор в начало текущей строки. Следующий за этим символом текст перезаписывает существующий:

print("Или вырубишь\rЧто написано пером, не вырубишь топором")
print("Хотя если сообщение о-очень длинное, то вырубишь только часть\rЧто написано пером, не вырубишь топором")

Здесь в первой строке часть до символа \r будет перезаписана полностью, а во второй – частично, так как она длиннее:

Что написано пером, не вырубишь топором
Что написано пером, не вырубишь топором вырубишь только часть

Символ перевода каретки назад (\b) удаляет последний символ:

print("123\b45")
print("Ой ты\b\b\b, степь широкая!")

Подряд можно использовать несколько управляющих символов, поэтому во втором примере полностью удалена строка " ты":

1245
Ой, степь широкая!
Робот Кеша читает

Термин «каретка» широко применяется программистами для обозначения позиции текстового курсора, указывающей место ввода. Однако каретка и управляющие символы берут свое происхождение от механических пишущих машинок. Раньше кареткой называли подвижную часть машинки, которая определяла положение печатающего элемента. Клавиши вроде «Перевод строки» и «Возврат каретки» помогали операторам начинать новые строки и возвращаться к началу текущей строки соответственно. Со временем эти термины перешли в компьютер, сохранив свое первоначальное функциональное предназначение.

Экранирование символов

Часто строка должна содержать специальный символ как свою часть, то есть без использования его специального значения. Рассмотрим простой случай, когда нужно сохранить путь к файлу в Windows:

path = "C:\Python projects\task.py"
print(path)

Результат вывода такой строки на экран может показаться неожиданным:

C:\Python projects      ask.py

Появление отступа связано с тем, что последовательность символов \ и t в \task.py рассматривается Python как управляющий символ, обозначающий добавление табуляции. Чтобы исправить эту ситуацию, нужно экранировать символ обратной косой черты, добавив перед ней ещё один обратный слэш (\):

path = "C:\\Python projects\\task.py"
print(path) 

Теперь путь выводится корректно, так как каждый символ \ был экранирован:

C:\Python projects\task.py

Экранирование позволяет указать интерпретатору, что конкретный символ следует воспринимать буквально, а не как служебный знак. Поэтому мы даже можем включить в строку кавычки того же типа, что используются для ее определения:

print("На сцене ставили \"Колобок\"") 
# Вывод: На сцене ставили "Колобок"

Необработанные строки

Однако экранирование каждого специального символа вручную может показаться неудобным, поэтому Python предлагает альтернативный способ: необработанные строки (англ. – raw strings). В таких строках любая комбинация символов, включающих обратный слэш, интерпретируется буквально, а не как управляющая последовательность.

Создать необработанную строку можно с помощью префикса r перед открывающей кавычкой строки:

path = r"C:\Python projects\task.py"
print(path) 
# Вывод: C:\Python projects\task.py 

Использование необработанных строк значительно упрощает работу с длинными последовательностями специальных символов. Однако, хотя в необработанных строках обратные слэши считаются обычными символами, экранирование самих кавычек всё равно остаётся необходимым для того, чтобы предотвратить досрочное завершение строки.

Кодирование символов

Компьютер хранит и обрабатывает информацию в виде чисел 0 и 1, поэтому каждому символу соответствует определённая числовая последовательность. Например, заглавная английская буква A может выглядеть как 01000001.

Процесс преобразования символов в числовые коды и обратно называется их кодированием.

Если каждый символ представляет собой последовательность из 8 бит (чисел 0 и 1), то такая система позволит представить до 28 = 256 различных символов. Однако этого может быть недостаточно для некоторых языков, ведь только в китайском языке тысячи иероглифов.

Исторически существовало множество различных кодировок, каждая из которых поддерживала определенный набор символов (например, ASCII для английского языка или КОИ-8 для кириллицы). Но это вызывало трудности при передаче текста между разными языками и платформами, так как без нужной кодировки текст становился нечитаемым.

Современные системы используют универсальный стандарт для кодирования практически всех существующих символов, включая кириллицу и даже эмодзи – Юникод (англ. – Unicode). Каждому символу в Юникоде сопоставляется определенное шестнадцатеричное значение с префиксом U+. Например, значение U+1F60A соответствует эмодзи 😊, а U+0410 – заглавной русской букве А.

Python разрешает напрямую встраивать символы Юникода:

print("\u041f\u0440\u0438\u0432\u0435\u0442!") 
# Вывод: Привет!

Кодировка UTF-8

Юникод решает проблему совместимости разных кодировок благодаря единому набору символов, однако для фактического хранения символов в памяти компьютера нужен метод их представления в двоичной форме. Самым распространённым способом кодирования символов Юникода является использование кодировки UTF-8 (от англ. Unicode Transformation Format, 8-bit – формат преобразования Юникода, 8-бит).

UTF-8 обладает рядом преимуществ, включая совместимость с ASCII (первые 128 символов Юникода соответствуют ASCII), а также возможность кодирования любых символов Юникода с использованием от 1 до 4 байт.

Например, для кодирования латинских символов достаточно одного байта (или 8 бит) – английская буква A (U+0041) кодируется как 01000001, однако кириллические буквы требуют двух байт – русская буква А (U+0410) кодируется как 11010000 10010000.

Функции для работы с кодированием символов

Python предоставляет встроенные инструменты для взаимодействия с внутренними представлениями символов. Основные из них – функции ord() (от англ. ordinal – порядковый номер) и chr() (от англ. character символ).

Функция

ord(x)

Описание

Возвращает номер символа x в Юникоде

Параметры

  • x – строка, представляющая собой один символ

Возвращаемое значение

Целое число

Функция

chr(n)

Описание

Возвращает символ в Юникоде по номеру n

Параметры

  • n – порядковый номер символа в Юникоде

Возвращаемое значение

Строка

Функция ord() возвращает числовой эквивалент заданного символа в Юникоде, в то время как функция chr() делает противоположное и получает символ по указанному числу.

Например, получим порядковые номера некоторых символов:

print(ord("a")) 
# Вывод: 97
print(ord("1")) 
# Вывод: 49

А теперь по полученным порядковым номерам символов вернём сами символы:

print(chr(97)) 
# Вывод: a
print(chr(49))
# Вывод: 1

Примеры

Пример 1. Уведомление о подтверждении доставки в интернет-магазине

Уведомление о подтверждении доставки, отправляемое на электронную почту, содержит отформатированную строку с адресом:

# Данные пользователя
user_name = "Вавилов Николай Иванович"
address = "ул. Ленина, д. 15, кв. 35"
city = "Москва"
 
# Форматируем адрес с помощью \n и \t
delivery_address = (
    f"Доставка для: {user_name}\n"
    f"\tАдрес: { address}\n"
    f"\tГород: {city}\n"
)
print(delivery_address)

Вывод:

Доставка для: Вавилов Николай Иванович
        Адрес: ул. Ленина, д. 15, кв. 35
        Город: Москва

Пример 2. Путь к файлу с логами

Серверное приложение записывает логи в файл:

# Путь к файлу с логами
escaped_path = "C:\\server\\logs\\app.log"
print(f"Логи хранятся по пути: {escaped_path}")

Вывод:

Логи хранятся по пути: C:\server\logs\app.log

Пример 3. Смс-уведомление с эмодзи о готовности заказа

Интернет-магазин отправляет уведомление с эмодзи о готовности заказа:

# Текст SMS с эмодзи (Юникод)

# Текст SMS с эмодзи (Юникод)
sms_text = "Ваш заказ №42 готов к выдаче! \U0001F69A"
print(sms_text)

Вывод:

Ваш заказ №42 готов к выдаче! 🚚

Итоги

  • Управляющие символы – это последовательности символов, которые начинаются с обратного слэша (\) и используются для специальных действий в строке: \n для переноса строки, \t для добавления табуляции, \r для возврата каретки и \b для удаления последнего символа.
  • Экранирование символов с помощью обратного слэша (\) используется для того, чтобы специальные символы воспринимались как часть строки.
  • Необработанные строки создаются добавлением префикса r перед строкой. В таких строках символ \ не обрабатывается как начало управляющего символа.
  • Юникод – это универсальный стандарт для кодирования большинства существующих символов.
  • UTF-8 – это самая распространённая кодировка для хранения символов Юникода. Она использует от 1 до 4 байт для кодирования символов.
  • Функция ord() возвращает Юникод-номер заданного символа.
  • Функция chr() возвращает символ по его Юникод-номеру.

Задания для самопроверки

1. Что делает управляющий символ \n?

Переводит каретку на новую строку.

2. Используйте управляющие символы и выведите на экран следующую строку:

Величина        Единица
Сила света      кандела
Сила тока       ампер
print("Величина\tЕдиница\nСила света\tкандела\nСила тока\tампер")

3. Что такое Юникод?

Универсальный стандарт для кодирования большинства существующих символов.

4. Используйте экранирование символов и выведите на экран следующие строки:

C:\Program files\browser\test
A:\necessary files\timetable
D:\reading\bulgakov
print("C:\Program files\\browser\\test")
print("A:\\necessary files\\timetable")
print("D:\\reading\\bulgakov")

5. Чем отличаются функции ord() и chr()?

Функция ord() возвращает порядковый номер символа в Юникоде, а функция chr(), наоборот, возвращает символ по его порядковому номеру.