Python 撤消一系列步骤中先前步骤的最佳方法

Python 撤消一系列步骤中先前步骤的最佳方法,python,optimization,design-patterns,coding-style,Python,Optimization,Design Patterns,Coding Style,我试图找到一种更好的方法来执行以下函数。我有一系列需要完成的步骤,如果有任何步骤失败,我需要像这样撤消上一个步骤: try: A = createA() except: return None try: B = createB(A) except: deleteA(A) return None try: C = createC(B) except: deleteB(B) deleteA(A) return None t

我试图找到一种更好的方法来执行以下函数。我有一系列需要完成的步骤,如果有任何步骤失败,我需要像这样撤消上一个步骤:

try:
    A = createA()
except:
    return None

try:
    B = createB(A)
except:
    deleteA(A)
    return None

try:
    C = createC(B)
except:
    deleteB(B)
    deleteA(A)
    return None

try:
    D = createD(C)
except:
    deleteC(C)
    deleteB(B)
    deleteA(A)
    return None

return D
如果可能的话,我不想重复。我该如何改进这一点?是否有一个已知的模式可以遵循


我考虑过的一件事是将
deleteB(
)添加到
deleteC()
,并将
deleteA()
添加到
deleteB()
。这是最好的方法吗?

如果您查看一些设计模式,请检查以下内容:


这可能就是你正在寻找的。此外,it命令还可以执行“撤消”操作。如果下面的问题与您的问题类似,请检查该问题

正如评论所指出的,这就是上下文管理器协议的用途。但是,如果您还不想深入了解什么是相当高级的功能,那么您可以在进行时定义
lambda
匿名函数,以记住要整理的内容

try:
    deleters = []
    A = createA()
    deleters.append( lambda: deleteA(A) )
    B = createB( A)
    deleters.append( lambda: deleteB(B) )
    C = createC( B)
    deleters.append( lambda: deleteC(C) )
    D = createD( C)
    return D
except:
    for d in reversed( deleters):
        d()
    return None

这取决于“撤消”的确切含义。例如,如果A、B、C、D等是任意的用户命令,并且可能有大量的命令以任何顺序排列,那么您可能需要围绕do/undo编写某种抽象

如果A、B、C、D等是需要整理的资源(数据库连接、文件等),那么上下文管理器可能更合适

或者A,B,C,D是其他类型的东西

使用上下文管理器的简短代码:

class A:
    def __enter__(self):
        set things up
        return thing
    def __exit__(self, type, value, traceback):
        tear things down

class B, C and D are similar

def doSomethingThatNeedsToUseD():
    try:
        with A() as a:
        with B() as b:
        with C() as c:
        with D() as d:
            d.doSomething()
    except:
        print("error")

你要找的是所谓的纪念图案。这是GoF设计模式之一:

在不违反封装的情况下,捕获并外部化对象的内部状态,以便以后可以将对象恢复到此状态


可以找到使用python实现它的一种方法。

可以使用的一种模式是上下文管理器,您可以使用上下文管理器,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,用于为您关闭文件的位置。由于Python3.3有
contextlib.ExitStack
与上下文管理器相结合来实现这些功能。一种方法是您可以编写一个undo函数,将所有
deleteX()
函数包装起来,并像
undo([C,B,A])
一样调用它,它解析您的obj以删除并相应地调用
deleteX()
。虽然这可能不是最佳的方法。我不知道python,但一些相当于goto的方法实际上是一个很好的解决方案,尽管它不赞成这种方法。有关一般标准,请参见