try语句的可选else子句的预期用途是什么?


当前回答

else块通常可以用来补充出现在每个except块中的功能。

try:
    test_consistency(valuable_data)
except Except1:
    inconsistency_type = 1
except Except2:
    inconsistency_type = 2
except:
    # Something else is wrong
    raise
else:
    inconsistency_type = 0

"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""

在这种情况下,在每个except块中设置inconsistency_type,以便在无错误情况下在else中补充行为。

当然,我将此描述为某一天可能会出现在您自己的代码中的模式。在这个特定的情况下,您只要在try块之前将inconsistency_type设置为0即可。

其他回答

Try-except-else非常适合结合EAFP模式和duck-typing:

try:
  cs = x.cleanupSet
except AttributeError:
  pass
else:
  for v in cs:
    v.cleanup()

您可能认为naïve代码是好的:

try:
  for v in x.cleanupSet:
    v.clenaup()
except AttributeError:
  pass

这是在代码中意外隐藏严重错误的好方法。我在那里输入了清理,但是让我知道的AttributeError正在被吞噬。更糟糕的是,如果我写对了,但清理方法偶尔被传递一个具有错误命名属性的用户类型,导致它在中途无声地失败并留下一个未关闭的文件,会怎样?祝你在调试时好运。

假设您的编程逻辑取决于字典中是否有具有给定键的条目。你可以使用if…来测试dict.get(key)的结果。其他的……或者你可以这样做:

try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val(val)

也许它的用法是:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

也许这对你也有帮助。

如果执行落在try的底部(如果没有异常),else块中的语句将被执行。说实话,我从来没有找到过需要。

然而,处理异常注意到:

使用else子句更好 而不是向try中添加额外的代码 因为它避免意外 捕获非异常 由被保护的代码引发 尝试…除了声明。

因此,如果你有一个方法,例如,抛出一个IOError,你想捕捉它引发的异常,但如果第一个操作成功,你还想做其他事情,而你不想从那个操作中捕获IOError,你可能会写这样的东西:

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
    # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

如果您只是在operation_that_can_throw_ioerror()后面加上另一个other_operation_that_can_throw_ioerror(), except将捕获第二次调用的错误。如果你把它放在整个try块之后,它会一直运行,直到finally之后。else可以让你确定

第二次操作只有在没有例外的情况下才会进行, 它在最后一个块之前运行,并且 它引发的任何ioerror都不会在这里被捕获

使用else样式和可读性是一个重要原因。将可能导致异常的代码放在处理异常的代码附近通常是个好主意。例如,比较这些:

try:
    from EasyDialogs import AskPassword
    # 20 other lines
    getpass = AskPassword
except ImportError:
    getpass = default_getpass

and

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
else:
    # 20 other lines
    getpass = AskPassword

当异常不能提前返回或重新抛出异常时,第二个方法很好。如果可能的话,我会这样写:

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
    return False  # or throw Exception('something more descriptive')

# 20 other lines
getpass = AskPassword

注意:答案从最近发布的副本复制在这里,因此所有这些“AskPassword”的东西。