как декоратор: «отменить» изменения в try, кроме оператора путем копирования - PullRequest
0 голосов
/ 13 июня 2019

Я хочу отменить изменения в инструкции try после ввода исключения, сначала установив параметры копии, и только в случае успешной перезаписи оригинала этой копией.Кажется, у меня есть решение, но я не знаю, как превратить его в декоратор, чтобы мой код оставался сухим.

, чтобы проиллюстрировать:

a = 0
try: 
    a = 1
    1/0
except:
    pass

print(a)

output: 1 (и я хочуэто будет 0)

декоратор для обработки исключений в методах, которые я нашел здесь: метод обтекания класса в try /, за исключением использования decorator

декоратор, на который есть ссылки выше, выглядит следующим образом:

def handle_exceptions(f):
    def wrapper(*args, **kw):
        try:
            return f(*args, **kw)
        except Exception as e:
            raise e # or do w/e
    return wrapper

если я использую это:

class A:

    def __init__(self):
        self.items = []

    def add_something(item):
        try:
            self.items.append(item)
            1/0
        except Exception as e:
            raise e

, тогда элемент будет добавлен в список элементов (например, изменение состояния произошло до нажатия на исключение).

Метод 'add_something', который у меня есть в настоящее время, предотвращает это, пытается сначала установить его на копии и, в случае успеха, перезаписывает оригинал:

class A:

    def __init__(self):
        self.items = []

    def add_something(item):
        a_copy = self.items.copy()
        try:
            a_copy.append(item)
            1/0 # fails here, state of self.items remains unchanged
        except Exception as e:
            raise e
        else: # in case no exception is hit, overwrite
            self.items = a_copy

Это работает.Но мне нужно делать это много раз, поэтому я бы предпочел декоратор, который обрабатывает это так, чтобы метод 'add_something' мог оставаться чистым, в идеале следующим образом (или что-либо ближе всего):

    @exception_handler
    def add_something(item):
        self.items.append(item)
        1/0

Я хочу иметь декоратор @exception_handler, который выполняет то же поведение, что и в приведенном выше фрагменте кода, содержащем операторы try / exception / else, чтобы сохранить методы класса чистыми и четкими.

1 Ответ

1 голос
/ 13 июня 2019

Я не думаю, что декоратор - правильное решение здесь.1. Разные методы не будут иметь одинаковых требований отмены, поэтому декоратор должен принять функцию отмены в качестве аргумента.2. Даже если вы это сделаете, метод отмены может не иметь доступа к переменным, которые вы изменили в блоке try.

Я думаю, что лучшим подходом было бы написать абстрактный класс (назовем его Task) который имеет методы Run и Undo, но не реализован.Затем вы можете написать метод, который принимает объект этого класса в качестве входных данных, выполнить метод Run в блоке try и выполнить Undo в блоке exc.Преимущество такого способа состоит в том, что класс может содержать общие переменные, так что и Run, и Undo имеют к нему доступ.

...