我希望在输入异常后,先在副本上进行设置,并且仅在成功用该副本覆盖原始副本的情况下,才能“撤消” try语句中的更改。我似乎有解决方案,但不知道如何将其变成装饰器,因此我的代码保持干燥状态。
说明:
a = 0
try:
a = 1
1/0
except:
pass
print(a)
输出:1(我希望它是0)
我在这里找到的方法中用于处理异常的装饰器:wrapping class method in try / except using 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 / except / else语句的代码段相同,以保持类方法的整洁。
答案 0 :(得分:1)
我认为装饰器不是这里的正确解决方案。 1.不同的方法将没有相同的撤消要求,因此装饰器必须将撤消函数作为参数。 2.即使这样做,撤消方法也可能无法访问您在try块中修改的变量。
我认为一种更好的方法是编写一个抽象类(我们将其称为Task
),该类具有Run
和Undo
方法,但未实现。然后,您可以编写一个将此类对象作为输入的方法,在try块中执行Run
方法,在except块中执行Undo
。这样做的好处是该类可以包含共享变量,以便Run
和Undo
都可以访问它。