Регистр: lower, upper, title
Один и тот же текст бывает написан как «Аня», «АНЯ» и «аня» — для Python это три разные строки. Знакомимся с методами регистра: lower, upper, title, capitalize и swapcase.
Редакция Питоники
Пользователь не заботится о регистре: в поле имени он напишет «аня», «Аня» или «АНЯ» — и все три варианта для Python различны, ведь сравнение строк идёт посимвольно. Методы регистра приводят текст к единому виду. Они есть у любой строки и вызываются точкой, как всё, что вы видели в уроке про формат-спецификации.
Сценарий: поиск по каталогу
В каталоге на 40 тысяч позиций пользователь пишет в поиск «чайник», а товар лежит под названием «Чайник электрический». Если сравнивать строки как есть, поиск не найдёт ничего, хотя человек написал правильное слово. Единственное препятствие — регистр. Снимают его в одну строку, но с важной оговоркой: нормализуют запрос, а показывают исходное название.
catalog = ['Чайник электрический', 'Кофеварка', 'ЧАЙНИК стальной']
query = 'чайник'
found = []
for name in catalog:
if query in name.lower():
found.append(name)
print(len(found))
for name in found:
print(name)
2 Чайник электрический ЧАЙНИК стальной
Два товара нашлись, третий — нет. Важно: в выводе остались и «Чайник», и «ЧАЙНИК» — исходные названия. Нормализация применялась только к запросу, который сравнивался с name.lower(). Если бы к нижнему регистру приводили и само название товара, в каталоге получилось бы два одинаковых ключа и один из товаров молча потерялся бы.
lower и upper: всё вниз и всё вверх
word = 'Питон'
print(word.lower())
print(word.upper())
питон ПИТОН
lower сгоняет все буквы в нижний регистр, upper — в верхний. Всё остальное — цифры, пробелы, знаки препинания — остаётся как было: у них регистра нет. Русские буквы обрабатываются так же, как латинские.
title, capitalize и swapcase
phrase = 'коТ Код и тОкен'
print(phrase.title())
print(phrase.capitalize())
print(phrase.swapcase())
Кот Код И Токен Кот код и токен КОт кОД И ТоКЕН
Три метода решают три разные задачи. title делает заглавной первую букву каждого слова — так оформляют имена и заголовки. capitalize поднимает только первый символ всей строки, а остальные буквы опускает. swapcase меняет регистр каждой буквы на противоположный — редкий гость в рабочем коде, но полезный для понимания: метод работает с каждым символом по отдельности.
Сравнение без учёта регистра
Зачем всё это нужно? Затем, что сравнивать текст людей нужно без учёта регистра. Строки «PYTHON» и «python» не равны, но их lower-версии равны всегда:
saved = 'python'
answer = 'PYTHON'
print(answer == saved)
print(answer.lower() == saved.lower())
False True
Это главный приём урока: и почту, и команды бота, и поисковые запросы перед сравнением приводят к нижнему регистру. Цикл по списку команд из реального бота выглядел бы так:
commands = ['СТОП', 'Start', 'выход']
for c in commands:
print(c.lower())
стоп start выход
lower против casefold: когда нужен второй
У большинства букв разница только в паде редких случаев. Немецкая ß при полном приведении к регистру превращается в ss, а обычный lower оставляет ß как ß. Для немецкого текста это две разные строки, и сравнение не сойдётся. Python 3.3 добавил отдельный метод casefold() — он приводит строку к виду, пригодному для сравнения, независимо от языка.
print('straße'.lower())
print('straße'.casefold())
print('STRASSE'.casefold())
print('straße'.casefold() == 'STRASSE'.casefold())
straße strasse strasse True
Для русского текста lower и casefold ведут себя одинаково, поэтому в большинстве проектов хватает lower. casefold ставят там, где текст сравнивают на разных языках: словари поисковых индексов, коды товаров, импорт из внешних источников.
Регистр и словари
Словарь чувствителен к регистру так же, как и сравнение: «Чай» и «чай» — два разных ключа. Если это не нужно, ключи нормализуют при записи, и товар с другим регистром просто перезапишет прежний.
prices = {'Чай': 320, 'чай': 340}
print(len(prices))
clean = {}
for name, price in prices.items():
clean[name.lower()] = price
print(len(clean), clean['чай'])
2 1 340
Первый словарь хранил два товара, второй — один: приведённые к нижнему регистру ключи столкнулись, и цена 340 переписала 320. Так нормализуют всё, что приходит извне и не должно плодить дубли.
| Метод | Что делает | Пример |
|---|---|---|
| lower() | всё в нижний регистр | 'Питон' → 'питон' |
| upper() | всё в верхний регистр | 'Питон' → 'ПИТОН' |
| title() | заглавная первая буква каждого слова | 'кот код' → 'Кот Код' |
| capitalize() | заглавная только первая буква строки | 'коТ Код' → 'Кот код' |
| swapcase() | меняет регистр каждой буквы наоборот | 'КОт' → 'коТ' |
| casefold() | полное приведение для сравнения | 'straße' → 'strasse' |
name = 'аня'
name.upper()
print(name)
name = name.upper()
print(name)
аня АНЯ
Первая попытка вычислила 'АНЯ' и тут же выбросила её: строка, которую никто не сохранил, исчезает. Строки неизменяемы — это правило из урока 1, и методы регистра его честно соблюдают: они не правят старую строку, а дарят новую.
Где ещё пригождается приведение регистра
- Поиск и фильтры: запрос приводят к нижнему регистру, чтобы «Чайник» и «чайник» нашлись вместе.
- Ключи словарей и теги: приводят при записи, чтобы не плодить дубликаты.
- Имена файлов: на Windows и macOS регистр не учитывается, на Linux учитывается. Код, который должен работать везде, сравнивает имена приведёнными к одному регистру.
- Артикулы и идентификаторы: «AB-12» и «ab-12» при импорте схлопываются в один код.
- Пароли — исключение из правил: их к нижнему регистру не приводят.
Из этих пяти случаев последний — исключение, и он важнее остальных. Приём «приведи и сравни» хорош для поиска, но не для секретов: если пароль приводить к нижнему регистру, «Passw0rd» и «passw0rd» становятся одним и тем же паролем, а защита слабеет. Пароли сравнивают точно, а длинные — дополнительно хешируют, и это отдельная тема.
tag = ' Python для всех '
clean = tag.strip().lower()
slug = clean.replace(' ', '-')
print(clean)
print(slug)
python для всех python-для-всех
Три операции подряд — и на выходе идентификатор, пригодный для адреса страницы или тега. Заметьте, что replace здесь работает уже по очищенной строке: сначала края, потом регистр, потом разделители. Порядок в таких цепочках решает всё — с пробелами по краям получился бы slug с дефисом в начале.
Мини-практика: коды товаров
Коды приходят из разных источников и отличаются регистром: «AB-12», «ab-12», «Ab-12» — для человека это один и тот же код, а для словаря — три. Приведём кода к общему виду и посчитаем, сколько уникальных на самом деле.
codes = ['AB-12', 'ab-12', 'Ab-12', 'CD-34']
seen = {}
for code in codes:
seen[code.lower()] = seen.get(code.lower(), 0) + 1
print(len(seen))
print(seen)
2
{'ab-12': 3, 'cd-34': 1}Четыре кода на входе, два на выходе: словарь привёл ключи к нижнему регистру и посчитал, сколько раз каждый встретился. Тот же приём без словаря записывается короче — множественным пониманием, о котором пойдёт речь в уроке про строки и списки.
Как сравнить две строки без учёта регистра
Это отдельный вопрос, и он возникает чаще, чем кажется. Сравнение answer == saved для 'ДА' и 'да' даёт False — и код, который проверяет команду бота или код промо, молча уходит в ветку «не совпало». Приём с .lower() на обеих сторонах вы изучили, но есть три вещи, которые на нём ломаются: когда приводить не нужно, когда приводить опасно и что делать, если в тексте смешаны языки.
saved = ['Питон', 'JAVA', 'Go']
incoming = ['питон', 'java', 'GO']
pairs = []
for a, b in zip(saved, incoming):
pairs.append(a.lower() == b.lower())
print(pairs)
print(all(pairs))
[True, True, True] True
Сравнивать по одному удобно, когда пары должны совпасть позициями. Но чаще нужно «совпало ли хоть одно» — и тут any() вместо all() сэкономит одну строку. Честнее сказать: zip здесь бросит ValueError, если длины списков разойдутся, а в реальном API списки приходят разной длины постоянно. В рабочем коде я бы сравнивал множества: set(x.lower() for x in saved) & set(y.lower() for y in incoming). Множества не упорядочены, но для вопроса «есть ли пересечение» это ровно то, что нужно.
- Приводить к регистру нужно обе стороны:
a.lower() == b.lower(), а не только одну — иначе сравнение останется чувствительным. - Не приводите то, что чувствительно к регистру: пароли, токены, контрольные суммы, артикулы. Там регистр — часть значения.
- Не приводите то, что человек должен увидеть в исходном виде: имя в письме, город в отчёте, название товара в выдаче.
Сортировка и поиск: регистр решает всё
Отдельная боль — сортировка. Python сортирует строки по кодам символов, а не по алфавиту и не по-человечески. Заглавные буквы имеют коды меньше строчных, поэтому 'Апельсин' встанет раньше 'яблоко' — и список выглядит перемешанным. Для поиска по каталогу или списку имён это выглядит как баг.
words = ['яблоко', 'Апельсин', 'банан']
print(sorted(words, key=str.lower))
['Апельсин', 'банан', 'яблоко']
Ключ key=str.lower говорит сортировке: сравнивай не сами строки, а их нижнерегистровые копии, а выводи originals. Обратите внимание — в выводе осталась исходная 'Апельсин' с большой буквы. Это то поведение, которое нужно в интерфейсе: порядок по алфавиту, написание как в исходнике. Отдельно скажу про casefold из урока 5 — для русского текста он не даёт ничего, а для немецкой ß меняет всё, поэтому в key= для русских данных берите str.lower.
| Задача | Что писать | Почему |
|---|---|---|
| Сравнить два ввода | a.lower() == b.lower() | Обе стороны в одном регистре |
| Найти в списке | next((x for x in items if x.lower() == q.lower()), None) | Сравнение по ключу, без лишнего списка |
| Отсортировать по-человечески | sorted(items, key=str.lower) | Исходное написание сохраняется |
| Проверить «это то же слово?» | a.casefold() == b.casefold() | casefold — для многоязычных сравнений |
Про next(...) стоит сказать отдельно: это не магия, а способ получить первый подходящий элемент и None, если ничего не нашлось. Альтернатива — цикл с break, но в генераторном виде он читается как «найди мне первое совпадение», и его удобно передавать в any() или all(): any(x.lower() == q.lower() for x in items).
Практика: приводим импорт к единому виду
Кейс, который встречается в каждом втором проекте — выгрузка из внешней системы. Коды приходят разнобоем: 'AB-12', 'ab-12', 'Ab-12'. Для человека это один артикул, для словаря — три. Наивное решение «пройтись по ключам и привести к нижнему регистру» ломает исходный словарь, и это редко замечают: код работает, просто часть товаров исчезает из выдачи.
codes = ['AB-12', 'ab-12', 'Ab-12']
uniq = {}
for code in codes:
key = code.lower()
uniq[key] = uniq.get(key, 0) + 1
print(uniq)
{'ab-12': 3}Словарь-счётчик решает обе задачи сразу: показывает, сколько записей схлопнулось (3), и даёт нормализованный ключ для последующего использования. Оригиналы при этом теряются — если нужно и нормализованное имя, и исходное, храните пару: records[key] = original. Мой совет: нормализуйте ключ в момент записи в хранилище, а не при каждом чтении. Тогда все потребители работают с одним и тем же видом данных и никто не вспоминает про .lower() в пятом месте.
Любой метод регистра возвращает новую строку: старая остаётся такой, какой была.
Сначала предскажи ответ в голове — это главный навык программиста.
print('ПиТоН'.lower())
phrase = 'кот код'
print(phrase.title())
print(phrase.capitalize())
answer = 'ДА'
print(answer.lower() == 'да')
1. Что вернёт 'Питон'.upper()?
2. Чем capitalize отличается от title?
3. Как правильно сравнить ввод пользователя с сохранённым паролем без учёта регистра?
4. Что выведет код: name = 'аня', затем name.upper(), затем print(name)?
5. Что сделает swapcase со строкой 'КОт'?
6. Что произойдёт с цифрами и пробелами при вызове 'кот 2026'.upper()?
7. Что вернёт 'straße'.casefold()?
8. Почему title() опасен для имён и артикулов?
Дана строка email с лишними пробелами по краям и заглавными буквами. Приведи её в порядок: убери пробелы по краям методом strip() и приведи всё к нижнему регистру — результат запиши в переменную и выведи.
Как привести строку к нижнему регистру в Python?
Методом lower: 'Питон'.lower() вернёт 'питон'. Метод не меняет исходную строку, а возвращает новую — результат нужно сохранить: s = s.lower(). Для верхнего регистра есть парный метод upper.
Урок 1: неизменяемость строкКак сравнить две строки без учёта регистра?
Привести обе к одному регистру и сравнить: answer.lower() == saved.lower(). Это стандартный приём для почт, команд бота и любых данных, которые люди набирают руками, — они почти никогда не бывают в едином регистре.
Чем title отличается от capitalize?
title делает заглавной первую букву каждого слова ('кот код' — 'Кот Код'), capitalize — только первый символ всей строки, опуская остальные ('коТ Код' — 'Кот код'). Для имён и заголовков берут title, для предложений — capitalize.
Почему name.upper() не меняет строку name?
Строки в Python неизменяемы: методы регистра не правят исходник, а возвращают новую строку. Если результат не присвоить — name = name.upper() — он просто исчезнет. То же верно для replace, strip и всех остальных методов строк.
Урок 7: replaceЧем lower отличается от casefold?
lower приводит буквы к нижнему регистру по правилам языка, casefold даёт полностью приведённую форму, пригодную для сравнения. Разница видна на немецкой ß: lower оставит «straße», а casefold превратит её в «strasse». Для русского текста методы равнозначны.
Урок 14: юникод и кодировкиКак найти товар по названию, не различая регистр?
Привести к одному регистру обе стороны и сравнить: if query.lower() in name.lower(). При этом нормализуют только то, с чем сравнивают, — само название товара остаётся как есть, чтобы в выводе не потерялся исходный вид.
Как сравнить две строки без учёта регистра в Python?
Привести обе стороны к нижнему регистру: a.lower() == b.lower(). Для поиска по списку удобнее генератор: any(x.lower() == q.lower() for x in items). Регистр приводят у обеих сторон — привести только одну бессмысленно. Для текста на разных языках используйте casefold() вместо lower(): он даёт форму, пригодную для сравнения.
Почему после lower() строки всё равно не равны?
Потому что lower() убирает только различия в регистре. Пробелы по краям, неразрывные пробелы, «ё» против «е» и «й» против «и» остаются. Порядок приведения важен: сначала приведите текст к одному виду (strip()), потом к регистру (lower()). Если совпадение нужно по всей строке, используйте casefold() — он честнее lower() для сравнений.
Как отсортировать список строк по алфавиту, а не по кодам?
Передайте ключ сортировки: sorted(words, key=str.lower). Python сравнивает не сами строки, а их нижнерегистровые копии, а выводит исходные — так написание сохраняется. Без key заглавные буквы встанут раньше строчных, потому что их коды меньше.
Можно ли приводить к нижнему регистру пароли?
Нет. Приведение к регистру делает разные пароли одинаковыми и снижает стойкость: 'Passw0rd' и 'passw0rd' станут одним ключом. Пароли сравнивают точно, а длинные — хешируют. Регистр допустимо нормализовать только там, где это не ослабляет защиту: имена пользователей для поиска, теги, артикулы.
Понравился урок? Сошлитесь на него
«Любой метод регистра возвращает новую строку: старая остаётся такой, какой была.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Строки · Урок 4
Формат-спецификации f-строк: цена, ширина, выравнивание
F-строка умеет не только вставлять значение, но и оформлять его: два знака после точки у цены, ровные колонки, знак числа, нули вместо пробелов. Всё это — спецификация после двоеточия.
Строки · Урок 6
strip: обрезаем пробелы и мусор
Пробелы по краям — самая частая грязь в данных: ввод пользователя, поля CSV, строки из файлов. Знакомимся с strip, lstrip и rstrip — и с аргументом-набором символов.
Строки · Урок 1
Строки в Python: текст как данные
Строка — самый частый тип данных в реальных задачах: имена, города, сообщения. Знакомимся с типом str: кавычки, len, конкатенация и умножение — и узнаём, почему строку нельзя переписать на месте.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
ООП · Урок 11
Магические методы: __str__ и __repr__
print(obj) без подготовки показывает тип и адрес в памяти. Магические методы __str__ и __repr__ позволяют самим решить, как объект превращается в строку, — человек увидит «21°C», а отладчик — Temperature(21).
магические методы pythondunder методы python
Datetime · Урок 5
strptime: строка превращается в дату
Лог, форма и таблица присылают даты строками — для вычислений нужен объект. Учим strptime читать строку по шаблону и отличать настоящий формат от почти настоящего.
строку в дату pythonpython преобразование строки в дату
Строки · Урок 9
split: разобрать строку
Одна строка данных редко живёт одна: CSV-запись, строка лога, поля формы. Метод split режет строку по разделителю и возвращает список частей — разбираем все варианты, от запятой до splitlines.
python разбить строкуpython разделить строку по запятой