После того как пользователь ввёл свои данные в требуемом формате, можно позаботиться и о пароле.
Напишите функцию password_validation
, которая принимает один позиционный параметр — пароль, и следующие именованные параметры:
min_length
— минимальная длина пароля, по умолчанию 8;possible_chars
— строка символов, которые могут быть в пароле, по умолчанию латинские буквы и цифры;at_least_one
— функция возвращающая логическое значение, по умолчаниюstr.isdigit
.
Если переданный позиционный параметр не является строкой, вызовите исключение TypeError
.
А так же реализуйте собственные исключения:
MinLengthError
— вызывается, если пароль меньше заданной длины;PossibleCharError
— вызывается, если в пароле используется недопустимый символ;NeedCharError
— вызывается, если в пароле не найдено ни одного обязательного символа.
Проверка условий должна происходить в порядке указанном в задании.
Так как, хороший разработчик никогда не хранит пароли в открытом виде, функция, в случае успешного завершения, возвращает хеш пароля. Для этого воспользуйтесь функцией sha256
из пакета hashlib
и верните его шестнадцатеричное представление.
В решении не должно быть вызовов требуемых функций.
Пример
Ввод
print(password_validation("Hello12345"))
Вывод
67698a29126e52a6921ca061082783ede0e9085c45163c3658a2b0a82c8f95a1
Ввод
print(password_validation(
"$uNri$e_777",
min_length=6,
at_least_one=lambda char: char in "!@#$%^&*()_"
))
Вывод
Вызвано исключение PossibleCharError
Решение
Продолжение серии задач на валидацию пользовательских данных.
По сути простая задача:
Проверяем передали ли нам строку, если нет, вызываем исключение.
Проверяем длину, если меньше заданого значения, вызываем исключение.
Проверяем все ли символы имеют допустимое значение, если нет – вызываем исключение.
Проверяем есть ли среди символов символ из списка обязательных, если нет – вызываем исключение.
По окончании всех проверок с помощью функций модуля hashlib генерируем и возвращаем hash пароля.
Посмотреть код
Решение
import hashlib
class MinLengthError(Exception):
pass
class PossibleCharError(Exception):
pass
class NeedCharError(Exception):
pass
possible_password_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
def password_validation(password, min_length=8,
possible_chars=possible_password_chars,
at_least_one=str.isdigit) -> str:
if not isinstance(password, str):
raise TypeError
if len(password) < min_length:
raise MinLengthError
if any([char not in possible_chars
for char in password]):
raise PossibleCharError
if not any([at_least_one(char) for char in password]):
raise NeedCharError
hash_object = hashlib.sha256()
hash_object.update(password.encode())
hash = hash_object.hexdigest()
return hash
Подскажите пожалуйста, почему это решение не проходит
import hashlib
class MinLengthError(Exception):
pass
class PossibleCharError(Exception):
pass
class NeedCharError(Exception):
pass
def password_validation(
password,
min_length=8,
possible_chars=’abcdefghijklmnopqrstuvwxyz0123456789′,
at_least_one=str.isdigit
):
if not isinstance(password, str):
raise TypeError
if len(password) < min_length:
raise MinLengthError
if any([char.lower() not in possible_chars for char in password]):
raise PossibleCharError
if not any([at_least_one(char) for char in password]):
raise NeedCharError
hash_object = hashlib.sha256()
hash_object.update(password.encode(‘utf-8’))
hex_dig = hash_object.hexdigest()
return hex_dig
принципиальных отличий между вашим и моим решением нет. Отличие одно – у вас в possible_char предложены заглавные буквы, а у меня для этого предусмотрено char.lower()
Вот ваше решение:
import hashlib
class MinLengthError(Exception):
pass
class PossibleCharError(Exception):
pass
class NeedCharError(Exception):
pass
possible_password_chars = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789’
def password_validation(password, min_length=8,
possible_chars=possible_password_chars,
at_least_one=str.isdigit) -> str:
if not isinstance(password, str):
raise TypeError
if len(password) < min_length:
raise MinLengthError
if any([char not in possible_chars
for char in password]):
raise PossibleCharError
if not any([at_least_one(char) for char in password]):
raise NeedCharError
hash_object = hashlib.sha256()
hash_object.update(password.encode())
hash = hash_object.hexdigest()
return hash
Представьте, что нам дали алфавит разрешенных символов, где запрещено использовать прописные буквы. ‘A’ использовать можно, а ‘a’ – нет.
И потом прислали пароль на проверку !AAAAaaaa123
Сергей, здравствуйте.
Позвольте еще раз задать тот же вопрос, который озвучивал Расул, и на который Вы уже ответили. Вернее, даже не задать вопрос, а уточнить нюансы для окончательного их понимания.
Вероятно, исходно неверный подход к решению вызывает некоторая путаница, связанная с решением задач G. Валидация имени, H. Валидация имени пользователя и I. Валидация пользователя. Там мы используем .lower() с целью сопоставления имени/фамилии с «сокращенной» версией алфавита (только в нижнем регистре).
И вот в этой, текущей, задаче мы по аналогии делаем так же. Интерпретатор выдает желаемый результат. И мы считаем (неверно), что всё в порядке.
Но мы не учитываем, что здесь речь идет о пароле. В котором, если учитывать значимость вопроса безопасности, регистр важен. В результате мы отправляем на проверку решение, в котором предусмотрена версия алфавита, включающая, например, только строчные буквы (используя при этом .lower() и думая, что всё хорошо). Но тест Яндекса выдает неудовлетворительный результат, поскольку тестирование «настроено», в том числе, на то, чтобы валидировать пароль на регистр (то есть не только на строчные, но и на прописные буквы).
Правильно ли я поняла суть? Скажите, пожалуйста.
А еще возник вопрос по необходимости использования списочных выражений (генераторов списков) в all([…]), any([…]).
Скажите, пожалуйста, а можно использовать просто генераторное выражение (генератор)? Ведь нам же, исходя из поставленных задач, не требуется сам список (например, для его вывода).
Если я правильно поняла из освоенной по разным источникам информации, списочные выражения заранее генерируют весь список. А генератор останавливается при обнаружении первого совпадения (в случае any) или несовпадения (в случае all). Т.е., получается, генератор не перебирает и, что важно, не запоминает лишние сведения. Поэтому, возможно, скорость выполнения не будет сильно отличаться, если при использовании генератора совпадение/несовпадение будет в конце последовательности (а может быть и будет, если в начале). Но генераторы точно позволяют экономить память, а ведь производительность же всегда важна…
Вот, например, Яндекс принимает, в том числе, такую вариацию на тему:
Уместны ли мои размышления? Очень важно Ваше мнение. Заранее спасибо.
Мне сложно предположить с чем связано ограничение на алфавит именно в этой задаче, но в жизни вполне возможна ситуация, когда в пароле на каком-то из производств могли бы быть запрещены большая I(i) и маленькая l(L) из-за похожести их написания на бумаге. И тогда не каждая заглавная или строчная буква будут иметь антипода в разрешенных к использованию буквах.
В части, касающейся вашего кода ваши рассуждения верны. Здесь нет необходимости создавать список целиком, достаточно использовать генератор.
Эта ошибка появилось потому, что при размещении решения на этом ресурсе в качестве правильного решения, я недостаточно критично посмотрел на код, созданный в процессе изучения языка. С другой стороны, это именно вариант решения, и он позволил вам задать такой хороший вопрос.
Сергей, большое… нет, вот прямо огромное спасибо!