';最后';Python中If/Elif语句的等效值
Python的';最后';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
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,否则本例将进行清理,这意味着任何类型的异常都会被清除。