';最后';Python中If/Elif语句的等效值

';最后';Python中If/Elif语句的等效值,python,finally,Python,Finally,Python的if/else语句是否有一个与try/except/finally语句类似的finally等价物?这将使我们能够简化: if condition1: do stuff clean up elif condition2: do stuff clean up elif condition3: do stuff clean up ... ... 为此: if condition1: do s

Python的
if/else
语句是否有一个与
try/except/finally
语句类似的
finally
等价物?这将使我们能够简化:

 if condition1:
      do stuff
      clean up
 elif condition2:
      do stuff
      clean up
 elif condition3:
      do stuff
      clean up
 ...
 ...
为此:

 if condition1:
      do stuff
 elif condition2:
      do stuff
 elif condition3:
      do stuff
 ...
 ...
 finally:
      clean up
其中
finally
仅在满足条件并运行其“do stuff”后才会被调用?相反,如果不满足任何条件,
最终
代码将不会运行

我不喜欢滔滔不绝地说亵渎神明的话,但我能描述它的最好方式是,在每一段“做事情”的末尾都有一个“GOTO”语句,它最终导致了

本质上,它与
else
语句相反。而
else
仅在不满足其他条件的情况下运行,而只有在满足其他条件的情况下才会运行。

这是否可怕

for _ in range(1):
    if condition1:
        do stuff
        break
    elif condition2:
        do stuff
        break
else:
    finally stuff
这个怎么样

class NoFinally(Exception):
    pass

try:
    if condition1:
        do stuff
        raise NoFinally
    elif condition2:
        do stuff
        raise NoFinally
except NoFinally:
    pass
else:
    finally

老实说,我讨厌这两个

你的逻辑与此类似:

cleanup = True
if condition1:
    do stuff
elif condition2:
    do stuff
elif condition3:
    do stuff
....
else:
    cleanup = False

if cleanup:
    do the cleanup

难看,但这正是你所要求的

完全可以这样做:

def function(x,y,z):
    if condition1:
        blah
    elif condition2:
        blah2
    else:
        return False

    #finally!
    clean up stuff.
在某些方面,不如使用单独的函数那么方便。但是,最好的做法是无论如何不要生成太长的函数。将您的逻辑划分为易于阅读的小函数(通常最多1页长),这使得测试、记录和理解执行流程变得更加容易


需要注意的一点是,
finally
子句在发生异常时不会运行。要做到这一点,您还需要添加
try:
内容。

另一个建议,如果预先计算了条件,它可能适合您

if condition1:
    do stuff
elif condition2:
    do stuff
...
if any([condition1, condition2, ...]):
    clean_up
如果您将条件作为if语句的一部分进行评估,这将是一件痛苦的事情,因为在这种情况下,您必须对
任何
函数进行第二次评估……除非Python比我意识到的更聪明。

如下所示:

from .actions import stuff1, stuff2

actions={condition1: stuff1, condition2: stuff2}
for condition in actions:
    if condition:
        actions[condition]()
        cleanup()
        break

当然,需要注意的是,您的条件键必须是唯一的和可散列的。您可以通过使用不同的数据结构来解决此问题。

mhlester的答案有重复的代码,改进的版本可能如下所示:

class NoCleanUp(Exception):
    pass

try:
    if condition1:
        do stuff
    elif condition2:
        do stuff
    else:
        raise NoCleanUp
except NoCleanUp:
    pass
else:
    cleanup

派对有点晚了,但最近问题一直很活跃

通常我会做一个这样的上下文管理器

class CleanUp(object):

    class Cancel(Exception):
        pass

    def __init__(self, f_cleanup):
        self.f_cleanup = f_cleanup

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):

        cancelled = exception_type and issubclass(exception_type, self.__class__.Cancel)

        if not cancelled:
            self.f_cleanup()

        return not exception_type or cancelled

    def cancel(self):
        raise self.__class__.Cancel
def cleanup():
    print "Doing housekeeping"


with CleanUp(cleanup) as manager:
    if condition1:
        do stuff
    elif condition2:
        do stuff
    else:
        manager.cancel()
然后你可以像这样使用它

class CleanUp(object):

    class Cancel(Exception):
        pass

    def __init__(self, f_cleanup):
        self.f_cleanup = f_cleanup

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception_value, traceback):

        cancelled = exception_type and issubclass(exception_type, self.__class__.Cancel)

        if not cancelled:
            self.f_cleanup()

        return not exception_type or cancelled

    def cancel(self):
        raise self.__class__.Cancel
def cleanup():
    print "Doing housekeeping"


with CleanUp(cleanup) as manager:
    if condition1:
        do stuff
    elif condition2:
        do stuff
    else:
        manager.cancel()
你可以试试看

try:
    if-elif-else stuff
finally:
    cleanup stuff

异常已引发,但清理已完成

实际上未完成。听起来你可以简化你的逻辑。不。。。对于
if/else
附录,没有
finally
:if可能包含一些返回语句,需要在它们之后进行清理。看,我在自己的代码中就有这样的语句,我同意,这非常难看。当我去看时,我很惊讶没有好的方法来美化它。是的,但也许你应该重新思考你的程序的逻辑,因为
if/elif/else
不应该遵循那种结构是的,它们都很实用,但也很难看。我觉得一定有更好的办法!这两种方法仍然存在重复清理代码的问题;在这种情况下,break或raise都会执行与所需行为相反的操作(即在满足任何if分支时运行“finally”代码)。如果满足
else:return False
,则
finally
子句也不会运行。如果使用if/else/finally从外部循环中断,则此构造不起作用。@RolfBly这就是代码的目的:如果只想在满足其中一个条件时运行“finally”块,则不能在条件中包含“else”块,否则最后一个区块将一直运行。@Vincenzoo是的,我知道。也许我应该建议在解释中加入这一点。而且,这是一个很好的转换语句的Python模型,我喜欢这个。“非常枯燥!”DylanYoung Ye,我通常会把这个放在身边,因为我发现这个任务比人们想象的要普遍得多。请记住,除非调用cancel,否则本例将进行清理,这意味着任何类型的异常都会被清除。