🏠 Домашнее задание

⚡ Суть задания

Создать класс Student с датой рождения, автоматической нумерацией, валидацией возраста, строковыми представлениями, альтернативным конструктором и фильтрацией по возрасту.

Результат: файл student.py, который можно запустить и увидеть ожидаемый вывод.

📋 Формулировка задания

Исходное задание из практической работы:

  1. Создайте класс Student с именем и датой рождения. Дата передаётся строкой YYYY-MM-DD и сохраняется как datetime.date. Добавьте проверку возраста — студенту должно быть не менее 16 лет.
  2. Каждому студенту автоматически присваивайте уникальный student_id, начиная с 1.
  3. Добавьте строковое представление объекта.
  4. Добавьте метод show_info, который выводит имя, текущий возраст и ID.
  5. Реализуйте классовый метод from_string для создания объекта из строки "Bob, 2001-12-03".
  6. Добавьте метод calculate_age_on для возраста на переданную дату.
  7. Реализуйте статический метод filter_by_min_age для отбора студентов старше заданного возраста.
  8. Проверьте работу класса: создайте студентов разными способами, выведите информацию, отловите ошибку для молодого кандидата, отфильтруйте список.

🔧 Шаг 0. Подготовка окружения

Перед началом работы над любым заданием курса нужно настроить окружение. Эти шаги одинаковы для всех уроков.

📁 Структура репозитория: мы используем один репозиторий для всех практических работ курса. Это удобнее, чем десятки отдельных репозиториев: общий .gitignore, единая история, легко переключаться между уроками.
1

Создайте (или откройте) рабочую папку

В VS Code нажмите Ctrl+K Ctrl+O → выберите или создайте папку python-fundamentals-practice. Это будет корень вашего учебного репозитория.

# Или в терминале VS Code (Ctrl + `):
mkdir python-fundamentals-practice
cd python-fundamentals-practice
2

Инициализируйте Git-репозиторий (один раз)

git init

echo "# Python Fundamentals — Практические работы" > README.md
echo "venv/" > .gitignore
echo "__pycache__/" >> .gitignore
echo "*.pyc" >> .gitignore
echo ".env" >> .gitignore

git add README.md .gitignore
git commit -m "init: базовая структура репозитория"
3

Создайте папку для текущего урока

mkdir -p lesson-69
cd lesson-69
4

Создайте виртуальное окружение (venv)

# Windows
python -m venv venv
venv\Scripts\activate

# Mac / Linux
python3 -m venv venv
source venv/bin/activate

После активации в начале строки терминала появится (venv).

5

Создайте ветку для задания

cd ..
git checkout -b lesson/69-practice-17

# Если настроен удалённый репозиторий:
git push -u origin lesson/69-practice-17

🛠️ Шаги выполнения задания

1

Создайте файл student.py

В папке lesson-69 создайте файл student.py.

2

Реализуйте класс Student

Добавьте атрибут класса current_id, инициализацию с парсингом даты и валидацией, методы __str__, __repr__, show_info, calculate_age, calculate_age_on, @classmethod from_string и @staticmethod filter_by_min_age.

3

Проверьте работу

Создайте несколько объектов, выведите информацию, попробуйте передать некорректную дату и отфильтруйте список.

✅ Полное решение

Ниже приведено полное решение задания. Совет: попробуйте выполнить самостоятельно, прежде чем смотреть ответ.

from datetime import datetime, date


class Student:
    current_id: int = 1
    MIN_AGE: int = 16

    def __init__(self, name: str, birth_date: str) -> None:
        self.birth_date = datetime.strptime(birth_date, "%Y-%m-%d").date()
        if not self.is_valid_birthdate():
            raise ValueError("Student must be at least 16 years old.")

        self.name = name
        self.student_id = Student.current_id
        Student.current_id += 1

    def __str__(self) -> str:
        return f"Student: {self.name}, birth_date: {self.birth_date}, ID: {self.student_id}"

    def __repr__(self) -> str:
        return (
            f"Student(name={self.name!r}, birth_date={self.birth_date!r}, "
            f"student_id={self.student_id!r})"
        )

    def show_info(self) -> None:
        print(
            f"Student:\n\tName: {self.name}\n\tAge: {self.calculate_age()}\n\tID: {self.student_id}"
        )

    def calculate_age(self) -> int:
        today = date.today()
        return self.calculate_age_on(today)

    def calculate_age_on(self, target_date: date) -> int:
        age = target_date.year - self.birth_date.year
        if (target_date.month, target_date.day) < (self.birth_date.month, self.birth_date.day):
            age -= 1
        return age

    def is_valid_birthdate(self) -> bool:
        return self.calculate_age() >= self.MIN_AGE

    @classmethod
    def from_string(cls, data: str) -> "Student":
        name, date_string = map(str.strip, data.split(","))
        return cls(name, date_string)

    @staticmethod
    def filter_by_min_age(students: list["Student"], min_age: int) -> list["Student"]:
        return [s for s in students if s.calculate_age() >= min_age]


# Проверка работы класса
s1 = Student("Alice", "2005-05-10")
s2 = Student.from_string("Bob, 2001-12-03")

print(s1)
s1.show_info()
print(s2)
s2.show_info()

print("Min age 21:")
for student in Student.filter_by_min_age([s1, s2], 21):
    print("\t", student)

try:
    Student("Bill", "2009-05-15")
except ValueError as error:
    print(f"ValueError: {error}")

Ожидаемый вывод (зависит от текущей даты):

Student: Alice, birth_date: 2005-05-10, ID: 1
Student:
	Name: Alice
	Age: 21
	ID: 1
Student: Bob, birth_date: 2001-12-03, ID: 2
Student:
	Name: Bob
	Age: 24
	ID: 2
Min age 21:
	 Student: Bob, birth_date: 2001-12-03, ID: 2
ValueError: Student must be at least 16 years old.

🧪 Как проверить решение

  1. Активируйте venv: venv\Scripts\activate (Windows) или source venv/bin/activate (Mac/Linux).
  2. Запустите файл: python lesson-69/student.py.
  3. Убедитесь, что в терминале нет ошибок и вывод совпадает с ожидаемым.
  4. Попробуйте изменить даты рождения в конце файла и убедитесь, что валидация срабатывает.

🐛 Отладка в VS Code

Если что-то не работает:

  1. Поставьте точку останова (breakpoint) в __init__.
  2. Нажмите F5 или выберите «Run → Start Debugging».
  3. В панели Debug посмотрите значения self.birth_date, self.student_id и Student.current_id.
  4. Проверьте Terminal на наличие traceback — Python показывает номер строки с ошибкой.

💾 Сохранение работы

git add lesson-69/
git commit -m "lesson-69: Student class with datetime, validation and filtering"
git push

💡 Советы и типичные ошибки

  • Убедитесь, что venv активирован перед запуском.
  • Не коммитьте папку venv/ — она указана в .gitignore.
  • Счётчик current_id должен увеличиваться только при успешном создании объекта.
  • Проверяйте возраст с учётом месяца и дня, а не только года.
  • Разделяйте списки студентов вне класса, чтобы избежать мутации общего атрибута.
Проверить по документации: аннотации типов в примере выходят за рамки исходного задания. Подробнее см. typing и PEP 484.