Справочник по Python · модуль 5 · строки
Глава 5.2
Регистр
строк
capitalize(), lower() и casefold() возвращают новые строки. Первые два меняют форму текста, а casefold() предназначен прежде всего для сравнений без учёта регистра — и делает это надёжнее, чем lower().
- Категория
- Строковые методы
- Уровень
- Базовый → продвинутый
- Связанные темы
- Unicode, сравнения, неизменяемость
- Зачем это знать
- Нормализовать текст для вывода и сравнения
§1Зачем приводить регистр
Человек, набирающий текст, о регистре не думает. Пользователь введёт PYTHON, Python или python и будет считать, что написал одно и то же. Программа так не считает: для неё это три разные строки.
print("PYTHON" == "Python")
False
Нормализация регистра убирает это расхождение: обе строки приводят к одной форме и сравнивают уже её. Методы этой главы решают две разные задачи — привести текст к нужному виду для показа и привести его к единой форме для сравнения. Путать их не стоит, и §13 объясняет почему.
§2Метод возвращает новую строку
Строки в Python неизменяемы, поэтому ни один метод регистра не меняет исходную строку — все они создают новую.
source = "PyThOn" result = source.lower() print(source) print(result)
PyThOn python
Строка text.lower() сама по себе не делает ничего: результат вычислен и выброшен. Нужно либо сохранить его — text = text.lower(), — либо сразу использовать в выражении. Ошибки при этом не будет, просто текст останется прежним. Это та же логика, что у методов списков в главе 3.10, только наоборот: там метод менял объект и возвращал None, здесь объект неизменяем и возвращается новый.
§3capitalize(): первая позиция
capitalize() делает первый символ строки заглавным. Параметров у метода нет.
name = "иван" print(name.capitalize())
Иван
Если первый символ регистра не имеет — цифра, знак, пробел, — он остаётся как есть.
print("123abc".capitalize())
123abc
§4capitalize() понижает остальное
Название метода описывает только половину работы. Вторая половина: все остальные буквы приводятся к нижнему регистру — независимо от того, какими они были.
title = "pYTHON API" print(title.capitalize())
Python api
p Y T H O N A P I ↑ └─────────────────┘ │ всё это → нижний регистр └ первая позиция → верхний регистр
Поэтому capitalize() не годится для оформления заголовков и названий, где регистр внутри строки важен. Для «каждое слово с заглавной» есть отдельный метод title(), а для проверки такой формы — istitle() из главы 5.8.
§5Пробел в начале
«Первая позиция» понимается буквально — это символ с индексом 0, а не первая буква. Пробел в начале строки полностью меняет результат.
text = " pYTHON" print(repr(text.capitalize())) print(repr(text.strip().capitalize()))
' python' 'Python'
В первой строке первая позиция — пробел, поднимать нечего, а все буквы после неё попали под понижение. Метод не ищет первую букву после пробелов, поэтому края строки очищают заранее — strip() разбирается в главе 5.9.
Обычный print() покажет python, и ведущие пробелы легко не заметить. repr() выводит строку в кавычках, ровно так, как её записал бы Python, — при отладке текста это экономит много времени.
§6lower(): нижний регистр
lower() возвращает копию строки, где все буквы приведены к нижнему регистру. Параметров нет.
text = "ПРИВЕТ, Python 3.12!" print(text.lower())
привет, python 3.12!
Метод работает с Unicode, поэтому корректно понижает не только латиницу: кириллица, греческий, немецкий обрабатываются так же.
§7Что lower() не трогает
В примере выше изменились только буквы. Цифры 3 и 12, точка, запятая, пробел и восклицательный знак остались на месте — у них попросту нет регистра.
| Что в строке | Что делает lower() |
|---|---|
| заглавные буквы | понижает |
| строчные буквы | оставляет как есть |
| цифры, знаки, пробелы | не меняет |
| эмодзи и символы | не меняет |
Отсюда полезное следствие: lower() безопасно применять к любому тексту — он не может испортить неалфавитную часть.
§8Где lower() подводит
Пока речь о русском и английском, lower() достаточно. Проблема начинается там, где в языке одна буква записывается несколькими способами. Немецкая ß и сочетание ss — одно и то же слово, но разные символы.
first = "Straße" second = "STRASSE" print(first.lower()) print(second.lower()) print(first.lower() == second.lower())
straße strasse False
lower() честно понизил обе строки, но ß так и осталась ß. Для человека это одно слово, для сравнения — разные строки. Именно эту задачу решает casefold().
§9casefold(): сравнение без регистра
casefold() тоже возвращает строку в нижнем регистре, но преобразует агрессивнее: он приводит к общей форме символы, которые в разных языках записываются по-разному.
first = "Straße" second = "STRASSE" print(first.casefold()) print(second.casefold()) print(first.casefold() == second.casefold())
strasse strasse True
Обратите внимание на длину: ß превратилась в две буквы ss. Результат casefold() может быть длиннее исходной строки — для сравнения это не важно, а вот для показа пользователю уже важно.
§10Греческая сигма
Немецкая ß — не единственный случай. В греческом одна и та же буква сигма пишется по-разному в конце слова и в середине.
word = "ΣΙΣΥΦΟΣ" print(word.lower()) print(word.casefold())
σισυφος σισυφοσ
lower() поступает грамотно с точки зрения языка: в конце слова он ставит конечную сигму ς. casefold() поступает грамотно с точки зрения сравнения: обе формы приводит к обычной σ, чтобы слово совпало само с собой в любой записи.
Это и есть разница между двумя методами в одной фразе: lower() сохраняет правила языка, casefold() их намеренно стирает ради сопоставимости.
§11lower() или casefold()
| Задача | Метод | Почему |
|---|---|---|
| показать текст строчными буквами | lower() | сохраняет письменные нормы языка |
| сравнить ввод пользователя | casefold() | сводит варианты записи к одному |
| поиск по тексту без учёта регистра | casefold() | то же основание |
| сделать первую позицию заглавной | capitalize() | оформление, а не сравнение |
| записать логин или e-mail в базу | lower() | результат увидит человек |
Практическое правило: текст для глаз — lower(), текст для == — casefold(). Для русского и английского они дают одинаковый результат, поэтому разница проявится не на ваших тестах, а на реальных данных.
§12Обе стороны сравнения
Нормализация помогает, только если применена к обеим строкам. Одностороннее приведение оставляет ту же проблему.
entered = "PYTHON" expected = "Python" print(entered.casefold() == expected) print(entered.casefold() == expected.casefold())
False True
В первой строке слева python, справа Python — совпадения нет. Правило простое: один и тот же метод применяют к обеим сторонам сравнения.
§13Нормализовать — не значит хранить
Соблазн понятен: привести имя пользователя к нижнему регистру один раз и хранить уже нормализованным. Но тогда исходная форма теряется навсегда.
что ввёл человек: "Иван Петров" → хранить и показывать для поиска: "иван петров" → сравнивать
Обычная практика — хранить исходный текст, а нормализованную форму использовать только для поиска и сравнения. Особенно это касается casefold(): он может изменить саму запись слова, и показывать пользователю strasse вместо введённого Straße уже неверно.
§14Порядок методов
Методы вызывают цепочкой: каждый следующий работает с результатом предыдущего. Порядок при этом меняет результат.
raw = " pYTHON API " clean = raw.strip().lower() label = clean.capitalize() print(repr(clean)) print(repr(label))
'python api' 'Python api'
| Шаг | Что на входе | Что на выходе |
|---|---|---|
raw | — | ' pYTHON API ' |
.strip() | ' pYTHON API ' | 'pYTHON API' |
.lower() | 'pYTHON API' | 'python api' |
.capitalize() | 'python api' | 'Python api' |
Общее правило цепочки: сначала убирают лишнее (strip()), затем приводят регистр, и только потом оформляют.
§15Регистр и сортировка
Глава 5.1 показала, что sorted() сравнивает кодовые точки, из-за чего заглавные буквы оказываются раньше строчных. Методы этой главы дают решение.
words = ["Яблоко", "арбуз", "Ананас"] print(sorted(words)) print(sorted(words, key=str.lower))
['Ананас', 'Яблоко', 'арбуз'] ['Ананас', 'арбуз', 'Яблоко']
Аргумент key означает «сравнивать не сами слова, а результат str.lower от них». При этом в списке остаются исходные слова — меняется только правило сравнения. Подробно key разбирается в главе 6.10.
§16Частые ошибки
| Что написано | Что произойдёт | Как правильно |
|---|---|---|
text.lower() отдельной строкой | результат выброшен, text прежний | text = text.lower() |
ждать от capitalize() сохранения остальных букв | вся строка после первой позиции станет строчной | для заголовков — title() |
" текст".capitalize() | заглавной не будет вовсе: первая позиция — пробел | text.strip().capitalize() |
lower() для сравнения многоязычного текста | "Straße" и "STRASSE" не совпадут | casefold() с обеих сторон |
casefold() для показа имени | запись слова может измениться | показывать исходную форму |
| нормализовать одну сторону сравнения | результат зависит от формы второй строки | применить метод к обеим |
text.lower без скобок | сравнение с методом, а не с текстом — всегда False | text.lower() |
capitalize() с аргументом | TypeError: метод не принимает параметров | вызывать с пустыми скобками |
§17Проверьте себя
Меняет ли lower() исходную строку?
Нет. Строки неизменяемы, метод возвращает новую строку — её нужно сохранить или сразу использовать.
Почему "pYTHON API".capitalize() даёт "Python api"?
Метод поднимает первый символ и одновременно понижает все остальные, независимо от их исходного регистра.
Почему " PYTHON".capitalize() не даёт " Python"?
Первая позиция — пробел, у него нет регистра. Буквы после неё попадают под понижение, и заглавной не остаётся.
Когда casefold() обязателен, а lower() недостаточен?
Когда в тексте возможны символы, записываемые по-разному: немецкая ß против ss, две формы греческой сигмы. Для сравнения нужна единая форма.
Почему casefold() не стоит использовать для отображения?
Он может изменить саму запись слова и даже его длину: Straße превращается в strasse.
Что не так с entered.casefold() == expected?
Нормализована только левая сторона. Метод нужно применить к обеим строкам.
§18Шпаргалка
text.capitalize()text.lower()text.casefold()a.casefold() == b.casefold()text.strip().lower()sorted(words, key=str.lower)text = text.lower()Итог главы
Все три метода создают новые строки и не меняют исходную. capitalize() поднимает первую позицию и понижает всё остальное, поэтому для заголовков не годится. lower() даёт строчную форму с сохранением языковых норм — это выбор для текста, который увидит человек. casefold() сводит разные записи одного символа к общей форме и потому надёжнее в сравнениях, но менять им текст для показа нельзя.