2014-12-05 54 views
1

我知道'tryelse'不是一个真实的东西,但我的问题是写出这个逻辑的最好方法。鉴于以下示例,foo和bar是可能会中断的函数。在python中编写“try else”的最佳方法是什么?

我想aafoo(),但如果休息,我希望它成为bar(),但如果有一个人违反过,然后设置aa以0作为默认值。

try: 
    aa = foo() 
elsetry: 
    aa = bar() 
except e: 
    aa = 0 

重申我的问题,在python中写出这个逻辑的最好方法是什么?

回答

3

嵌套的方法仍然是最好的:

try: 
    aa = foo() 
except Exception: 
    try: 
     aa = bar() 
    except Exception: 
     aa = 0 

尽管试图用较少的嵌套来做到这一点,上面表达了你想做的事情d读者很清楚。如果你试图嵌套更多,那么写出来就变得很尴尬,现在是时候重新考虑你的方法了。但嵌套两个尝试/除外是好的。

你也可以这样写:

try: 
    aa = foo() 
except Exception: 
    aa = None 

if aa is None: 
    try: 
     aa = bar() 
    except Exception: 
     aa = 0 

但不知何故不(至少对我来说),右看看。在foo()可以返回None作为aa的有效值的情况下也是不正确的。

+2

第二种解决方案很尴尬。它不会减少缩进,也使得只有在'foo'失败时才想尝试'bar'才不那么明显。第一个解决方案+1(又名正确的方法:) – iCodez 2014-12-05 22:31:03

+0

我不打算像你这样有两个以上的破解函数,但出于好奇,如果我有五个或十个不同的易碎函数我想要这个功能? – 2014-12-05 22:34:49

+0

@StevenRogers:您可以将所有函数添加到列表中,遍历列表并通过try/call调用每个函数。一旦第一个函数成功给你一个值,你就会立即跳出循环。 – 2014-12-05 22:37:57

1

我觉得这是应该做的最好的办法是:

try: 
    aa = foo() 
except: 
    try: 
     aa = bar() 
    except: 
     aa = 0 

这是当你没有elif的语句就像在JavaScript中你做了什么:

if if_condition: 
    code 
else: 
    if elif_condition: 
     code 
    else: 
     code 
+0

请不要提倡使用bare'except'。抓住'例外'或更具体的东西。 – roippi 2014-12-05 22:41:16

+0

@roippi:他不主张这一点,他只是从问题中复制它,因为这里的其他答案都是...... – abarnert 2014-12-05 22:43:34

4

如果你有其中任一长链,或替代的动态列表中,您可能需要使用一个for循环:

for func in funcs: 
    try: 
     aa = func() 
     break 
    except: 
     pass 
else: 
    aa = 0 

注意,无论哪种方式,你可能不要't 真的想要一个光秃的except在这里。通常你只希望发现一些特定类型的错误(例如,ValueErrorLookupError),其他任何东西都不应该意味着“默默地尝试下一个错误”,而是“向程序员显示意外出错的东西”。但你知道如何解决这个问题。


你当然可以换行了一个功能,如果你需要反复使用它:

def try_funcs(*funcs, defval=0, ok_exceptions=Exception): 
    for func in funcs: 
     try: 
      return func() 
     except ok_exceptions: # ok_exceptions can also be a tuple of exception classes. 
      pass 
    return defval 

当然,作为在评论中提到的,这的确需要一切你想尝试成为没有参数的函数。如果你想尝试spam(42),那么eggs(beans)如果失败了怎么办?或者甚至不是函数调用,而是其他表达式,如foo[bar]

这是一样的出现各地的Python一般情况下:您使用partial在议论同lambda绑定对于第一种情况,或者写一个包装函数第二:

result = try_funcs(partial(spam, 42), partial(eggs, beans), lambda: foo[bar]) 

但是,如果你只是有一个静态的两个或三个替代品尝试,Simon Visser's simple nested answer是更清晰。


如果你问为什么语言没有你tryelse ......嗯,我知道它拿出蟒思路/ -dev列表和其他地方几十倍,并进行了讨论,所以你可能想要搜索更详细/权威的答案。但我认为可以归结为以下几点:尽管理论上有可能提出一个可能看起来更干净的案例,但每个人所给出的每个示例都可以是现在的样子,或者显然应该被重构,因此没有任何令人信服的理由更改语法,保留新的关键字等。

+0

@mgilson:我只是在添加相同的东西,但名称和解释不同。我保存了你的名字(并且也使用'Exception'而不是'(Exception,)',因为我正要......),因为它更具可读性。谢谢。 – abarnert 2014-12-05 22:45:54

+0

非常好的主意!然而,当函数采用不同的参数时,它更难使用 – 2014-12-05 22:46:50

+0

@PiotrDabkowski:并不“太难”;你只需要使用'partial'(当它真的只是一个函数调用)或者写一个'lambda'函数(当它是一个任意的表达式)时 - 与你需要传递一个nullary可调用函数的_any_情况完全一样,通过Python(例如,Tkinter或Twisted回调)。 – abarnert 2014-12-05 23:13:37

相关问题