Модуль 5 · Строки

Справочник по Python · модуль 5 · строки

Глава 5.8

5.8

Печатность, пробелы
и состояние регистра

isprintable() и isspace() проверяют служебные свойства символов и помогают ловить то, чего не видно глазом. islower(), isupper() и istitle() отвечают на вопросы о регистре букв — и все три требуют, чтобы буквы вообще были.

Категория
Строковые методы
Уровень
Базовый → средний
Связанные темы
Unicode, регистр, очистка строк
Зачем это знать
Различать видимый текст, пробелы и регистр букв

§1Состояние, а не состав

Глава 5.7 отвечала на вопрос «из чего строка состоит»: буквы, цифры, ASCII. Здесь вопросы другие — «можно ли это показать», «есть ли тут что-то кроме пробелов», «в каком регистре буквы».

Общее правило семейства остаётся прежним: условие проверяется для каждого символа. Но пустую строку разные методы трактуют по-разному, и на этом легко ошибиться.

МетодВопросПустая строка
isprintable()всё ли можно отобразитьTrue
isspace()всё ли — пробельные символыFalse
islower()все ли буквы строчныеFalse
isupper()все ли буквы заглавныеFalse
istitle()каждое ли слово с заглавнойFalse

§2isprintable(): что видно

Метод возвращает True, если строку можно вывести на экран как есть — без управляющих символов, которые не рисуются, а отдают команды.

main.pyтекст, перевод строки и табуляция
print("Отчёт №3".isprintable())
print("Строка 1\nСтрока 2".isprintable())
print("Имя\tБалл".isprintable())
Выводперевод строки и табуляция непечатны
True
False
False

Логика здесь такая: \n не отображается сам, а перемещает курсор на новую строку; \t сдвигает его к следующей позиции табуляции. Оба — команды, а не знаки.

§3Пустая строка и пробел

Два случая, которые почти всегда удивляют.

main.pyпусто и один пробел
print("".isprintable())
print(" ".isprintable())
Выводоба варианта печатны
True
True

Пустая строка проходит по той же причине, что и в isascii(): непечатных символов в ней нет, значит условие выполнено. А обычный пробел — полноценный печатный символ: он занимает место и выводится, в отличие от \n.

§4Невидимые символы

Настоящая польза isprintable() — ловить то, что глазом не увидеть. Скопированный из документа или веб-страницы текст часто содержит служебные символы Unicode.

main.pyмежду словами — символ нулевой ширины
name = "Иван​Петров"

print(name)
print(len(name))
print(name.isprintable())
Выводбукв десять, а длина одиннадцать
ИванПетров
11
False

На экране всё выглядит нормально, но строка не совпадёт ни с "ИванПетров", ни с "Иван Петров". Такие случаи ищут по расхождению длины и по isprintable() — сравнение строк здесь бессильно, потому что глазами разницы не видно.

Откуда это берётся

Символы нулевой ширины, неразрывные пробелы и мягкие переносы попадают в данные при копировании из Word, PDF и веб-страниц. Если пользователь уверяет, что ввёл всё правильно, а проверка не проходит — len() и isprintable() первыми покажут, в чём дело.

§5isspace(): только пробельные

Метод отвечает на вопрос «в строке нет ничего, кроме пробельных символов». Строка при этом должна быть непустой.

main.pyтри варианта
print(" \t\n".isspace())
print("  x  ".isspace())
print("".isspace())
Выводбуква и пустая строка не подходят
True
False
False

Типичное применение — отсеять ввод, который выглядит заполненным, но состоит из одних пробелов.

§6Пробелов больше одного

«Пробельный символ» — это не только клавиша пробела. Сюда входят табуляция, перевод строки, возврат каретки и ряд символов Unicode.

main.pyнеразрывный пробел
nbsp = " "

print(nbsp.isspace())
print(nbsp.isascii())
print(nbsp.isprintable())
Выводпробельный, но не ASCII и не печатный
True
False
False

Неразрывный пробел выглядит как обычный, но им не является. Он не совпадёт с " " при сравнении, и именно он чаще всего попадает в текст, скопированный с веб-страницы.

§7isspace() или strip()

Задачу «строка пустая или из одних пробелов» решают двумя способами, и они не равнозначны.

main.pyдве проверки одной строки
line = "   \n"

print(line.isspace())
print(bool(line.strip()))
Выводответы противоположны по смыслу
True
False
Строкаisspace()bool(strip())
" "TrueFalse
""FalseFalse
"текст"FalseTrue

Разница в средней строке: isspace() для пустой строки даёт False, и проверка «пусто ли поле» через него пропустит пустой ввод. Поэтому для валидации надёжнее if not line.strip() — она покрывает оба случая сразу. Метод strip() разбирается в главе 5.9.

§8islower() и isupper()

Оба метода смотрят только на буквы. Цифры, пробелы и знаки препинания проверке не мешают — они просто не участвуют.

main.pyцифры и знаки не влияют
print("python 3!".islower())
print("Python 3!".islower())
print("PYTHON 3!".isupper())
print("PYthon".isupper())
Выводрешает регистр букв, а не остальных символов
True
False
True
False

§9Нужна хотя бы одна буква

Если букв в строке нет вовсе, проверять нечего — и обе проверки возвращают False.

main.pyс буквой и без неё
print("42a!".islower())
print("42A!".isupper())
print("42!".islower(), "42!".isupper())
Выводбез букв обе проверки ложны
True
True
False False

Одной строчной буквы среди цифр и знаков достаточно для islower(). А строка "42!" не является ни строчной, ни заглавной — вопрос к ней просто неприменим.

§10islower() — не отрицание isupper()

