Предизвикателства > International Whores' Day! > Решения > Решението на Илиян Гаврилов

Резултати
1 точки от тестове
0 точки от учител

1 точки общо

7 успешни теста
0 неуспешни теста
Код

 1from abc import ABC, abstractmethod
 2from collections import deque
 3
 4
 5class LimitPolicy(ABC):
 6    @abstractmethod
 7    def validate(self, candidate, current):
 8        pass
 9
10
11class ObjectLimitPolicy(LimitPolicy):
12    def __init__(self, limit):
13        self.__limit = limit
14
15    def validate(self, candidate, current):
16        if len(current) + 1 > self.__limit:
17            raise ValueError(f"Cannot insert item! Object limit [ {self.__limit} ] would be exceeded!")
18
19
20class SizeLimitPolicy(LimitPolicy):
21    def __init__(self, limit):
22        self.__limit = limit
23
24    def validate(self, candidate, current):
25        if sum(len(item) for item in current) + len(candidate) > self.__limit:
26            raise ValueError(f"Cannot insert item! Size limit [ {self.__limit} ] would be exceeded!")
27
28
29class SlotStorage:
30    """ Holds the actual data for one slot on one instance """
31    __slots__ = ("__queue", "__policies")
32
33    def __init__(self, policies):
34        self.__queue = deque()
35        self.__policies = policies
36
37    def __len__(self):
38        return len(self.__queue)
39
40    def __iter__(self):
41        return iter(self.__queue)
42
43    def push(self, item):
44        for policy in self.__policies:
45            policy.validate(item, self.__queue)
46        self.__queue.append(item)
47
48    def pop(self):
49        if self.__queue:
50            self.__queue.popleft()
51
52    def snapshot(self):
53        return tuple(self.__queue)
54
55
56class Slot:
57    """ Connects each instance ot its SlotStorage """
58    __slots__ = ("__policies", "__attr")
59
60    def __init__(self, *, object_limit=None, size_limit=None):
61        candidates = ((object_limit, ObjectLimitPolicy), (size_limit, SizeLimitPolicy))
62        self.__policies = tuple(cls(limit) for limit, cls in candidates if limit is not None)
63        self.__attr = ""
64
65    def __set_name__(self, owner, name):
66        self.__attr = f"_slot_storage_{name}"
67
68    def __get__(self, instance, owner):
69        if instance is None:  # Class access
70            return self
71
72        return self.__storage(instance).snapshot()  # Instance access
73
74    def __set__(self, instance, value):
75        self.__storage(instance).push(value)
76
77    def __delete__(self, instance):
78        self.__storage(instance).pop()
79
80    def __storage(self, instance):
81        return instance.__dict__.setdefault(self.__attr, SlotStorage(self.__policies))

.......
----------------------------------------------------------------------
Ran 7 tests in 0.000s

OK

Дискусия
История
Това решение има само една версия.