Українська
Практика
Приклад 1. Калькулятор ділення
Написати програму, яка читає два дійсні числа, обчислює їх частку та незалежно від результату повідомляє про завершення спроби. Неправильний формат і ділення на нуль повинні мати різні повідомлення. Нескінченності й NaN відхиляються; перевіряється також скінченність результату, адже дуже велика частка може переповнити float.
py
import math
def divide(left: str, right: str) -> float:
a = float(left)
b = float(right)
if not (math.isfinite(a) and math.isfinite(b)):
raise ValueError("потрібні скінченні числа")
result = a / b
if not math.isfinite(result):
raise OverflowError("результат завеликий")
return result
left = input("Ділене: ")
right = input("Дільник: ")
try:
result = divide(left, right)
except ValueError as error:
print("Помилка введення:", error)
except ZeroDivisionError:
print("На нуль ділити не можна")
except OverflowError:
print("Результат не вміщується у float")
else:
print(f"Частка: {result:.4f}")
finally:
print("Спробу завершено")Для введення 7, 2:
Ділене: 7
Дільник: 2
Частка: 3.5000
Спробу завершеноДля введення 7, 0 замість частки буде повідомлення «На нуль ділити не можна». Рядок про завершення залишається. Перевірте також abc, nan, inf, а для переповнення – 1e308, 1e-308. finally тут потрібний для демонстрації порядку виконання; він не перетворює неправильний результат на правильний.
Приклад 2. Розбір календарної дати
Прочитати дату у форматі ДД.ММ.РРРР, перевірити її та вивести ISO-запис. Неправильну дату подати як власний DateInputError зі збереженням початкової причини. У журналі dates.log записати повний traceback; користувачеві показати коротке пояснення.
Метод datetime.strptime розбирає рядок за шаблоном %d.%m.%Y: день, місяць, рік. Він перевіряє календар, але допускає деякі поля без початкового нуля. Додаткова перевірка форми забезпечує саме десять символів і ASCII-цифри. date() повертає лише дату, а isoformat() – запис РРРР-ММ-ДД. Документація: https://docs.python.org/3.14/library/datetime.html#datetime.datetime.strptime.
py
import logging
from datetime import date, datetime
logging.basicConfig(filename="dates.log", encoding="utf-8",
level=logging.INFO,
format="%(levelname)s: %(message)s")
logger = logging.getLogger(__name__)
class DateInputError(Exception):
pass
def parse_date(text: str) -> date:
try:
digits = text[:2] + text[3:5] + text[6:]
if (len(text) != 10 or text[2] != "."
or text[5] != "." or not digits.isascii()
or not digits.isdecimal()):
raise ValueError("неправильна форма запису")
return datetime.strptime(text, "%d.%m.%Y").date()
except ValueError as error:
message = "потрібна чинна дата ДД.ММ.РРРР"
raise DateInputError(message) from error
text = input("Дата: ")
try:
result = parse_date(text)
except DateInputError as error:
logger.exception("Дату не прийнято")
print("Помилка:", error)
else:
print("ISO:", result.isoformat())
logger.info("Дату прийнято")Дата: 29.02.2024
ISO: 2024-02-29Для 29.02.2025:
Дата: 29.02.2025
Помилка: потрібна чинна дата ДД.ММ.РРРРУ журналі буде два пов’язані винятки: календарний ValueError і наш DateInputError. Точний текст стандартної календарної помилки може залежати від версії Python. Умова перевірки починається з довжини: короткий рядок не доходить до індексів 2 та 5 через коротке обчислення or. Зрізи коротких рядків безпечні. Перевірте також порожній рядок, 1.02.2024, 31.04.2026 та 01.01.0001. Для зміни формату змінюють і контракт, і перевірку.
Приклад 3. Налагодження розрахунку стипендії
Використаємо умовне навчальне правило: за середнього бала від 90 включно нараховується 2000 одиниць, від 75 до 90 – 1500, нижче 75 – 0. Це тестові константи задачі. Потрібно знайти помилку в програмі, а потім перевірити обидві межі інтервалів.
Наступний код навмисно неправильний: другий if має власний else і може перезаписати вже обчислене значення.
py
def scholarship(score: int) -> int:
if not 0 <= score <= 100:
raise ValueError("бал поза межами 0..100")
amount = 0
if score >= 90:
amount = 2000
if score >= 75:
amount = 1500
else:
amount = 0
return amount
for score in (74, 75, 89, 90, 100):
print(score, scholarship(score))Фактичний помилковий вивід:
74 0
75 1500
89 1500
90 1500
100 1500Поставте умовну точку зупинки на другому if: score == 90. Перед виконанням рядка amount дорівнює 2000, після виконання його гілки – 1500. Гіпотеза: друга перевірка має бути частиною того самого ланцюжка. Замініть лише другий if на elif. Повторний запуск дає:
74 0
75 1500
89 1500
90 2000
100 2000На захисті поясніть, чому try/except не знаходив би цю помилку: усі операції коректні для типів, а результат суперечить умові. Перевірте також 0, 100, −1 і 101; останні два значення мають спричиняти ValueError і після виправлення.