Из предыдущего параграфа следует важное: not text.isupper() и text.islower() — разные условия.

Строкаislower()isupper()Почему
"python"TrueFalseвсе буквы строчные
"PYTHON"FalseTrueвсе буквы заглавные
"Python"FalseFalseрегистр смешанный
"42!"FalseFalseбукв нет вовсе

Две последние строки дают False обеим проверкам. Значит, из «не заглавная» не следует «строчная»: между ними ещё два состояния.

§11istitle(): регистр слов

Метод проверяет, что каждая группа букв начинается с заглавной, а продолжается строчными.

main.pyтри заголовка
print("Python Для Всех".istitle())
print("Python для всех".istitle())
print("Иван Петров".istitle())
Выводво второй строке слова со строчной
True
False
True

Проверке istitle() соответствует преобразование title(): оно приводит строку ровно к такому виду. Пара работает так же, как isupper() и upper().

§12Где istitle() расходится с ожиданием

Метод считает словом любую непрерывную последовательность букв. Любой другой символ — дефис, апостроф, цифра — начинает новое «слово».

main.pyдефис, апостроф и аббревиатура
print("План-Отчёт".istitle())
print("O'Brien".istitle())
print("IPhone".istitle())
Выводпервые две строки проходят, третья — нет
True
True
False

Разберём каждую. План-Отчёт — две группы букв, обе с заглавной, проверка пройдена; а вот привычное План-отчёт её не пройдёт. В O'Brien апостроф разделил O и Brien, и обе части начинаются с заглавной. А IPhone провалился: это одна группа букв, где после заглавной I идёт ещё одна заглавная P.

Вывод для практики

istitle() проверяет механическое правило, а не правила оформления заголовков в языке. Настоящий заголовок с предлогами со строчной буквы — «Война и мир» — проверку не пройдёт. Использовать метод стоит только там, где нужно именно это механическое правило.

§13Проверка не преобразует

Методы is... ничего не меняют. Это очевидно, но ошибка встречается: строку проверяют там, где хотели преобразовать.

main.pyвопрос и действие
text = "Python"
upper_text = text.upper()

print(text.isupper())
print(upper_text, upper_text.isupper())
Выводисходная строка не изменилась
False
PYTHON True
ВопросДействие
text.isupper()text.upper()
text.islower()text.lower()
text.istitle()text.title()

Методы левого столбца возвращают bool, правого — новую строку. Преобразования разбирались в главе 5.2 и разбираются в 5.10.

§14Составные условия

Ни один метод главы не годится для проверки ввода в одиночку. Обычно условия соединяют.

main.pyимя должно быть видимым и не пустым
for name in ["Анна", "   ", "", "Иван​Петров"]:
    valid = bool(name.strip()) and name.isprintable()
    print(repr(name), valid)
Выводпроходит только первое имя
'Анна' True
'   ' False
'' False
'Иван\u200bПетров' False

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

§15Частые ошибки

Что написаноЧто произойдётКак правильно
"".isprintable() как проверка вводавернётся True: пустая строка печатнаотдельно проверить непустоту
line.isspace() как «поле не заполнено»пустая строка даст False и пройдёт проверкуif not line.strip():
not text.isupper() вместо islower()смешанный регистр и строки без букв дадут Trueпроверять то состояние, которое нужно
"123".isupper()False: букв нетпомнить о требовании хотя бы одной буквы
считать isspace() проверкой одного пробелатабуляция и перевод строки тоже пройдутсравнивать с " ", если нужен именно пробел
принимать istitle() за правила заголовка"Война и мир" проверку не пройдётписать собственное правило оформления
сравнивать строки, не проверив печатностьневидимый символ сделает равные строки разнымиlen() и isprintable() при отладке
ждать изменения строки после isupper()метод только отвечает на вопросдля преобразования вызвать upper()

§16Проверьте себя

Почему "123".islower() возвращает False?

В строке нет ни одной буквы, регистр которой можно было бы проверить. По той же причине isupper() тоже даст False.

Считает ли isprintable() пробел печатным символом?

Да. Обычный пробел выводится и занимает место, в отличие от \n и \t.

Что вернёт "".isspace() и почему это важно?

False. Поэтому проверка «поле не заполнено» через isspace() пропустит пустой ввод — надёжнее not line.strip().

Следует ли из not text.isupper(), что строка строчная?

Нет. Есть ещё смешанный регистр и строки без букв — в обоих случаях обе проверки ложны.

Почему "IPhone".istitle() даёт False, а "O'Brien" — True?

Апостроф разделяет группы букв, и каждая начинается с заглавной. В IPhone группа одна, и внутри неё вторая заглавная буква нарушает правило.

Как найти невидимый символ в строке?

Сравнить len() с ожидаемым числом символов и проверить isprintable().

§17Шпаргалка

Можно отобразитьtext.isprintable()
Только пробелыtext.isspace()
Поле не заполненоnot text.strip()
Регистр буквtext.islower()text.isupper()
Каждое слово с заглавнойtext.istitle()
Проверка вводаbool(t.strip()) and t.isprintable()

Итог главы

isprintable() отвергает управляющие символы и потому находит невидимую грязь в скопированном тексте, а пустую строку и обычный пробел считает печатными. isspace(), наоборот, требует непустой строки — из-за чего для проверки «поле не заполнено» надёжнее not text.strip(). Проверки регистра смотрят только на буквы и все три дают False, если букв нет: из «не заглавная» не следует «строчная». istitle() проверяет механическое правило, а не правила оформления заголовков.

Глава 5.8 · Проверки состояния строк · Справочник по Python Автор: Макаров Максим Николаевич