Форум > Малки задачи за големи програмисти

Малки задачи за големи програмисти

Георги Кунчев
01.11.2024 19:08
Здравейте, Както стана ясно вчера, породено от анкетата за обратна връзка, споделяме набор кратки задачи, с които можете да тренирате. Задачите няма да се оценяват. Няма да ги проверяваме. Не е нужно да споделяте решение. Ако решите да споделите и да потърсите обратна връзка, ще дадем. Ако имате въпроси, питайте и ще кажем. Ако сме допуснали грешка, казвайте - ще я оправим. Ако вие имате задача, която бихте споделили, заповядайте долу в коментарите. Като цяло това е списък от задачи, измислени и решени "на крак", така че не сме се стремили да дефинираме корнър кейсове или стриктно поведение при неочакван вход. Идеята е да ви дадем занимавка, храна за размисъл, нещо, с което да започнете. Чувствайте се свободни да надграждате инструкциите и да модифицирате, ако го намерите за интересно и вълнуващо. Задачите са в следните категории: * Типове данни; * Функции; * Декоратори; * ООП; * Context managers and exceptions. Всяка категория има по три задачи. Във всяка задача има примерно решение, което сме замаскирали, за да не ви дразни периферното зрение. Замаскирането е направно чрез Base64 encoding. Ето примерен код, който показва как можете да енкоуднете, или декоуднете нещо. ``` import base64 def to_base64(text): """Convert text to Base64.""" text_bytes = text.encode('utf-8') b64_bytes = base64.b64encode(text_bytes) return b64_bytes.decode('utf-8') def from_base64(b64_text): """Convert text from Base64.""" b64_bytes = b64_text.encode('utf-8') text_bytes = base64.b64decode(b64_bytes) return text_bytes.decode('utf-8') # Можете да дефинирате стрингове с много редове, ограждайки ги в тройни кавички. CODE = """ def fun(): return "Примерна функция." """ # Това е енкоуднатата версия на горното, за да визуализирам и обратния процес. ENCODED = "CmRlZiBmdW4oKToKICAgIHJldHVybiAi0J/RgNC40LzQtdGA0L3QsCDRhNGD0L3QutGG0LjRjy4iCg==" print(to_base64(CODE)) print(from_base64(ENCODED)) ``` С две думи - взимате енкоуднатата версия от тук, слагате я в `ENCODED` константата по-горе и рънвате. Можете да си закоментирате реда, който принти `to_base64(CODE)`, тъй като той е оставен само за да ви покаже как сме енкоуднали суровия код. Това го споделяме, защото е на Python. Ако не ви се занимава с това, можете да използвате и [това](https://www.base64decode.org/). Надявам се задачите да са полезни и интересни... Ако не са - [Always Look On The Bright Side Of Life](https://www.youtube.com/watch?v=L2Wx230gYJw) ## Типове данни ### Задача 1 Напиши програма, която евалюира потребителски инпут и създава обекти от конкретен тип и конкретна стойност. Принтира репрезентацията на създадения обект. ``` python program.py &lt;&lt;&lt; Въведи тип: &lt;&lt;&lt; int &gt;&gt;&gt; Въведи аргументи: &lt;&lt;&lt; 5 &gt;&gt;&gt; 5 python program.py &gt;&gt;&gt; Въведи тип: &lt;&lt;&lt; str &gt;&gt;&gt; Въведи аргументи: &lt;&lt;&lt; something &gt;&gt;&gt; 'something' python program.py &gt;&gt;&gt; Въведи тип: &lt;&lt;&lt; list[int] &gt;&gt;&gt; Въведи аргументи: &lt;&lt;&lt; 1, 2, 3 &gt;&gt;&gt; [1, 2, 3] ``` Програмата може да използва функцията `input`, за да поиска вход от потребителя. Опитайте наистина да създадете обект и да му принтирате стойността чрез `repr()`, а не просто да сглабяте репрезентацията му ръчно с конкатенация. По-лесно и по-интересно е. Ако искате, се заиграйте с типовете данни и вход, които да поддържате, но ето примерен вход, който да поддържате. ``` int - Цяло число. Така, както е подадено. float - Дробно число. Така, както е подадено. str - Символен низ. Така, както е подаден. list[str] - Списък от стрингове. Очаква вход от елементи, разделени със запетая. Всеки елемент ще стане отделен обект в списъка. Махнете интервалите в началото и в края на стринга, така че вход "1, 2, 3" резултира в "['1', '2', '3']" list[int] - Списък от цели числа. Очаква вход от елементи, разделени със запетая. По-различно от горното, защото трябва да "кастнете" елементите от списъка към цяло число. dict[str] - Речник с ключ(стринг) и стойност(стринг). Очаква вход от елементи, разделени със запетая. Ключът е отделен от стойността с ":". При вход "a:1,b:2" -> "{'a': '1', 'b': '2'}". ``` Примерно решение: ``` CnR5cGVzID0gewogICAgJ2ludCc6IChpbnQsIGxhbWJkYSBhcmc6IGFyZyksCiAgICAnZmxvYXQnOiAoZmxvYXQsIGxhbWJkYSBhcmc6IGFyZyksCiAgICAnc3RyJzogKHN0ciwgbGFtYmRhIGFyZzogYXJnKSwKICAgICdsaXN0W3N0cl0nOiAobGlzdCwgbGFtYmRhIGFyZzogbWFwKHN0ci5zdHJpcCwgYXJnLnNwbGl0KCcsJykpKSwKICAgICdsaXN0W2ludF0nOiAobGlzdCwgbGFtYmRhIGFyZzogbWFwKGludCwgbWFwKHN0ci5zdHJpcCwgYXJnLnNwbGl0KCcsJykpKSksCiAgICAnZGljdFtzdHJdJzogKGRpY3QsIGxhbWJkYSBhcmc6IG1hcChsYW1iZGEgZWw6IHR1cGxlKG1hcChzdHIuc3RyaXAsIGVsLnNwbGl0KCc6JykpKSwgYXJnLnNwbGl0KCcsJykpKQp9CgppbnB1dF90eXBlID0gaW5wdXQoJ9CS0YrQstC10LTQuCDRgtC40L86ICcpCmlucHV0X2FyZ3MgPSBpbnB1dCgn0JLRitCy0LXQtNC4INCw0YDQs9GD0LzQtdC90YLQuDogJykKCnR5cGVfLCBhcmdzID0gdHlwZXNbaW5wdXRfdHlwZV0KcHJpbnQocmVwcih0eXBlXyhhcmdzKGlucHV0X2FyZ3MpKSkpCg== ``` ### Задача 2 Напиши програма, която очаква потребителски вход на дробно число и извежда репрезентация на речник, който дефинира отделно цялата и дробната му част. ``` python program.py &gt;&gt;&gt; Въведи число: &lt;&lt;&lt; 3.14159 &gt;&gt;&gt; {'whole_part': 3, 'dec_part': 14159} ``` Програмата може да използва функцията `input`, за да поиска вход от потребителя. Опитайте наистина да създадете обект и да му принтирате стойността чрез `repr()`, а не просто да сглабяте репрезентацията му ръчно с конкатенация. По-лесно и по-интересно е. Примерно решение: ``` CmlucHV0X251bWJlciA9IGlucHV0KCfQktGK0LLQtdC00Lgg0YfQuNGB0LvQvjogJykKd2hvbGVfcGFydCwgZGVjX3BhcnQgPSBtYXAoaW50LCBzdHIoaW5wdXRfbnVtYmVyKS5zcGxpdCgnLicpKQpwcmludChkaWN0KHdob2xlX3BhcnQ9d2hvbGVfcGFydCwgZGVjX3BhcnQ9ZGVjX3BhcnQpKQo= ``` ### Задача 3 Напиши програма, която очаква потребителски вход на текст на кирилица и извежда текста преведен на шльокавица. ``` python program.py &gt;&gt;&gt; Въведи текст: &lt;&lt;&lt; Шльокавица. Едно две три. &gt;&gt;&gt; Shljokavitsa. Edno dve tri. ``` Програмата може да използва функцията `input`, за да поиска вход от потребителя. Няма значение как ще си дефинирате превода на самите букви. Идеята е да тренирате Питон, а не да се чудите как е по-правилно да се преведе "ь" например. Опитайте да дефинирате превода само веднъж и само за малки букви, а да напишете логика, която се справя с главните. Не закачайте препинателните знаци. Примерно решение: ``` Cm1hcHBpbmcgPSB7CiAgICAn0LAnOiAnYScsCiAgICAn0LEnOiAnYicsCiAgICAn0LInOiAndicsCiAgICAn0LMnOiAnZycsCiAgICAn0LQnOiAnZCcsCiAgICAn0LUnOiAnZScsCiAgICAn0LYnOiAnemgnLAogICAgJ9C3JzogJ3onLAogICAgJ9C4JzogJ2knLAogICAgJ9C5JzogJ2onLAogICAgJ9C6JzogJ2snLAogICAgJ9C7JzogJ2wnLAogICAgJ9C8JzogJ20nLAogICAgJ9C9JzogJ24nLAogICAgJ9C+JzogJ28nLAogICAgJ9C/JzogJ3AnLAogICAgJ9GAJzogJ3InLAogICAgJ9GBJzogJ3MnLAogICAgJ9GCJzogJ3QnLAogICAgJ9GDJzogJ3UnLAogICAgJ9GEJzogJ2YnLAogICAgJ9GFJzogJ2gnLAogICAgJ9GGJzogJ3RzJywKICAgICfRhyc6ICdjaCcsCiAgICAn0YgnOiAnc2gnLAogICAgJ9GJJzogJ3NodCcsCiAgICAn0YonOiAneScsCiAgICAn0YwnOiAnaicsCiAgICAn0Y4nOiAnaXUnLAogICAgJ9GPJzogJ2lhJwp9CgppbnB1dF90ZXh0ID0gaW5wdXQoJ9CS0YrQstC10LTQuCDRgtC10LrRgdGCOiAnKQoKdHJhbnNsYXRlZF90ZXh0ID0gW10KZm9yIGNoYXIgaW4gaW5wdXRfdGV4dDoKICAgIGlmIGNoYXIgaW4gbWFwcGluZzoKICAgICAgICB0cmFuc2xhdGVkX3RleHQuYXBwZW5kKG1hcHBpbmdbY2hhcl0pCiAgICBlbGlmIGNoYXIubG93ZXIoKSBpbiBtYXBwaW5nOgogICAgICAgIHRyYW5zbGF0ZWRfdGV4dC5hcHBlbmQobWFwcGluZ1tjaGFyLmxvd2VyKCldLmNhcGl0YWxpemUoKSkKICAgIGVsc2U6CiAgICAgICAgdHJhbnNsYXRlZF90ZXh0LmFwcGVuZChjaGFyKQoKcHJpbnQoJycuam9pbih0cmFuc2xhdGVkX3RleHQpKQo= ``` ## Функции ### Задача 1 Напишете функция `spam`, която приема произволен брой позиционни и именувани аргументи, чийто брой обаче съвпада, т.е. ако имате три позиционни, трябва да имате три именувани. Функцията връща речник, чиито ключове са позиционните аргументи, а стойности са имената, използвани за подаване на именувани аргументи. Стойностите зад тези имена се игнорират. ``` print(spam(1, 2, 3, name1=4, name2=5, name3=6)) &gt;&gt;&gt; {1: 'name1', 2: 'name2', 3: 'name3'} ``` Не се притеснявайте от факта, че речникът по принцип е неподреден. От Python 3.6 насам kwargs е подреден речник и редът е гарантиран. Примерно решение: ``` CmRlZiBzcGFtKCphcmdzLCAqKmt3YXJncyk6CiAgICByZXR1cm4gZGljdCh6aXAoYXJncywga3dhcmdzLmtleXMoKSkpCg== ``` ### Задача 2 Напишете функция `spam`, която приема два позиционни параметъра. Един `tuple` от специални стрингове и един `int`. Функцията връща `True`, ако числото, подадено като втори параметър, се намира в някой от затворените интервали, дефинирани от първия. Интервалите смятам за очевидни, но ако не е ясно - питайте. ``` print(spam(('1|3', '2|9', '11|15'), 1)) # True print(spam(('1|3', '2|9', '11|15'), 12)) # True print(spam(('1|3', '2|9', '11|15'), 55)) # False ``` Примерно решение: ``` CmRlZiBzcGFtKGl0ZW1zLCBzdW1fKToKICAgIGZvciBpdGVtIGluIGl0ZW1zOgogICAgICAgIG1pbl8sIG1heF8gPSBpdGVtLnNwbGl0KCd8JykKICAgICAgICBpZiBtaW5fIDw9IHN1bV8gPD0gbWF4XzoKICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgIHJldHVybiBGYWxzZQo= ``` ### Задача 3 Напишете функция `spam`, която приема един позиционен аргумент от тип `list` от `str` и произволен брой именувани аргументи от тип `str`. Функцията връща `True`, ако в списъка, подаден като първи аргумент, има елемент, който съдържа в себе си стринга, подаден като втори аргумент (името на параметъра или стойността му). В противен случай връща `False`. ``` # Няма именувани параметри, така че проверката е ясна. print(spam(['asd', 'qwerty'])) # False # Името "sd" се съдържа в първия елемент от списъка. print(spam(['asd', 'qwerty'], sd=1)) # True # Името "qwerty" се съдържа във втория елемент от списъка. Реално съвпада с него. print(spam(['asd', 'qwerty'], qwerty=1)) # True # Стойността "wer" се съдържа във втория елемент от списъка. print(spam(['asd', 'qwerty'], something='wer')) # True ``` Примерно решение: ``` CmRlZiBzcGFtKGl0ZW1zLCAqKmt3YXJncyk6CiAgICBmb3IgaXRlbSBpbiBpdGVtczoKICAgICAgICBmb3Iga2V5LCB2YWx1ZSBpbiBrd2FyZ3MuaXRlbXMoKToKICAgICAgICAgICAgaWYga2V5IGluIGl0ZW06CiAgICAgICAgICAgICAgICByZXR1cm4gVHJ1ZQogICAgICAgICAgICBpZiBpc2luc3RhbmNlKHZhbHVlLCBzdHIpIGFuZCB2YWx1ZSBpbiBpdGVtOgogICAgICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgIHJldHVybiBGYWxzZQo= ``` ## Декоратори ### Задача 1 Напишете декоратор `spam`, който може да декорира произволна функция, очакваща само именувани аргументи. Декораторът трябва да разменя местата на име/стойност на всички подадени именувани аргументи. За визуализация използвам функцията `helper_fun`. ``` @spam def helper_fun(**kwargs): for key, value in kwargs.items(): print(f"'{key}' passed with a value of '{value}'") helper_fun(to_be_value='to_be_key') ``` Очевидно се очаква стойностите на именуваните аргументи да са стрингове, защото след размяната те ще станат имена, а ако не са, ще се породи грешка, но това е ок. Нека работим само със стрингове. Примерно решение: ``` CmRlZiBzcGFtKGZ1bik6CiAgICBkZWYgZGVjb3JhdGVkKCoqa3dhcmdzKToKICAgICAgICByZXR1cm4gZnVuKCoqZGljdChtYXAocmV2ZXJzZWQsIGt3YXJncy5pdGVtcygpKSkpCiAgICByZXR1cm4gZGVjb3JhdGVkCg== ``` ### Задача 2 Напишете декоратор `spam`, който може да декорира произволна функция. Декораторът очаква като аргумент функция, която да извика непосредствено преди изпълнение на декорираната функция, подавайки пълният набор аргументи, които декорираната функция е получила. Позиционните аргументи се подават директно, а от именуваните използваме само стойностите им и ги подаваме като позиционни. За визуализация използвам функцията `helper_fun`. ``` @spam(print) def helper_fun(*args, **kwargs): pass helper_fun(1, 2, 3, asd=123) &gt;&gt;&gt; 1 2 3 123 &gt;&gt;&gt; helper_fun was called with (1, 2, 3) and {'asd': 123} # Функцията helper_fun не прави нищо, освен да принтира вторият ред от примера по-горе. # Преди това, обаче, декораторът spam е извикал функцията print, # подавайки 4 позиционни параметъра: 1, 2, 3 и 123. # Първият ред от резултата е резултата от извикването на този print. ``` Забележете, че в примера по-горе, от именувания (asd=123) сме използвали само неговата стойност (123) и сме го подали на `print`. Подавайки именуван на `print`, ще получите грешка. Примерно решение: ``` CmRlZiBzcGFtKGluaXRfZnVuKToKICAgIGRlZiBkZWNvcmF0b3IoZnVuKToKICAgICAgICBkZWYgZGVjb3JhdGVkKCphcmdzLCAqKmt3YXJncyk6CiAgICAgICAgICAgIGluaXRfZnVuKCooYXJncyArIHR1cGxlKGt3YXJncy52YWx1ZXMoKSkpKQogICAgICAgICAgICByZXR1cm4gZnVuKCphcmdzLCAqKmt3YXJncykKICAgICAgICByZXR1cm4gZGVjb3JhdGVkCiAgICByZXR1cm4gZGVjb3JhdG9yCg== ``` ### Задача 3 Напишете декоратор `spam`, който може да се прилага върху декоратори. Целта му е при инициализиране на кода (т.е. по време на прилагане на декоратора) да се принтира текст, показваш коя функция с кой декоратор е била декорирана. За визуализация използвам функцията `helper_fun` и декоратора `plus_5_decorator`. Целта на функцията е просто да върне числото 8, а декораторът `plus_5_decorator` добавя 8 към резултата от произволна функция, която е декорирал. ``` @spam def plus_5_decorator(fun): def decorated(*args, **kwargs): return fun(*args, **kwargs) + 5 return decorated @plus_5_decorator def helper_fun(*args, **kwargs): return 8 # При изпълнение на този файл (дори да не извикате helper_fun), се очаква следния изход. # Тъй като декораторът plus_5_decorator е декориран със spam, всеки път, # когато приложите plus_5_decorator някъде, в конзолата ще виждате коя функция # е била декорирана с него. &gt;&gt;&gt; helper_fun has been decorated with plus_5_decorator ``` Примерно решение: ``` CmRlZiBzcGFtKGZ1bik6CiAgICBkZWYgZGVjb3JhdGVkKHRhcmdldCk6CiAgICAgICAgcHJpbnQoZiJ7dGFyZ2V0Ll9fbmFtZV9ffSBoYXMgYmVlbiBkZWNvcmF0ZWQgd2l0aCB7ZnVuLl9fbmFtZV9ffSIpCiAgICAgICAgcmV0dXJuIGZ1bih0YXJnZXQpCiAgICByZXR1cm4gZGVjb3JhdGVkCg== ``` ## ООП ### Задача 1 Напишете миксин `GangstaMixIn`, който може да се прилага на произволен клас, променяйки стринговата репрезентазия на неговите инстанции, като я "украсява" във формат "This is <normal representation>, yo!" ``` class VerboseInt(GangstaMixIn, int): pass class VerboseStr(GangstaMixIn, str): pass print(VerboseInt(10)) # This is 10, yo! print(VerboseStr('Dr. Dre')) # This is Dr. Dre, yo! ``` Примерно решение: ``` CmNsYXNzIEdhbmdzdGFNaXhJbjoKCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gZiJUaGlzIGlzIHtzdXBlcigpLl9fc3RyX18oKX0sIHlvISI== ``` ### Задача 2 Напишете клас `Weird`, чиито инстанции не очакват никакви аргументи при създаване. Инстанциите от класа могат да се извикат, резултат от което е нова инстанция на същия клас. ``` weird = Weird() print(weird) # &lt;__main__.Weird object at 0x000001E1E6938210&gt; print(weird()) # &lt;__main__.Weird object at 0x000001E1E6938250&gt; print(weird()) # &lt;__main__.Weird object at 0x0000021F40BF82D0&gt; ``` Примерно решение: ``` CmNsYXNzIFdlaXJkOgoKICAgIEBjbGFzc21ldGhvZAogICAgZGVmIF9fY2FsbF9fKGNscyk6CiAgICAgICAgcmV0dXJuIGNscygpCg== ``` ### Задача 3 Напишете клас `Storage`, който приема един позиционен параметър от тип `type` и произволен брой именувани параметри. При инициализация класът създава по една инстанция на типа, подаден като позиционен аргумент, за всеки именуван аргумент, подавайки този аргумент на класа подаден като `type`. Инстанции на класа `Storage` трябва да могат да се подават на функцията `len`, а очакваният резултат е броя инстанции, които са създадени при инициализирането (с други думи броя позиционни параметри). Инстанции на класа `Storage` трябва да могат да бъдат индексирани с квадратни скоби (само ще четем, без да пишем с квадратни скоби). Ако в квадратните скоби е подадено име, съвпадащи с името на някой именуван параметър, който е подаден при създаване на инстанцията, връща се създадената инстанция на класа, подаден като позиционен аргумент. Ако не - някаква грешка. Използвам класа `Example` като примерен тип, който `Storage` може да приеме. ``` class Example: def __init__(self, **kwargs): print(f'New example instance created from {kwargs}') self._kwargs = kwargs def __str__(self): return f"Example instance created form {self._kwargs}" storage = Storage(Example, name1=1, name2=2) # New example instance created from {'name1': 1} # New example instance created from {'name2': 2} print(len(storage)) # 2 print(storage['name1']) # Example instance created form {'name1': 1} ``` Примерно решение: ``` CmNsYXNzIFN0b3JhZ2U6CgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGNscywgKiprd2FyZ3MpOgogICAgICAgIHNlbGYuX2luc3RhbmNlcyA9IHt9CiAgICAgICAgZm9yIGtleSwgdmFsdWUgaW4ga3dhcmdzLml0ZW1zKCk6CiAgICAgICAgICAgIHNlbGYuX2luc3RhbmNlc1trZXldID0gY2xzKCoqZGljdChbKGtleSwgdmFsdWUpXSkpCiAgICAKICAgIGRlZiBfX2xlbl9fKHNlbGYpOgogICAgICAgIHJldHVybiBsZW4oc2VsZi5faW5zdGFuY2VzKQogICAgCiAgICBkZWYgX19nZXRpdGVtX18oc2VsZiwgbmFtZSk6CiAgICAgICAgcmV0dXJuIHNlbGYuX2luc3RhbmNlc1tuYW1lXQo= ``` ## Context managers and exceptions ### Задача 1 Напишете клас `ReversedPrint`, чиито инстанции могат да се ползват с `with`. В тялото на `with` с инстанции на този клас очакваме `print` функцията да обръща текст, подаден като аргумент. Извън тялото очакваме функцията да работи нормално. ``` print('Normal print.') # Normal print. with ReversedPrint(): print('.tnirp desreveR') # Reversed print. print('Normal print again.') # Normal print again. ``` За да модифицирате поведението на функцията, можете да използвате `__builtins__.print`, което ви дава достъп да я презапишете. Много лоша практика, но за този дребен пример става, а и всичко ще е само в контекста на нашият мениджър. Разбира се, можете да използвате и друг подход, ако измислите такъв. Примерно решение: ``` CmNsYXNzIFJldmVyc2VkUHJpbnQ6CgogICAgZGVmIF9fZW50ZXJfXyhzZWxmKToKICAgICAgICBzZWxmLl9wcmludCA9IF9fYnVpbHRpbnNfXy5wcmludAogICAgICAgIF9fYnVpbHRpbnNfXy5wcmludCA9IGxhbWJkYSB4OiBzZWxmLl9wcmludCgnJy5qb2luKHJldmVyc2VkKHgpKSkKICAgIAogICAgZGVmIF9fZXhpdF9fKHNlbGYsICpfKToKICAgICAgICBfX2J1aWx0aW5zX18ucHJpbnQgPSBzZWxmLl9wcmludAo= ``` ### Задача 2 Напишете клас `InfiniteContextManager`, чиито инстанции могат да се ползват с `with`. Инстанции на мениджъра ви трябва да могат да се извикват, връщайки обект, който също да поддържа контекст мениджър протокола, и чиито инстанции също да могат да бъдат извиквани, което прави същото, и така до безкрай... При влизане в блока вашата инстанция трябва да връща обект, който да можете да хванете с `with ... as ...:`. Обектът трябва да може да се подава на функцията `len`, като очакваният резултат е броят извиквания, през които сте минали, за да инициализирате контекстния си мениджър. ``` with InfiniteContextManager() as cm: print(len(cm)) # 1 with InfiniteContextManager()()()()() as cm: print(len(cm)) # 5 ``` Примерно решение: ``` CmNsYXNzIEluZmluaXRlQ29udGV4dE1hbmFnZXI6CgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHNlbGYuX2NvdW50ID0gMQoKICAgIGRlZiBfX2NhbGxfXyhzZWxmKToKICAgICAgICBzZWxmLl9jb3VudCArPSAxCiAgICAgICAgcmV0dXJuIHNlbGYKICAgIAogICAgZGVmIF9fbGVuX18oc2VsZik6CiAgICAgICAgcmV0dXJuIHNlbGYuX2NvdW50CgogICAgZGVmIF9fZW50ZXJfXyhzZWxmKToKICAgICAgICByZXR1cm4gc2VsZgogICAgCiAgICBkZWYgX19leGl0X18oc2VsZiwgKl8pOgogICAgICAgIHBhc3MK ``` ### Задача 3 Напишете функция `smart_getattr`, която приема два позиционни аргумента. Един произволен обект и един стринг - име на атрибут, който да търсим в обекта. Функцията се опитва да върне от обекта стойност с подаденото име чрез индексация - `object[name]`. Ако това не стане (има грешка), опитва да върне атрибут с това име - `object.name`. Ако и това не става, хвърля `MegaError`, който вие сами трябва да дефинирате. ``` # Създаване на нов клас, наследяващ речник, и директна инициализация на # инстанция от този клас. Това е само за да е възможно сетването на атрибути # към иснтанцията, което е невъзможно с обикновен речник. mega_dict = type('', (dict, ), {})({'name1': 'val1'}) mega_dict.example = 123 print(smart_getattr(mega_dict, 'name1')) # val1 print(smart_getattr(mega_dict, 'example')) # 123 print(smart_getattr(mega_dict, 'invalid')) # MegaError: Value invalid not found anywhere. ``` Примерно решение: ``` CmNsYXNzIE1lZ2FFcnJvcihFeGNlcHRpb24pOgogICAgcGFzcwoKZGVmIHNtYXJ0X2dldGF0dHIob2JqLCB2YWx1ZSk6CiAgICB0cnk6CiAgICAgICAgcmV0dXJuIG9ialt2YWx1ZV0KICAgIGV4Y2VwdDoKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJldHVybiBnZXRhdHRyKG9iaiwgdmFsdWUpCiAgICAgICAgZXhjZXB0OgogICAgICAgICAgICByYWlzZSBNZWdhRXJyb3IoZidWYWx1ZSB7dmFsdWV9IG5vdCBmb3VuZCBhbnl3aGVyZS4nKQo= ```
Дискусия
Георги Кунчев
10.11.2024 14:05

Благодаря! Оправено е.
Ева Ганчева
10.11.2024 14:00

На задача 1 на ООП на кода с примерното решение накрая е изпуснато == и затова не се декоудва
Виктор Бечев
09.11.2024 14:54

За хората, на които им е било интересно да решават такъв тип задачи - препоръчваме да хвърлите око на задачите, които бяхме написали един за друг за лекцията в четвъртък (07.11). Задачите можете да намерите [тук](https://gist.github.com/vbechev/b6580c0eef70a0bd65d2889a6e212d86) и [тук](https://gist.github.com/gvkunchev/ea1badcf3ad61fef048c2b55347f8855). Бих казал, че последните задачи в двата gist-а са по-лесни от първите, но ultimately все са неща, за които има как да напишете решение с настоящите си знания (дори да не е най-фенси решението, както ние се опитвахме да направим по време на лекцията). Също така, за хората, които имат проблем с PEP8, [поздрав](https://www.youtube.com/watch?v=hgI0p1zf31k&ab_channel=PythonDiscord).