Python 如何装饰:';撤消';通过复制try-except语句中的更改

Python 如何装饰:';撤消';通过复制try-except语句中的更改,python,exception,decorator,Python,Exception,Decorator,我希望在输入异常时,首先通过副本上的设置“撤消”try语句中的更改,并且仅当成功地用该副本覆盖原始副本时。我似乎有一个解决方案,但不知道如何把它变成一个装饰器,使我的代码保持干燥 举例说明: a = 0 try: a = 1 1/0 except: pass print(a) 输出:1(我希望它是0) 用于处理我在此处找到的方法中的异常的装饰器: 上面引用的装饰器如下所示: def handle_exceptions(f): def wrapper(*arg

我希望在输入异常时,首先通过副本上的设置“撤消”try语句中的更改,并且仅当成功地用该副本覆盖原始副本时。我似乎有一个解决方案,但不知道如何把它变成一个装饰器,使我的代码保持干燥

举例说明:

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

print(a)
输出:1(我希望它是0)

用于处理我在此处找到的方法中的异常的装饰器:

上面引用的装饰器如下所示:

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”方法可以保持干净,理想情况如下(或任何最接近的方法):


我希望有一个decorator,@exception\u处理程序,它可以实现与上面包含try/except/else语句的代码片段中相同的行为,以保持我的类方法干净明了。

我认为decorator不是正确的解决方案。 1.不同的方法不会有相同的撤销要求,因此装饰程序必须使用撤销函数作为参数。 2.即使这样做,撤消方法也可能无法访问您在try块中修改的变量


我认为更好的方法是编写一个抽象类(我们称之为
Task
),它有
Run
Undo
方法,但尚未实现。然后,您可以编写一个将此类的对象作为输入的方法,在try块中执行
Run
方法,在except块中执行
Undo
。这样做的好处是类可以包含共享变量,这样
Run
Undo
都可以访问它。

为什么不在赋值之前检查赋值是否有效?这应该比从头开始实现事务要容易得多。我同意-用装饰器实现这一点没有什么好办法(如果你只处理数据结构,你可以先进行深度复制,然后再进行递归复制,但用类是不可行的)。
    @exception_handler
    def add_something(item):
        self.items.append(item)
        1/0