This simple class allows sub-classes to commit changes to an instance to a history, and rollback to previous states.
1 2 3 4 5 6 7 8 9 10 11 | class Transaction(object):
def __init__(self):
self.__log = []
def _commit(self):
self.__log.append(self.__dict__.copy())
def _rollback(self):
try:
self.__dict__.update(self.__log.pop(-1))
except IndexError:
pass
|
This class could be useful when a programmer needs to implement an undo history for objects which can be interactivly modified by the end-user.
Tags: oop
shallow copy. Unfortunately, dict.copy makes a shallow copy. So this Transaction class will fail in all kinds of cases. Here is an example:
shallow copy. I clicked on 'Add' too early. I wanted to explain more, so here I go again.
Unfortunately, dict.copy makes a shallow copy. So this Transaction class will fail in all kinds of cases. Here is an example:
The output from that:
my bad. I forgot to commit the transactions, that's why it was not working. I'm still trying to figure out if the shallow dict.copy can somehow cause a problem, but until then, I'm changing my opinion. Good recipe!
back with a different example. Simon, I was wrong earlier and I strongly apologize. This recipe looked great to me the first time I looked at it, it's so simple and yet so powerful. On the other hand, instinctively I felt that there must be something wrong here with the shallow copy and that is why I've kept trying to find a hole in your recipe.
I think I've got it now. Here is an example:
And the output is:
But now, here is a solution for the problem. Import the copy module and do a copy.deepcopy(self.__dict__) instead of the self.__dict__.copy(). I owed you that after the mistakes I've made.
Thanks for the feedback. Thanks for the criticism Dan, I'll make those changes now.
DOH! It seems I have lost control of this recipe...
'No recipes found in the Cookbook that belong to you. Please select a cookbook to add a recipe.'
...and cannot make any changes.
honor __getstate__ and __setstate__. An extended version, which honors __getstate__ and __setstate__ could look like this.
Also, I would self.__dict__.clear() before the update.
Submitted an extended version. See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/551788 for an extended version for this.
The story of the evolution from this class can be read at http://www.harald-hoyer.de/linux/pythontransactionclass