-
Notifications
You must be signed in to change notification settings - Fork 0
Week 6
All tasks of the 6th week.
Open task
Напишем свой аналог листа таблицы Excel. Нужно написать структуру данных Field, в которой доступ к значениям будет осуществляться по ключам. Ключом будет пара "буква" - "число", по аналогии с адресом ячейки в Excel. Возможные форматы обращения к одной и той же "ячейке" данных:
field = Field()
field[1, 'a'] = 25
field['a', 1] = 25
field['a', '1'] = 25
field['1', 'a'] = 25
field['1a'] = 25
field['a1'] = 25
field[1, 'A'] = 25
field['A', 1] = 25
field['A', '1'] = 25
field['1', 'A'] = 25
field['1A'] = 25
field['A1'] = 25В этом списке каждая из этих строк записывает число 25 в ячейку с одним и тем же ключом. Соответственно, по любому из перечисленных ключей должно быть можно получить это число из объекта field. Также должны быть реализованы удаление элемента из структуры (через оператор del) и возможность использования оператора in, например:
(1, 'a') in field: True
"A1" in field: True
('D', '4') in field: FalseТаким образом, выходит, что ключом структуры может быть либо кортеж, либо строка. При попытке получить или записать значение по ключу другого типа должно быть вызвано исключение TypeError. При некорректном значении строки или элементов кортежа нужно вызывать исключение ValueError. Корректными значениями будет считать одиночные буквы и неотрицательное целое число любой длины, т.е. правильные варианты ключей:
А1
А222543
Z89
Неправильные варианты ключей:
AA5
Q2.5
-6F
A
27
GGКроме вышеперчисленного, по объекту должно быть возможно итерироваться. При проходе циклом по объекту должны возвращаться значения, хранящиеся в нём. Порядок возврата значений не важен. Если запрашивается правильный формат ячейки, но в нашем контейнере такого ключа нет, то нужно вернуть None. Например:
field = Field()
print(field["C5"] is None)
> TrueПримечания:
В своем решении этого задания я использовал в качестве ключей хранимого словаря frozenset, а проверку на ValueError реализовал через регулярку. Также рекомендую проверку типов и преобразование поступившего ключа в тот вид, в котором он хранится "под капотом", вынести в отдельный метод и вызывать его из всех описываемых магических методов.
Open task
Доработать класс Field так, чтобы вдобавок к реализованному функционалу появились следующие возможности: field = Field()
- Запись значения в ячейку:
- field.a1 = 25: эквивалентно field['a1'] = 25
- field.A1 = 25: то же самое
- Получение значения:
field['b', 2] = 100
field.b2
field.B2- Удаление значения:
del field.a1, del field.A1 - эквивалентно del field['a', 1]
Таким образом, внутри класса Field методы работы с атрибутами должны работать с тем же объектом, в котором хранятся значения, обрабатываемые в методах setitem, getitem, delitem.
Кроме того, обычное присвоение и получение атрибутов (тех, которые не являются адресом ячейки данных нашего класса) должно производиться по стандартному алгоритму питоновских объектов, т.е. они должны храниться в словаре dict объекта.
field = Field()
field.abcde = 125
print(field.abcde, field.__dict__['abcde'] == 125)
125 TrueДля таких атрибутов также должны быть реализованы получение, присваивание и удаление значения.
Open task
Напишем часть сервиса, который будет помогать бронировать переговорки в офисе. Для этого опишем класс Booking - его объекты будут содержать информацию о конкретном бронировании, а также вспомогательную функцию create_booking, которая будет создавать новый объект бронирования и записывать информацию о бронировании в базу данных бронирований через предоставляемое API. Возвращать она должна будет статус создания бронирования (получилось или переговорка уже занята) и информацию о брони в формате JSON. Ниже - подробности.
Класс Booking должен обладать следующим функционалом.
- конструктор должен принимать три аргумента в следующем порядке: название переговорки, datetime начала брони и datetime конца брони
- внутри конструктора, если datetime конца брони оказался раньше, чем datetime начала, нужно вызвать исключение ValueError
Также у объектов этого класса должны быть следующие поля (рекомендую сделать часть из них в виде проперти):
- room_name
- название переговорки, полученное из конструктора
- start
- datetime начала брони. Должна быть возможность назначить новое время начала уже созданной брони
- end
- datetime конца брони. Должна быть возможность назначить новое время конца уже созданной брони
- duration
- длительность бронирования в минутах (гарантируется, что длительность любой встречи кратна одной минуте, поэтому это должно быть целое число)
- start_date
- дата начала брони в формате YYYY-MM-DD (строка)
- end_date
- дата конца брони в формате YYYY-MM-DD (строка)
- start_time
- время начала брони в формате HH-MM (строка) end_time время конца брони в формате HH-MM (строка)
Функция create_booking должна обладать следующей сигнатурой:
create_booking(room_name, start, end) -> strгде аргументы - это те же аргументы, которые принимает конструктор Booking, а выходная строка - это json определенного формата, который описан чуть ниже по тексту.
Будем считать, что взаимодействие с базой данных у нас уже описано нашим коллегой в соседнем файле api.py. В нем есть уже готовая функция register_booking, которая:
- принимает на вход объект класса Booking
- возвращает True, если бронирование получилось создать
- возвращает False, если мы пытаемся забронировать уже занятую в это время переговорку
- если такой переговорки не существует, вызывается KeyError
Таким образом, в том же файле, что и класс Booking, вам нужно описать фукнцию create_booking, которая:
- обладает сигнатурой create_booking(room_name, start, end) -> str, где аргументы - те же, что и в конструкторе Booking
- в самом начале своей работы выводит на экран текст: Начинаем создание бронирования
- внутри функции создается объект класса Booking, а также вызывается функция register_booking, которая принимает на вход созданный объект. Должны быть обработаны все случаи работы register_booking: True, False и KeyError. Сделать это поможет конструкция try-except
- перед выходом из функции должно выводиться на экран сообщение Заканчиваем создание бронирования. Это должно происходить в любом случае, даже если мы попытались создать бронирование с неверными датами и получили ValueError (см. описание класса Booking). Для этого рекомендую использовать блок finally, в котором описать этот print
Функция должна возвращать json-строку с ответом, в котором будут содержаться следующие поля:
- created: true/false, получилось ли забронировать комнату. Если возникло KeyError, то нужно здесь записать false
- msg: сообщение с пояснениями. Сообщение должно быть одним из следующих: Бронирование создано, Комната занята, Комната не найдена. Сообщение выбирается на основе того, что вернет функция register_booking
- booking
- это бронирование в виде json-строки. Должны содержаться поля: room_name, duration, start_date, end_date, start_time, end_time.
Формат ввода
result = create_booking(
"Вагнер",
datetime.datetime(2022, 9, 1, 14),
datetime.datetime(2022, 9, 1, 15, 15)
)
print(result)Формат вывода
Вывод на экран: Начинаем создание бронирования Заканчиваем создание бронирования Функция возвращает:
{
"created": false,
"msg": "Комната занята",
"booking": {
"room_name": "Вагнер",
"start_date": "2022-09-01",
"start_time": "14:00",
"end_date": "2022-09-01",
"end_time": "15:15",
"duration": 75
}
}Примечания
Пример написания функции create_booking:
from api import register_booking
def create_booking(room_name, start, end):
booking = Booking(........)
try:
result = register_booking(booking)
except ....:
....
return json.dumps(......)