我用" revert"写了一堂课。装饰。目的是改变收益率中的类成员,如果发生任何异常,则回复"所有的变化。 :
class A():
def __init__(self):
self.kuku = 'old_value'
@contextmanager
def revertible_transaction(self):
old_self = deepcopy(self)
try:
yield
except Exception as e:
self = old_self
raise e
def change_stuff(self):
with self.revertible_transaction():
self.kuku = 'new_value'
raise Exception
我希望self.kuku仍然是' old_value'在我运行change_stuff()之后,但它的新标准是'代替。
任何想法为什么这不起作用以及如何正确地做到这一点?
答案 0 :(得分:0)
您无法有效地分配给self
;您只是在不修改原始对象的情况下更改本地名称引用的对象。如有必要,您需要显式保存要恢复的对象的状态。
@contextmanager
def revertible_transaction(self):
old_kuku = self.kuku
try:
yield
except Exception:
self.kuku = old_kuku
raise
答案 1 :(得分:0)
self
中的 revertible_transaction
只是一个局部变量。它与self
中的change_stuff
不同,重新绑定它不会改变任何其他内容。即使您传递了引用(例如,通过yield
- 并使用with ... as ...
进行分配,您仍然不会替换调用者对change_stuff()
方法的任何引用实例
因此,您无法像这样替换self
。您需要替换实例属性;你可以通过self.__dict__
词典来获取这些词典,通常是:
@contextmanager
def revertible_transaction(self):
old_state = deepcopy(self.__dict__)
try:
yield
except Exception as e:
self.__dict__ = old_state
raise e
这对使用插槽的类不起作用,但代码可以简单地扩展到然后复制MRO中所有__slots__
类属性中列出的所有名称。