9.5. Самостоятельная работа

Примечание

При выполнении заданий используйте заготовки решений: -> Репозиторий.

Подробнее: см. Цикл выполнения и защиты заданий.

9.5.1. Комплексная задача

№9.5.1

Продолжите решение задачи № 8.5.1.

Используя результаты предыдущего решения, а также заготовку и Листинги 9.5.1-9.5.3:

  • функции сохранения и загрузки перенесите в отдельный модуль;

  • вычисления и фильтры - в отдельный модуль;

  • импортируйте новые модули, скорректируйте main.py;

  • добавьте if __name__ == "__main__" в main.py.

Листинг 9.5.1 - Модуль database.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"""Комплексная задача.

Модуль содержит функции:
- загрузка данных из файла;
- сохранение данных в файл.
"""

import json
import csv


def load_db(filename):
    """Загрузить данные из json-файла 'filename'.

    Функция не обрабатывает исключения.

    Результат: list of dict или возбуждается исключение.

    Сложность: O(1).
    """
    ...


def save_db(db, filename):
    """Сохранить данные 'db' в csv-файл 'filename'.

    Функция не обрабатывает исключения.

    Сложность: O(1).
    """
    ...
Листинг 9.5.2 - Модуль employee.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
"""Комплексная задача.

Модуль содержит функции:
- печать объекта;
- фильтры и вычислительные функции.
"""


def print_employee(item):
    """Вывести объект 'item' на экран со всеми атрибутами.

    Сложность: O(1).
    """
    ...


def employees_filter(db, lang):
    """Вернуть отфильтрованную базу 'db' (список сотрудников), у которых
    в качестве языка программирования имеется 'lang'.

    Аргументы:
        - db (list of dict): база данных;
        - lang (str): язык программирования.

    Результат:
        - (list of dict): отфильтрованная база данных.

    Сложность: O(N).
    """
    ...


def employee_avg_height(db, younger_than):
    """Вернуть средний рост среди сотрудников 'db', у которых
    год рождения не менее 'younger_than'.

    Аргументы:
        - db (list of dict): база данных;
        - younger_than (int): минимальный год рождения.

    Результат:
        - (float): если такие сотрудники есть;
          (None): если таких сотрудников нет.

    Исключения:
        - ValueError: если кол-во найденных сотрудников равно 0.

    Сложность: O(N).
    """
    ...
Листинг 9.5.3 - Модуль main.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""Комплексная задача.

Главный модуль.
"""

import json
import csv
import database
import employee

# Это пример кода, он может быть произвольно усложнен
# в рамках ограничений темы
#
# Требования:
#
# - функции сохранения и загрузки перенесите в отдельный модуль;
# - вычисления и фильтры - в отдельный модуль;
# - импортируйте новые модули, скорректируйте main.py;
# - добавьте if __name__ == "__main__" в main.py.

# Каждый модуль должен иметь наименование, соответствующее
# выбранному варианту


if __name__ == "__main__":
    try:
        db = database.load_db("data.json")

        while True:

            print("\n-----")
            print("Меню")
            print("-----")
            print("1. Список сотрудников.")
            print("2. Фильтр по языку программирования.")
            print("3. Средний рост сотрудников, моложе указанного г.р.")
            print("\nВыберите пункт меню или нажмите ENTER для выхода: ",
                  end="")

            answer = input()

            if answer == "1":
                print("Содержимое базы данных ({}):".format(len(db)))
                for i, item in enumerate(db, start=1):
                    print("{}.".format(i))
                    employee.print_employee(item)

            elif answer == "2":
                lang = input("Введите язык программирования: ")
                # "Нормализация" наименования языка на случай ошибки при вводе
                lang = lang.capitalize()

                res = employee.employees_filter(db, lang)

                if len(res) > 0:
                    print("Список сотрудников со знанием "
                          "языка программирования {} ({}):".
                          format(lang, len(res)))
                    for i, item in enumerate(res, start=1):
                        print("{}.".format(i))
                        employee.print_employee(item)

                    # Сохранение результата в файл
                    try:
                        database.save_db(res, "filter_result.csv")
                        print("Результат поиска сохранен в файл.")
                    except (IOError, csv.Error):
                        print("Не удалось сохранить результат поиска в файл.")
                else:
                    print("Таких сотрудников нет.")

            elif answer == "3":
                try:
                    younger_than = int(
                        input("Введите год рождения сотрудника: "))

                    try:
                        res = employee.employee_avg_height(db, younger_than)
                        print("Средний рост сотрудников, {} г.р. и моложе: "
                              "({:.1f}) см.".
                              format(younger_than, res))
                    except ValueError:
                        print("Таких сотрудников нет.")
                except ValueError:
                    print("Год рождения должен быть целым числом.")

            else:
                break

    except (IOError, json.decoder.JSONDecodeError) as err:
        print("Ошибка при чтении файла с данными:", err)

    except Exception as err:
        print("Произошла ошибка!")
        print("Тип:", type(err))
        print("Описание:", err)


# --------------
# Пример вывода:
#
# -----
# Меню
# -----
# 1. Список сотрудников.
# 2. Фильтр по языку программирования.
# 3. Средний рост сотрудников, моложе указанного г.р.
#
# Выберите пункт меню или нажмите ENTER для выхода: 1
# Содержимое базы данных (3):
# 1.
# Имя: Иванов Иван
# День рождения: 01/12/2000
# Рост (см.): 170
# Вес (кг.): 70.5
# Есть машина: True
# Языки программирования: ['С++', 'Python']
# 2.
# Имя: Сергеев Сергей
# День рождения: 01/06/2001
# Рост (см.): 180
# Вес (кг.): 110.4
# Есть машина: False
# Языки программирования: ['Pascal', 'Delphi']
# 3.
# Имя: Николаева Мария
# День рождения: 14/07/1998
# Рост (см.): 180
# Вес (кг.): 66.9
# Есть машина: True
# Языки программирования: ['C#', 'C++', 'C']
#
# -----
# Меню
# -----
# 1. Список сотрудников.
# 2. Фильтр по языку программирования.
# 3. Средний рост сотрудников, моложе указанного г.р.
#
# Выберите пункт меню или нажмите ENTER для выхода: 2
# Введите язык программирования: Python
# Список сотрудников со знанием языка программирования Python (1):
# 1.
# Имя: Иванов Иван
# День рождения: 01/12/2000
# Рост (см.): 170
# Вес (кг.): 70.5
# Есть машина: True
# Языки программирования: ['С++', 'Python']
# Результат поиска сохранен в файл.
#
# -----
# Меню
# -----
# 1. Список сотрудников.
# 2. Фильтр по языку программирования.
# 3. Средний рост сотрудников, моложе указанного г.р.
#
# Выберите пункт меню или нажмите ENTER для выхода: 3
# Введите год рождения сотрудника: 2000
# Средний рост сотрудников, 2000 г.р. и моложе: (175.0) см.