Пета задача
Брой точки, които дава задачата: 5.
Краен срок: 23-и април, 19:00 часа.
Основната идея на задачата е да се напише клас (даже 2), който търси атрибути в йерархия от класове.
Какво представлява търсенето на атрибути?
Ако имаме клас и име на атрибут, то търсенето на атрибут представлява проверка в кой клас от йерархията (родители на дадения) първо се среща дадения атрибут. Обхождането може да стане по два начина—в ширина и в дълбочина.
Пример
Нека разгледаме горния пример, в който А
наследява B
и C
, а B
наследява D
. Ако се опитаме в A
да търсим атрибута x
с търсене в дълбочина ще го намерим в класа D
, а ако го търсим с търсене в ширина ще го намерим в класа C
.
Код, код, код
Сега да пристъпим към конкретното описание на модула, който трябва да се напише.
В модула трябва да присъстват 2 атрибута: BFS
и DFS
, които ще отговарят на двата метода на търсене. Стойностите им нямат значение, стига да са различни и да не се променят.
Основната логика ще стои в класа Resolver
:
__init__(self, cls, method=BFS)
— cls е класът, в който ще търсим атрибути, а method е методът, по който ще ги търсим (виж атрибутитеBFS
иDFS
по-горе)- класът трябва да поддържа оператора . (точка, __getattribute__) като обръщение от типа
obj.attr
, къдетоobj
е от типResolver
, трябва да върне:атрибутът наНяма значение какво е поведението на Resolver при атрибути започващи с долна черта. Подобни тестове няма да има!obj
с имеattr
, акоattr
започва с долна черта (_
)None
, ако атрибутът не е намерен вcls
и неговите родителски класове по зададения метод- обект а атрибути
cls
иvalue
, в които стоят съответно класа, където е намерен атрибута, и стойността на атрибута в този клас
Също така трябва да се напише помощен клас ValueResolver
, чийто конструктор има същата сигнатура, но оператора точка работи по малко по-различен начин. Ако атрибутът е намерен се връща стойността му, а ако не е намерен се хвърля AttributeError
. ValueResolver
трябва да наследява Resolver
.
Забележки
- Не може да сте сигурни от кой тип (стар, нов) са класовете, които ви се дават.
- Ако класовете са от нов тип, то те няма да ползват
__slots__
. - За да проверявате дали клас има определен атрибут ползвайте неговия
__dict__
, защото(has|get)attr
търсят в цялата йерархия. - Родителите на даден клас трябва да се обхождат в реда на появяването им в списъка с родители, който съвпада с реда на елементите в
__bases__
.
Примерни тестове
Подготвили сме ви скриптче, в което има няколко примерни теста. За да го изпълните е достатъчно да имате модул с име p5 съдържаш, това което се искаше от вас. Най-лесно е да си кръстите програмата p5.py
и да я сложите в същата директория, където и p5-sample.py
.
Връзка: p5-sample.py