Предизвикателства > Безгрешен блок > Решения > Решението на Димитър Фенерски

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

1 точки общо

1 успешни теста
1 неуспешни теста
Код (simplified and corrected version)

 1class ProtectedSection:
 2    def __init__(self, log=(), suppress=()):
 3        self.log = log
 4        self.suppress = suppress
 5        self.exception = None
 6
 7    def __enter__(self):
 8        return self
 9
10    def __exit__(self, exc_type, exc_value, exc_tb):
11        if any([exc_type is exc for exc in self.log]):
12            self.exception = exc_type(exc_value)
13            return True
14        if any([exc_type is exc for exc in self.suppress]):
15            return True

.F
======================================================================
FAIL: test_special_cases (test.TestSolution.test_special_cases)
Test special cases to show you that you missed something.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 128, in test_special_cases
self.assertIsNone(cm.exception)
AssertionError: ZeroDivisionError(ZeroDivisionError('division by zero')) is not None

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

Дискусия
История

f1class ProtectedSection:f1class ProtectedSection:
n2    def __init__(self, log=tuple(), suppress=tuple()):n2    def __init__(self, log=(), suppress=()):

Можеш да инстанцираш празни кортежи и само с ().

3        self.log = [*log]3        self.log = log

Това просто прави self.log на списък, вместо кортеж. В конкретния случай и кортежът ти върши работа, така че можеш направо self.log = log

4        self.suppress = [*suppress]4        self.suppress = suppress
5        self.exception = None
56
6    def __enter__(self):7    def __enter__(self):

Няма нищо лошо в това да дефинираш клас, който да държи изключението, но бих го дефинирал извън ProtectedSection. Не е нужно да го дефинираш при всяко използване на мениджъра си. Тук просто можеш да го инстанцираш веднъж за всяко използване.

Като цяло това е работещ подход, но доста често в работата с контекстни мениджъри ще срещнеш просто return self в тялото на __enter__. Спокойно можеш да закачиш exception атрибута за инстанцията self, без да минаваш през допълнителния клас. Ако мислиш, че така си по гъвкав, мога да се съглася. Просто бих изнесъл дефиницията на класа.

n7        class Silencer:n
8            def __init__(self):
9                self.exception = None
10        self.silencer = Silencer()
11        return self.silencer8        return self
129
13    def __exit__(self, exc_type, exc_value, exc_tb):10    def __exit__(self, exc_type, exc_value, exc_tb):
nn11        if any([exc_type is exc for exc in self.log]):
14        err = exc_type(exc_value)12            self.exception = exc_type(exc_value)
15        if any([isinstance(err, exc) for exc in self.log]):
16            self.silencer.exception = err
17            return True13            return True
n18        if any([isinstance(err, exc) for exc in self.suppress]):n14        if any([exc_type is exc for exc in self.suppress]):
19            return True15            return True
t20        return Nonet

Това е излишно. Така или иначе ще върнеш None, ако нямаш изпълнен return.

Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op