Используйте две предыдущих функции валидации и напишите функцию user_validation, которая принимает именованныеаргументы:
last_name— фамилия;first_name— имя;username— имя пользователя.
Если функции был передан неизвестный параметр или не передан один из обязательных, то вызовите исключение KeyError.
Если один из параметров не является строкой, то вызовите исключение TypeError.
Обработка данных должна происходить в порядке: фамилия, имя, имя пользователя.
Если поле заполнено верно, функция возвращает словарь с данными пользователя.
Примечание
В решении не должно быть вызовов требуемых функций.
Пример
Ввод
print(user_validation(last_name="Иванов", first_name="Иван", username="ivanych45"))Вывод
{'last_name': 'Иванов', 'first_name': 'Иван', 'username': 'ivanych45'}Ввод
print(user_validation(last_name="Иванов", first_name="Иван", username="ivanych45", password="123456"))Вывод
Вызвано исключение KeyErrorРешение
Продолжение серии задач на валидацию пользовательских данных.
Если воспользоваться двумя ранее написанными функциями, то остается мелочь — убедиться, что все нужные переданы поля (именованные переменные).
Это можно сделать как через проверку наличия ключа в словаре, так и через попытку получить данные с использованием try/except. Если что-то пошло не так, вызываем исключение KeyError. В противном случае, проверям с помощью функции name_validation правильность имени и фамилии, а с помощью username_validation — имя учетной записи.
Посмотреть код
Решение
class CyrillicError(Exception):
pass
class CapitalError(Exception):
pass
class BadCharacterError(Exception):
pass
class StartsWithDigitError(Exception):
pass
def name_validation(name) -> str:
valid_cyrillic_chars = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя'
if not isinstance(name, str):
raise TypeError
if not all([char.lower() in valid_cyrillic_chars for char in name]):
raise CyrillicError
if name.capitalize() != name:
raise CapitalError
return name
def username_validation(username) -> str:
valid_username_chars = 'abcdefghijklmnopqrstuvwxyz_0123456789'
if not isinstance(username, str):
raise TypeError
if not all(char.lower() in valid_username_chars for char in username):
raise BadCharacterError
if username[0].isdigit():
raise StartsWithDigitError
return username
def user_validation(*args, **kwargs) -> dict:
allowed = ['last_name', 'first_name', 'username']
user = kwargs
try:
if any([user[field] == '' for field in allowed]):
raise KeyError
except Exception:
raise KeyError
if not all([field in allowed for field in user.keys()]):
raise KeyError
name_validation(user['last_name'])
name_validation(user['first_name'])
username_validation(user['username'])
return user
Почему вы пишете содержимое функции all в квадратных скобках, когда можно написать без них и это скомпилируется:
?
вы правы, скобки тут не очень нужны. написал тогда по привычке и это не самый лучший вариант.
Здравствуйте, извините так и не понял, что проверяет вот эта строка:
try:
if any([user[field] == » for field in allowed]):
raise KeyError
Такое ощущение, что она показывает False во всех случаях. И где исключение TypeError?
Вот мое решение, которое проходит все тесты.
def user_validation(**kwargs):
keys = [‘last_name’, ‘first_name’, ‘username’]
user = kwargs
if not all(item in keys for item in kwargs):
raise KeyError
if not all(isinstance(item, str) for item in kwargs.values()):
raise TypeError
name_validation(user[‘last_name’])
name_validation(user[‘first_name’])
username_validation(user[‘username’])
return user
Если честно, я немного удивлен вопросами. Давайте разбираться
try: if any([user[field] == '' for field in allowed]): raise KeyError except Exception: raise KeyErrorЕсли любое значение ключа пустое (нам не передали параметр) — эскалируем KeyError что на мой взгляд логично. зачем вызывать проверки, если обязательные поля нам не переданы? При этом если ключ вдруг окажется не строкой, что на мой взгляд противоречит условию задачи, мы тоже эскалируем KeyError. Потому что имеем ошибку в ключе. Хотя, возможно, тут имело смысл вызвать TypeError. то что яндексы не доумались в тесте передать пустую строку в качестве имени — это их недоработка, которую вы вскрыли.
Проверка на тип, происходит внутри двух функций. Этот подход более гибок, по сравнению с вашим вариантом хотя бы тем, что если вдруг в яндексе решат в kwargs передать еще и дату рождения к примеру или любой другой ключ, на что имеют полное право к слову, который может иметь тип int ваше решение упадет с TypeError. По-хорошему проверять нужно только то, что попросили, а не все подряд. и это еще один недостаток яндексовских тестов.
Тем не менее, я не претендую на окончательную правоту ни в одном из вопросов хотя бы потому, что для того, чтобы ответить мне приходится вспоминать почему и зачем я так сделал и я могу ошибиться. Тем более, что яндексы с момента создания этого сайта могли изменить тесты и я даже не уверен, что мои решения до сих пор срабатывают.
Я всегда исхожу из мысли, что писать код стоит максимально универсально и что защита от дурака (от кривых данных на входе например) это важная составляющая программирования, которой надо обязательно научиться, чтобы писать хорошие программы. Особенно в эпоху агентского программирования.