在Python中,需要以相反的顺序清理finally块内的所有操作。
我将用Perl解释这个要求。
sub fun1{
add_1();
verify_1();
add_2();
verify_2();
remove_2();
remove_1();
}
如果verify_2()
抛出异常,则add_1()
保持未清除状态。
这就是我在Perl 中处理清理的方式
sub fun1{
@cleanUpActions = ();
try {
add_1();
push (@cleanUpActions, sub {remove_1()} );
verify_1();
add_2();
push (@cleanUpActions, sub {remove_2()} );
verify_2();
remove_2();
pop @cleanUpActions;
remove_1();
pop @cleanUpActions;
} catch {
BaseException->throw("")
} finally{
foreach my $action (reverse @cleanUps){
&$action;
}
}
}
在Python中尝试了相同的逻辑。
def r2():
remove_2()
def r1():
remove_1()
clean_list = []
def fun1():
try:
add_1()
clean_list.append(r1)
verify_1()
add_2()
clean_list.append(r2)
verify_2()
remove_2();
clean_list.pop()
remove_1();
clean_list.pop()
except:
raise Exception
finally:
clean_list.reverse()
for func in clean_list:
func()
上面的Python代码是有效的,但我不需要它。我不想写单独的def,而是想把函数块作为匿名函数添加到列表中,就像我在Perl中可以做的那样。Python Lambda只接受表达式,不支持多行体。
有没有其他有效的方法来处理Python中的此类清理操作。
匿名子类被称为"lambdas";在Python中。
add_1()
clean_list.append(lambda: remove_1())
verify_1()
也就是说,您可以使用不带()
的函数的名称作为函数指针。
>>> def f():
... print("foo")
...
>>> x = f
>>> x()
foo
所以你只需要
add_1()
clean_list.append(remove_1)
verify_1()
还要注意,您可以在函数内部使用def
,从而可以创建多语句清理函数。
add_1()
def r1():
remove_1()
clean_list.append(r1)
verify_1()