1

这是捕获和向被调用者抛出异常的正常方法

def check(a):

    data  = {}

    if not a:
        raise Exception("'a' was bad")

    return data

def doSomething():

    try:
        data = check(None)
    except Exception, e:
        print e

这是另一种选择+我喜欢的一些东西:

  1. 'data' 总是存在的,'check' 函数可以为数据设置一些默认值,然后逻辑包含在函数中并且不必重复。也意味着当发生异常时,开发人员不能犯错误尝试访问数据。(数据可以在'doSomething'函数的最顶部定义+分配一些默认值)
  2. 你不必到处乱用 try/excepts 来弄乱“doSomething”函数

    def check(a):
    
        errors = []
        data = {}
    
        if not a:
            errors.append("'a' was bad")
    
        return data, errors
    
    def doSomething():
    
        data, errors = check(None)
        if errors:
            print errors
    

有什么问题吗?人们的意见是什么?

4

3 回答 3

4

有时第二种方法可能很有用(例如,如果您正在执行一系列相对独立的操作并且只想记录哪些操作失败了)。但是,如果您的目标是防止继续处于不正确的状态(即,不是“在发生异常时尝试访问数据的错误”),那么第二种方式并不好。如果您需要进行检查,您可能希望这样做:

def check(a):
    data  = {}
    if not a:
        raise Exception("'a' was bad")
    return data

def doSomething():
    data = check(None)
    # continue using  data

也就是说,进行检查,如果成功,则继续进行。您不需要使用except. 你应该只使用 try/except 如果你能以某种方式实际处理错误。如果你不能,那么你希望异常继续传播,如果有必要,一直传播并停止程序,因为这将阻止你继续以data无效的方式使用。

此外,如果检查后可以继续,但仍然“犯错误”访问 invalid data,那么你没有做一个很好的检查。检查的重点(如果有的话)应该是确保只要检查不引发异常,您就可以自信地继续进行。你这样做的方式,你基本上做了两次检查:你运行check,然后你检查异常。相反,只需运行检查。如果失败,则引发异常。如果成功,请继续使用您的代码。如果您希望检查区分可恢复和不可恢复的错误并记录不可恢复的错误,那么只需在检查中进行日志记录。

当然,在很多情况下,你可以让它变得更简单:

def doSomething():
    data.blah()
    # use data however you're going to use it

换句话说,只要做你想做的事。如果你做了一些data不起作用的事情,你会得到一个例外。通常没有理由进行单独的显式检查。(当然,检查肯定有正当理由。一个是如果实际操作代价高昂并且可能在后期失败,因此您需要预先检查有效性以避免浪费时间在长时间后失败的操作上计算。另一个原因可能是操作涉及 I/O 或某种并发,并且可能使某些共享资源处于无效状态。)

于 2013-07-13T23:34:34.137 回答
1

几年后,当你再次阅读自己的代码并试图弄清楚你到底想要做什么时,你会为所有这些杂乱无章的 try-excepts 感到高兴,因为它们有助于让错误和错误变得一目了然。什么是数据。

于 2013-07-13T23:28:07.723 回答
1

try/excepts 并不混乱;它们通过指示这段代码可以“预期”异常来增加代码的可读性。如果您将逻辑“ifs”与错误处理“ifs”混合在一起,您的代码可能会失去一些可读性。

此外,如果您知道 'a' 是 None 是您将遇到的唯一一种错误,您可以编写一个 if 并以这种方式处理它;在您给出的这个简单示例中很有意义。

但是,如果发生不同的错误,无论如何都会引发异常!

我不建议将其用作一般编程实践,以避免在任何地方尝试/除外。它承认并标记代码中发生异常的位置。

于 2013-07-13T23:38:13.943 回答