Предизвикателства > International Whores' Day!


International Whores' Day!
Краен срок: 05.06.2026 22:00
Точки: 1

Бяхме ви обещали нещо в една от новините за курса преди време и, въпреки че нарушихме обещанието да ви водим лекция, пълна с Gen Alpha slang, мислим предходното обещание да го спазим... Било то и с ден закъснение _(всъщност започнахме да пишем предизвикателството вчера, но така се случи)_. Та... Вчера беше [международният ден на курвите](https://en.wikipedia.org/wiki/International_Whores%27_Day). Не сме непременно фенове на Pride Month, но първи и втори юни можем да ги оценим. **Дисклеймър**: Не сме простаци и шовинисти, затова като казваме "курва" имаме предвид "жена, която извършва сексуални актове с други хора срещу заплащане". Нямаме предвид просто жена, която спи с всички наред, това е просто Мария _(да, проверихме дали в курса има Мария, преди да подберем името)_. Можете да прочетете за вчерашния празник в статията по-горе, но накратко - преди 51 години на вчерашната дата е имало бунт на френските проститутки, целящ да привлече вниманието към нечовешките работни условия на най-древната професия. Малко като протестите пред народното, ама обратното - при тях курвите стоят вътре. Бяхме ви подготвили актова фотография, но тъй като това е предизвикателство, а не домашно - няма да качваме картинка. Отвъд това, останалото знаете как работи... #### Задачата Искаме от вас да напишете клас `Slot`, който да може да се използва по следния начин: ``` class Whore: front = Slot(object_limit=2) back = Slot(size_limit=15) top = Slot() ``` ##### Употреба Искаме да можем да вкарваме обекти във всеки `Slot` и те да се запазват в него според следния интерфейс: ``` # С така дефинирания клас Whore от по-горе whore = Whore() whore.front = "something" print(whore.front) # ("something",) whore.front = "something else" print(whore.front) # ("something", "something else") print(whore.back) # () ``` С други думи, при операцията `=` към атрибут, който е слот - предметът от дясната страна бива вкаран в слота. Когато искаме да четем слот - получаваме `tuple` с всички обекти в него. Освен това искаме да дефинираме и изваждане на обекти от слот, чрез ключовата "дума" `del`: ``` # Примерът продължава print(whore.front) # ("something", "something else") del whore.front print(whore.front) # ("something else", ) ``` С други думи, обектите се вадят от слотовете в реда на вкарването им (опашка). А ако се опитаме да извадим обект от празен слот, операцията не трябва да прави нищо и не трябва да хвърля грешка. ##### Лимити Както си личи от първия пример, искаме класът да може да приема опционални аргументи `object_limit` и `size_limit`: - `object_limit` определя колко предмета може да поеме слотът. - `size_limit` определя максималната сума от размерите на всички предмети, които може да поеме слотът. При: - Опит за вкарване на предмет, който би довел до превишаване на лимита за брой предмети; - Опит за вкарване на предмет, който би довел до превишаване на лимита за общ размер на предметите; Искаме да се хвърли грешка: ``` # За припомняне class Whore: front = Slot(object_limit=2) back = Slot(size_limit=15) top = Slot() whore = Whore() whore.front = "something" whore.front = "something else" print(whore.front) # ("something", "something else") whore.front = "a third something" # ValueError: Вие си решавате. print(whore.front) # ("something", "something else") whore.back = "one thing" whore.back = "another, very big thing" # ValueError: Пак вие си решавате. ``` **Уточнение** - "общ размер на предметите" ще рече сумата на дължините на всеки предмет. С други думи, нямате гаранция, че всеки предмет, който се опитаме да вкараме в слота ще бъде низ, но имате гаранция, че всеки предмет, който се опитаме да вкараме, ще има дефинирано поведение за `len(object)`. **Уточнение 2** - и двата лимита са включителни - `<=`. #### Важна уговорка Съдържанието на всеки слот трябва да бъде независимо за всяка инстанция. Пример: ```python first = Whore() second = Whore() first.front = "something" print(first.front) # ("something",) print(second.front) # () ``` #### Въпроси? В коментарите, както винаги.
 1import unittest
 2
 3import solution
 4
 5
 6class TestSanity(unittest.TestCase):
 7    """Check if all data is present."""
 8
 9    def test_data(self):
10        names = ["Slot"]
11        unimported = [name for name in names if name not in dir(solution)]
12        self.assertEqual(unimported, [], "\n\nЕлементите по-горе липсват (проверете си имената)!")
13
14
15if __name__ == "__main__":
16    unittest.main()
 1import unittest
 2
 3from solution import Slot
 4
 5
 6class TestSlot(unittest.TestCase):
 7    def test_empty_slot_returns_empty_tuple_and_assignment_appends(self):
 8        class BasicWhore:
 9            front = Slot()
10
11        worker = BasicWhore()
12        self.assertEqual(worker.front, ())
13        worker.front = "lipstick"
14        worker.front = "phone"
15        self.assertEqual(worker.front, ("lipstick", "phone"))
16        self.assertIsInstance(worker.front, tuple)
17
18    def test_accessing_slot_through_class_returns_descriptor(self):
19        class BasicWhore:
20            front = Slot(object_limit=2)
21
22        self.assertIsInstance(BasicWhore.front, Slot)
23
24    def test_slot_state_is_separate_for_each_instance(self):
25        class BasicWhore:
26            front = Slot()
27
28        first = BasicWhore()
29        second = BasicWhore()
30        first.front = "phone"
31        self.assertEqual(first.front, ("phone",))
32        self.assertEqual(second.front, ())
33
34    def test_different_slots_are_independent(self):
35        class BasicWhore:
36            front = Slot()
37            back = Slot()
38
39        worker = BasicWhore()
40        worker.front = "lipstick"
41        worker.back = "wallet"
42        self.assertEqual(worker.front, ("lipstick",))
43        self.assertEqual(worker.back, ("wallet",))
44
45    def test_delete_removes_oldest_object_and_empty_delete_does_nothing(self):
46        class BasicWhore:
47            front = Slot()
48
49        worker = BasicWhore()
50        del worker.front
51        self.assertEqual(worker.front, ())
52        worker.front = "first"
53        worker.front = "second"
54        worker.front = "third"
55        del worker.front
56        self.assertEqual(worker.front, ("second", "third"))
57        del worker.front
58        del worker.front
59        del worker.front
60        self.assertEqual(worker.front, ())
61
62    def test_object_limit_raises_value_error_and_does_not_mutate_slot(self):
63        class BasicWhore:
64            front = Slot(object_limit=2)
65
66        worker = BasicWhore()
67        worker.front = "first"
68        worker.front = "second"
69        with self.assertRaises(ValueError):
70            worker.front = "third"
71        self.assertEqual(worker.front, ("first", "second"))
72
73    def test_size_limit_uses_len_and_does_not_mutate_slot(self):
74        class BasicWhore:
75            back = Slot(size_limit=5)
76
77        worker = BasicWhore()
78        worker.back = "abc"
79        worker.back = "de"
80        self.assertEqual(worker.back, ("abc", "de"))
81        with self.assertRaises(ValueError):
82            worker.back = "f"
83        self.assertEqual(worker.back, ("abc", "de"))
84
85
86if __name__ == "__main__":
87    unittest.main()
Дискусия