Как проверить пароль в Python: несколько правил и все ошибки

Python Автор: Среда и версия: CPython 3.14.5

Проверка пароля состоит из нескольких независимых вопросов: хватает ли символов, есть ли цифра, встретились ли буквы обоих регистров. Если интерфейс должен показать все замечания сразу, программа не останавливается после первой ошибки. Она проверяет каждое правило и возвращает нарушения в предсказуемом порядке. Примеры ниже выполнены на CPython 3.14.5.

Сначала зафиксируйте контракт проверки

Фраза «пароль должен быть надёжным» не задаёт алгоритм. Нужны точные условия и форма результата. Например, учебный валидатор может требовать минимальную длину, хотя бы одну цифру, заглавную и строчную букву. Результатом служит список кодов ошибок; пустой список означает, что все проверки пройдены.

До написания кода ответьте на четыре вопроса:

  1. Граница длины включительная или строгая?
  2. Что считать цифрой и буквой нужного регистра?
  3. Нужно вернуть первую ошибку или все ошибки?
  4. В каком порядке должны идти коды нарушений?

Последние два пункта влияют на структуру программы. Цепочка if — elif выбирает одну ветку, поэтому подходит для взаимоисключающих случаев. Требования к паролю независимы: одна строка может одновременно оказаться короткой, не содержать цифр и не иметь заглавных букв. Для такого контракта каждое правило проверяют отдельно.

len() считает символы строки

Встроенная функция len() возвращает число элементов последовательности. Для строки это число кодовых точек Unicode, а не размер в байтах.

samples = ["code", "пароль", "🔐code"]

for sample in samples:
    print(repr(sample), len(sample))
'code' 4
'пароль' 6
'🔐code' 5

На границе легко допустить ошибку на единицу. Если минимальная длина равна восьми, строка из восьми символов проходит это правило, а из семи — нет. В тестах нужны оба случая: только так проверяется сам знак сравнения.

Есть и тонкость Unicode. Визуально одинаковые символы могут состоять из разного числа кодовых точек. Например, é бывает одним символом или сочетанием e и отдельного ударения:

composed = "é"
combined = "e\u0301"

print(len(composed), len(combined), composed == combined)
1 2 False

Для учебной задачи достаточно поведения len(), если контракт не говорит об ином. В продуктовой форме политику Unicode и нормализации задают отдельно: незаметно менять пароль перед сохранением нельзя.

Методы строки проверяют один символ без таблиц алфавита

Методы str.isdigit(), str.isupper() и str.islower() работают и с Unicode. Поэтому ручные диапазоны вроде '0' <= char <= '9' и 'A' <= char <= 'Z' задают более узкую политику, чем строковые методы Python.

characters = ["7", "٧", "²", "A", "Я", "a", "я", "-"]

for char in characters:
    print(char, char.isdigit(), char.isupper(), char.islower())
7 True False False
٧ True False False
² True False False
A False True False
Я False True False
a False False True
я False False True
- False False False

isdigit() считает цифрами не только ASCII-символы 0–9: арабско-индийская цифра ٧ и надстрочная ² тоже дают True. Если системе разрешены только ASCII-цифры, это должно быть отдельным требованием. Подмена одного правила другим без явного решения меняет контракт.

У isupper() и islower() похожая семантика. Они учитывают регистр букв разных алфавитов, а пробелы, знаки пунктуации и цифры сами по себе не считают ни верхним, ни нижним регистром.

any() отвечает на вопрос «нашёлся хотя бы один»

any() принимает последовательность логических значений и возвращает True, как только встречает первое истинное. Генераторное выражение позволяет проверить символы без промежуточного списка:

text = "Course 7"
has_space = any(char.isspace() for char in text)
print(has_space)
True

Тот же шаблон подходит для любого строкового предиката: меняется проверка одного char, а обход строки остаётся прежним. Если синтаксис выражения внутри any() пока непривычен, сначала разберите списковые включения и генераторные выражения.

Пустой ввод заслуживает отдельного теста. Для пустого генератора any() возвращает False, потому что в нём нет ни одного истинного элемента. Это естественно для вопросов «есть ли хотя бы одна цифра» и «есть ли хотя бы одна заглавная буква».

Все нарушения собирают независимые проверки

Ранний return после первого нарушения уместен, когда функция отвечает только True или False. Для списка подсказок он мешает: пользователь исправит одну ошибку, отправит форму и лишь тогда увидит следующую.

Рабочая последовательность выглядит так:

  1. Создать пустой список проблем.
  2. Выполнить правила независимо друг от друга.
  3. Добавлять код каждого нарушенного правила в оговорённом порядке.
  4. Вернуть список после всех проверок.

Это описание намеренно не содержит готовую реализацию задачи. Оно фиксирует структуру, а условия и коды остаются частью практики.

Порядок кодов — часть API. Даже если фронтенд сейчас умеет переставлять сообщения, функция должна соблюдать контракт сама. Иначе одинаковый пароль начнёт выдавать подсказки в разной последовательности после безобидного рефакторинга.

Набор случаев, который ловит типовые ошибки

Одного «хорошего» пароля недостаточно. Минимальная таблица проверок покрывает отношения между правилами:

СлучайЧто он проверяет
пустая строкасразу несколько нарушений и отсутствие особого падения
строка на один символ короче границыстрогий знак сравнения длины
строка ровно на границеотсутствие ошибки «на единицу»
только строчные буквынезависимые проверки цифры и верхнего регистра
одна цифра в начале или концеобход всей строки, а не одной позиции
одна заглавная и одна строчная букваоба регистра распознаются отдельно
несколько нарушений сразуфункция возвращает полный список в нужном порядке
не-ASCII цифра или буквавыбранная Unicode-политика работает осознанно

Функция должна возвращать данные, а не печатать сообщения. print() полезен при отладке, но его вывод вызывающий код не сможет надёжно сопоставить с полями формы. Список коротких кодов отделяет проверку от русского текста интерфейса.

Учебный валидатор не заменяет политику продукта

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

Также не стоит незаметно обрезать пробелы или менять регистр. Для логина нормализация может быть частью контракта, а для пароля такое преобразование меняет секрет пользователя. Учебная функция решает более узкую задачу: применяет явно заданные правила к полученной строке.

Практика

В задаче «Валидация пароля на Python» нужно собрать все нарушения и сохранить порядок кодов. Она входит в путь «Python: валидация данных», где тот же подход применяется к другим форматам пользовательского ввода.

Источники