1import re
2
3
4class Kid(type):
5 def __new__(cls, name, bases, attr_dict):
6 if "__call__" not in attr_dict:
7 raise NotImplementedError("not implemented")
8 # test for raising errors
9 for name, value in attr_dict.items():
10 if callable(value) and name[0] != "_":
11 attr_dict[name] = Kid._has_been_naughty(value)
12 return type.__new__(cls, name, bases, attr_dict)
13
14 def __call__(cls, *args, **kwargs):
15 # add every existing kid to Santa's list
16 instance = super().__call__(*args, **kwargs)
17 Santa.add_kid(instance)
18 return instance
19
20 @staticmethod
21 def _has_been_naughty(public_method):
22 def wrapper(self, *args, **kwargs):
23 try:
24 public_method(self, *args, **kwargs)
25 except Exception as exc:
26 Santa.set_naughty(self)
27 raise exc
28 return wrapper
29
30
31class Santa:
32 _instance = None
33 naughty_or_nice_list ={}
34 # a dict where the kid is the key and the value is a dict with the info ab the kid
35 most_wanted = {}
36 lost_the_magic = False
37
38 def __new__(cls):
39 if cls._instance is None:
40 cls._instance = super().__new__(cls)
41 return cls._instance
42
43 @classmethod
44 def add_kid(cls, kid):
45 cls.naughty_or_nice_list[kid] = {"wish": None, "age": 0, "naughty": False}
46
47 @classmethod
48 def set_naughty(cls, kid):
49 cls.naughty_or_nice_list[kid]["naughty"] = True
50
51 def _extract_wish(self, message):
52 return re.search(r"['\"]([a-zA-Z0-9\s]+)['\"]", message).group(1)
53
54 def _extract_kID(self, message):
55 return re.search(r"^\s*(\d+)\s*$", message, re.MULTILINE).group(1)
56
57 def __set_wish(self, kid, wish):
58 if kid in self.naughty_or_nice_list:
59 self.naughty_or_nice_list[kid]["wish"] = wish
60 else:
61 raise ValueError("Unexisting kid is trying to contact Santa")
62
63 def __call__(self, kid, message):
64 wish = self._extract_wish(message)
65 self.__set_wish(kid, wish)
66 self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1
67 self.lost_the_magic = False
68
69
70 def __matmul__(self, message):
71 wish = self._extract_wish(message)
72 kID = self._extract_kID(message)
73 for current_kid in self.naughty_or_nice_list:
74 if int(id(current_kid)) == int(kID):
75 self.__set_wish(current_kid, wish)
76 break
77 self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1
78 self.lost_the_magic = False
79
80 def __iter__(self):
81 for kid, info in self.naughty_or_nice_list.items():
82 if info["wish"]:
83 yield info["wish"]
84
85 def __get_most_wanted(self):
86 most_wished = None
87 most_rep = 0
88 for wish, rep in self.most_wanted.items():
89 if rep > most_rep:
90 most_wished = wish
91 most_rep = rep
92 return most_wished
93
94 def __null_all_wishes(self):
95 for kid in self.naughty_or_nice_list:
96 self.naughty_or_nice_list[kid]["wish"] = None
97
98 def xmas(self):
99 if self.lost_the_magic:
100 print("No magic")
101 return
102 for kid, info in self.naughty_or_nice_list.items():
103 if info["age"] > 5:
104 continue
105 info["age"] += 1
106 if info["naughty"]:
107 kid("coal")
108 continue
109 gift = info["wish"] if info["wish"] else self.__get_most_wanted()
110 kid(gift)
111 self.lost_the_magic = True
112 self.__null_all_wishes()
.......F.......F.FF
Stdout:
No magic
No magic
No magic
No magic
.
======================================================================
FAIL: test_santa_gift_order (test.TestSanta.test_santa_gift_order)
Test ordering of the Santa iterator.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 260, in test_santa_gift_order
self.assertEqual(list(self.santa), ["toy2v2", "toy3", "toy1"])
AssertionError: Lists differ: ['toy1', 'toy2v2', 'toy3'] != ['toy2v2', 'toy3', 'toy1']
First differing element 0:
'toy1'
'toy2v2'
- ['toy1', 'toy2v2', 'toy3']
+ ['toy2v2', 'toy3', 'toy1']
======================================================================
FAIL: test_xmass_no_wishes_but_naughty_kids (test.TestSanta.test_xmass_no_wishes_but_naughty_kids)
Test a Christmas with no wishes, but naughty kids present.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 163, in test_xmass_no_wishes_but_naughty_kids
self.assertEqual(kid1.SECRET_PRESENT, None)
AssertionError: 'coal' != None
======================================================================
FAIL: test_xmass_public_with_no_error (test.TestSanta.test_xmass_public_with_no_error)
Test a Christmas with not-so-naughty kids.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 246, in test_xmass_public_with_no_error
self.assertEqual(kid1.public_without_error(), 42)
AssertionError: None != 42
======================================================================
FAIL: test_xmass_years_5_and_over (test.TestSanta.test_xmass_years_5_and_over)
Test with passing years with kid aged 5 and over.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 213, in test_xmass_years_5_and_over
self.assertEqual(kid1.SECRET_PRESENT, None)
AssertionError: 'toy' != None
Stdout:
No magic
No magic
No magic
No magic
----------------------------------------------------------------------
Ran 20 tests in 0.077s
FAILED (failures=4)
Виктор Бечев
20.12.2024 11:26Беше ми любопитно дали има разлика - минава ти един тест повече. Да знаеш, просто. :smile:
|
Габриела Николова
19.12.2024 20:22```
#final revised version with corrections
import re
class Kid(type):
def __new__(cls, name, bases, attr_dict):
if "__call__" not in attr_dict:
raise NotImplementedError("not implemented")
# test for raising errors
for name, value in attr_dict.items():
if callable(value) and name[0] != "_":
attr_dict[name] = Kid._has_been_naughty(value)
return type.__new__(cls, name, bases, attr_dict)
def __call__(cls, *args, **kwargs):
# add every existing kid to Santa's list
instance = super().__call__(*args, **kwargs)
Santa.add_kid(instance)
return instance
@staticmethod
def _has_been_naughty(public_method):
def wrapper(self, *args, **kwargs):
try:
public_method(self, *args, **kwargs)
except Exception as exc:
Santa.set_naughty(self)
raise exc
return wrapper
class Santa:
_instance = None
naughty_or_nice_list ={}
# a dict where the kid is the key and the value is a dict with the info ab the kid
most_wanted = {}
lost_the_magic = False
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
@classmethod
def add_kid(cls, kid):
cls.naughty_or_nice_list[kid] = {"wish": None, "age": 1, "naughty": False}
@classmethod
def set_naughty(cls, kid):
cls.naughty_or_nice_list[kid]["naughty"] = True
def _extract_wish(self, message):
return re.search(r"['\"]([a-zA-Z0-9\s]+)['\"]", message).group(1)
def _extract_kID(self, message):
return re.search(r"^\s*(\d+)\s*$", message, re.MULTILINE).group(1)
def __set_wish(self, kid, wish):
if kid in self.naughty_or_nice_list:
self.naughty_or_nice_list[kid]["wish"] = wish
else:
raise ValueError("Unexisting kid is trying to contact Santa")
def __call__(self, kid, message):
wish = self._extract_wish(message)
self.__set_wish(kid, wish)
self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1
self.lost_the_magic = False
def __matmul__(self, message):
wish = self._extract_wish(message)
kID = self._extract_kID(message)
for current_kid in self.naughty_or_nice_list:
if int(id(current_kid)) == int(kID):
self.__set_wish(current_kid, wish)
break
self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1
self.lost_the_magic = False
def __iter__(self):
for kid, info in self.naughty_or_nice_list.items():
if info["wish"]:
yield info["wish"]
def __get_most_wanted(self):
most_wished = None
most_rep = 0
for wish, rep in self.most_wanted.items():
if rep > most_rep:
most_wished = wish
most_rep = rep
return most_wished
def __null_all_wishes(self):
for kid in self.naughty_or_nice_list:
self.__set_wish(kid, None)
for wish in self.most_wanted:
self.most_wanted[wish] = 0
def xmas(self):
if self.lost_the_magic:
print("lost the magic")
pass
else:
for kid, info in self.naughty_or_nice_list.items():
if info["age"] > 5:
continue
if info["naughty"]:
kid("coal")
info["naughty"] = False # null it for next year
continue
gift = info["wish"] if info["wish"] else self.__get_most_wanted()
kid(gift)
self.lost_the_magic = True
self.__null_all_wishes()
for info in self.naughty_or_nice_list.values():
info["age"] += 1
```
PS много се извинявам за закъснението, пращам го само за да си го имам
|
Габриела Николова
19.12.2024 15:00Да, опитвах се да оправя проблемите, ще пусна тестовете му
|
Виктор Бечев
19.12.2024 13:52Добре, не бях сигурен дали ще предаваш нова версия или не, затова до момента нищо не съм ти казал по темата.
Имаш два проблема, заради които ти гърмят повечето тестове. Препоръчвам ти да пуснеш [тестовете на колегата Павел](https://py-fmi.org/homework/6#comment83) за да си видиш грешките, да не отива на вятъра това, което си свършила.
П.П. Липсва му `unittest.main()` отдолу.
|
Виктор Бечев
16.12.2024 01:14Ммммм, добър въпрос, печелиш точка за него. За в бъдеще е хубаво да ги задаваш публично, за да са полезни и за колегите ти.
Приемаме, че не могат да се създават деца преди първия Дядо Коледа. Как така той не е бил дете като малък - никой не знае. Имаше една сладка книга на Тери Пратчет - Дядо Прас, която имаше интересно тълкувание за измислените ни entity-та, но пак не обяснява как така. Ама за нашето домашно е така.
**Едит:** Това важи за **инстанции** на класовете, които използват `Kid` за метаклас! Не важи за самите класове. Т.е. е напълно валидно да имаме следното:
```
class SomeKidClass(metaclass=Kid):
pass
santa = Santa()
goshko = SomeKidClass()
```
Инстанциите - само след наличието на Дядо Коледа, но класовете - могат и преди това.
|
Габриела Николова
16.12.2024 01:07Исках само да питам дали може да се създава дете преди да се създаде първият santa? Ако да, значи децата трябва да се пазят в Kid, но пък тогава няма само Santa да знае кой какво иска и кой е бил послушен
|
f | 1 | import re | f | 1 | import re |
n | n | 2 | |||
2 | 3 | ||||
3 | class Kid(type): | 4 | class Kid(type): | ||
4 | def __new__(cls, name, bases, attr_dict): | 5 | def __new__(cls, name, bases, attr_dict): | ||
n | n | 6 | if "__call__" not in attr_dict: | ||
7 | raise NotImplementedError("not implemented") | ||||
8 | # test for raising errors | ||||
9 | for name, value in attr_dict.items(): | ||||
10 | if callable(value) and name[0] != "_": | ||||
11 | attr_dict[name] = Kid._has_been_naughty(value) | ||||
5 | return type.__new__(cls, name, bases, attr_dict) | 12 | return type.__new__(cls, name, bases, attr_dict) | ||
n | n | 13 | |||
14 | def __call__(cls, *args, **kwargs): | ||||
15 | # add every existing kid to Santa's list | ||||
16 | instance = super().__call__(*args, **kwargs) | ||||
17 | Santa.add_kid(instance) | ||||
18 | return instance | ||||
19 | |||||
20 | @staticmethod | ||||
21 | def _has_been_naughty(public_method): | ||||
22 | def wrapper(self, *args, **kwargs): | ||||
23 | try: | ||||
24 | public_method(self, *args, **kwargs) | ||||
25 | except Exception as exc: | ||||
26 | Santa.set_naughty(self) | ||||
27 | raise exc | ||||
28 | return wrapper | ||||
29 | |||||
6 | 30 | ||||
7 | class Santa: | 31 | class Santa: | ||
8 | _instance = None | 32 | _instance = None | ||
n | n | 33 | naughty_or_nice_list ={} | ||
9 | naughty_or_nice_list ={"most_wanted":{}} # a dict where the kid is the key and the value is a dict with the info ab the kid | 34 | # a dict where the kid is the key and the value is a dict with the info ab the kid | ||
10 | # a genius ORIGINAL idea ! | 35 | most_wanted = {} | ||
11 | # ------------------------ | 36 | lost_the_magic = False | ||
37 | |||||
12 | def __new__(cls): | 38 | def __new__(cls): | ||
13 | if cls._instance is None: | 39 | if cls._instance is None: | ||
14 | cls._instance = super().__new__(cls) | 40 | cls._instance = super().__new__(cls) | ||
15 | return cls._instance | 41 | return cls._instance | ||
16 | 42 | ||||
n | n | 43 | @classmethod | ||
44 | def add_kid(cls, kid): | ||||
45 | cls.naughty_or_nice_list[kid] = {"wish": None, "age": 0, "naughty": False} | ||||
46 | |||||
47 | @classmethod | ||||
48 | def set_naughty(cls, kid): | ||||
49 | cls.naughty_or_nice_list[kid]["naughty"] = True | ||||
50 | |||||
17 | def _extract_wish(self, message): | 51 | def _extract_wish(self, message): | ||
18 | return re.search(r"['\"]([a-zA-Z0-9\s]+)['\"]", message).group(1) | 52 | return re.search(r"['\"]([a-zA-Z0-9\s]+)['\"]", message).group(1) | ||
19 | 53 | ||||
n | 20 | def _extract_kid(self, message): | n | 54 | def _extract_kID(self, message): |
21 | return re.search(r"^\s*(\d+)\s*$", message, re.MULTILINE).group(1) | 55 | return re.search(r"^\s*(\d+)\s*$", message, re.MULTILINE).group(1) | ||
22 | 56 | ||||
n | 23 | def __call__(self, kid, message): | n | 57 | def __set_wish(self, kid, wish): |
24 | # ako veche e zvynqlo Promenqme jelanieto i ako e nad 5 go ignorirame | ||||
25 | wish = self._extract_wish(message) | ||||
26 | if kid in self.naughty_or_nice_list.keys(): | 58 | if kid in self.naughty_or_nice_list: | ||
27 | self.naughty_or_nice_list[kid]["wish"] = wish | 59 | self.naughty_or_nice_list[kid]["wish"] = wish | ||
28 | else: | 60 | else: | ||
n | 29 | self.naughty_or_nice_list[kid] = {"wish": wish, "age": 0, "naughty": False} | n | 61 | raise ValueError("Unexisting kid is trying to contact Santa") |
30 | # posle proverqvame dali jelanieto e v spisyka most_wanted | 62 | |||
31 | if wish in self.naughty_or_nice_list["most_wanted"].keys(): | 63 | def __call__(self, kid, message): | ||
32 | self.naughty_or_nice_list["most_wanted"][wish] += 1 | 64 | wish = self._extract_wish(message) | ||
33 | else: | 65 | self.__set_wish(kid, wish) | ||
34 | self.naughty_or_nice_list["most_wanted"][wish] = 1 | 66 | self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1 | ||
67 | self.lost_the_magic = False | ||||
68 | |||||
35 | 69 | ||||
36 | def __matmul__(self, message): | 70 | def __matmul__(self, message): | ||
n | 37 | # ako veche e zvynqlo same as above -> moje da se iznese vyv function | n | ||
38 | wish = self._extract_wish(message) | 71 | wish = self._extract_wish(message) | ||
n | 39 | kid = self._extract_kid(message) | n | 72 | kID = self._extract_kID(message) |
40 | if kid in self.naughty_or_nice_list.keys(): | 73 | for current_kid in self.naughty_or_nice_list: | ||
41 | self.naughty_or_nice_list[kid]["wish"] = wish | 74 | if int(id(current_kid)) == int(kID): | ||
42 | else: | 75 | self.__set_wish(current_kid, wish) | ||
43 | self.naughty_or_nice_list[kid] = {"wish": wish, "age": 0, "naughty": False} | 76 | break | ||
44 | 77 | self.most_wanted[wish] = self.most_wanted.get(wish, 0) + 1 | |||
45 | if wish in self.naughty_or_nice_list["most_wanted"].keys(): | 78 | self.lost_the_magic = False | ||
46 | self.naughty_or_nice_list["most_wanted"][wish] += 1 | ||||
47 | else: | ||||
48 | self.naughty_or_nice_list["most_wanted"][wish] = 1 | ||||
49 | # tova moje da se izkara vyv vynshna function | ||||
50 | 79 | ||||
51 | def __iter__(self): | 80 | def __iter__(self): | ||
n | 52 | return iter(self.wishes.values()) | n | 81 | for kid, info in self.naughty_or_nice_list.items(): |
82 | if info["wish"]: | ||||
83 | yield info["wish"] | ||||
84 | |||||
85 | def __get_most_wanted(self): | ||||
86 | most_wished = None | ||||
87 | most_rep = 0 | ||||
88 | for wish, rep in self.most_wanted.items(): | ||||
89 | if rep > most_rep: | ||||
90 | most_wished = wish | ||||
91 | most_rep = rep | ||||
92 | return most_wished | ||||
93 | |||||
94 | def __null_all_wishes(self): | ||||
95 | for kid in self.naughty_or_nice_list: | ||||
96 | self.naughty_or_nice_list[kid]["wish"] = None | ||||
53 | 97 | ||||
54 | def xmas(self): | 98 | def xmas(self): | ||
n | n | 99 | if self.lost_the_magic: | ||
100 | print("No magic") | ||||
101 | return | ||||
55 | for kid, info in self.naughty_or_nice_list.items(): | 102 | for kid, info in self.naughty_or_nice_list.items(): | ||
56 | if info["age"] > 5: | 103 | if info["age"] > 5: | ||
n | 57 | pass # santa go e otsviril | n | 104 | continue |
105 | info["age"] += 1 | ||||
58 | if info["naughty"]: | 106 | if info["naughty"]: | ||
t | 59 | return kid("coal") # TRQBVA DA VRUSHTA KONKRETNO DETE | t | 107 | kid("coal") |
60 | info["age"] += 1 | 108 | continue | ||
61 | 109 | gift = info["wish"] if info["wish"] else self.__get_most_wanted() | |||
62 | 110 | kid(gift) | |||
63 | 111 | self.lost_the_magic = True | |||
64 | # ----------------------------------------------------------------------------------------------------------------- | 112 | self.__null_all_wishes() | ||
65 | # ----------------------------------------------------------------------------------------------------------------- | ||||
66 | # -------------------------------------------- Testing ------------------------------------------------------------ | ||||
67 | # ----------------------------------------------------------------------------------------------------------------- | ||||
68 | # ----------------------------------------------------------------------------------------------------------------- |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|