Как упростить данный код?
Как можно укоротить следующий код с проверкой возраста для большей производительности?
def age_is_numeric(data):
while True:
age = input(data)
if age.isdigit():
age = int(age)
if age >= 18:
print("Доступ есть, удачи!")
else:
print("Вы маловат, возвращайтесь позже")
break
else:
print("Не распознали возраст, попробуйте снова!")
continue
user_age = age_is_numeric("Введите возраст:")
Ответы (2 шт):
Вот пример того, как это может быть в реальной программе. Хотя это всё-равно заготовка. Если начать писать классы, то это опять же будет по-другому. Но тут хотя бы метод максимального рефакторинга. Функции мелкие, выполняющие конкретную задачу, и настраиваемые параметрами.
def input_int(prompt):
while True:
inp = input(prompt)
if inp.isdigit():
return int(inp)
print("Некорректный ввод. Введите целое число, пожалуйста!")
def is_allowed_age(age):
return age >= 18
def check_age(age, checker):
if not checker(age):
raise ValueError('Возраст недостаточен. Возвращайтесь позднее.')
def validate_age(imputer, prompt, checker):
age = input_int(prompt)
check_age(age, checker)
def validate_user_data():
try:
validate_age(input_int, "Введите возраст:", is_allowed_age)
# validate ещё что-нибудь
print("Доступ есть, удачи!")
except ValueError as ex:
print(f'Ошибка проверки данных пользователя: {str(ex)}')
validate_user_data()
- Разбивка на мелкие функции, по возможности максимально "чистые", т.е. не зависящие напрямую от других функций, позволяет:
- удобно тестировать код
- легко перенастраивать логику функций
- переиспользовать эти функции
- легко читать и понимать отдельные куски кода вне остального контекста программы
- Использование исключений позволяет не проверять какие-то вещи по выходе из функций, а "вылетать" сразу на нужный уровень, возможно даже сразу на выход из программы, если не ловить исключения слишком рано
- "Говорящие" имена функций позволяют сразу понять назначение функции и возвращаемый ей результат
Легко заметить, что программа получилась не короче, а, наоборот, длиннее. Но её можно при этом:
- Легче понимать на уровне любой из функций
- Перенастраивать на другой функционал
- Тестировать
По-хорошему тут нужно вообще написать класс, вынести константы и т.д. Код маленький, а работы можно ещё много проделать.
Первым делом необходимо понять, что именно вы хотите:
Оптимизация - ускорение кода путём улучшения алгоритма. Иными словами: уменьшение количества суммарно выполненных операций (при этом не просто удалять лишние строки, а уменьшать количество итераций цикла, например)
"Улучшение" кода - улучшение его читаемости, расширяемости, простоты, увеличение / уменьшение количества абстракций (иногда всё это не возможно сделать одновременно, и необходимо найти баланс, необходимый для конкретного проекта).
Улучшение кода
Начнём с сигнатуры функции:
Функция называется age_is_numeric
, однако делает гораздо больше, чем описано, а именно:
- Запрашивает возраст с пользовательского ввода
- Проверяет, является ли возраст числовым значением
- Проверят, проходит ли возраст необходимые границы
Неописанное поведение в последствии может вызвать неожиданные баги, когда данную функцию будут использовать другие разработчики (или вы забудете).
Так как функции для получение инпута и проверки на число уже существуют, то нам необходимо реализовать только одну функцию: is_adult_age(age: int) -> bool
def is_adult_age(age):
return age >= 18
Тогда мы сможем использовать это вот так вот:
input_age = input("Enter age: ")
def is_adult_age(age):
return age >= 18
if (not input_age.isdigit()):
raise ValueError("Age isn't a digit");
age = int(input_age)
if (not is_adult_age(age)):
raise ValueError("Only adult is allowed")
print("Success!")
При этом мы можем легко поменять например источник возраста, получить его из базы данных, например, или способ вывода ошибки.
Однако
Если выпишите код для какого то проекта, который предполагает расширение в виде большего количества проверок, то код можно расширить в данной области.
Пара примеров:
1.
Предполагаются множественные проверки возраста (утрированно):
# Returns True, when age is validated, otherwise string with error message
def validate_age(age):
if (age < 18):
return "too young"
return True
Что в последствии поможет расширить его, например, в это:
def validate_age(age):
if (age < 18):
return "too young"
if (age > 32):
return "too old"
return True
Планируется добавить полноценный объект пользователя с информацией о нём
def validate_user(user):
if (user.age < 18):
return "User too young"
return true
Что можно расширить в это:
def contains_only(pattern, val):
for s in pattern:
if s in val:
return False
return True
def validate_user(user):
if user.age < 18:
return "User too young"
if not contains_only("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -", user.name):
return "Name can't conain special characters"
Оптимизация
В данном случае, из-за отсутствия циклов скорость алгоритма и так линейна. Оптимизация линейный алгоритмов не имеет смысла, так как скорость современных компьютеров достаточно быстрая, что бы на уходило минимальное количество времени, даже в таких, казалось бы, медленных языках, как python.