【问题标题】:Nested Try/Except or If/Else - How to tell which to use?嵌套的 Try/Except 或 If/Else - 如何判断使用哪个?
【发布时间】:2017-04-05 14:41:14
【问题描述】:

我意识到已经讨论过是否使用 If/Else 或 Try/Except 块。这样的问题位于:Better to 'try' something and catch the exception or test if its possible first to avoid an exception?

但我想将讨论进一步扩展到 nested try/exceptnested if/elif/else 逻辑块。这是设置...我想编写一个函数,允许用户提供字符串文字、整数或可迭代对象。这是一个高级函数,将为我编写的其他函数提供一定程度的抽象。我的代码是这样的:

def high_level_func(parameter = None):
    """
    :param parameter: Can accept the string 'All', a single integer, or an iterable such 
        as a range or a list or tuple of ints.
    """
    try:
        if parameter.lower() == 'all'
        # .lower because str input should be case-insensitive
            return str_all_function(parameter) # Only accepts the 
                    # string 'all' - case insensitive
    except AttributeError:
        # if parameter is an int or iter end up here because those types 
        # don't have .lower() methods
        try:
            for para in parameter:
                try:
                    print(int_input_function(parameter))
                except MyException:
                    raise MyException('An iter of something other than ints was '
                                      'provided and cause this error.')
        except TypeError:
            # parameter must be an int because ints aren't iterable and end up here
            return int_input_function(parameter)

在这种情况下,让我们假设我不知道大多数用户会喜欢哪种类型的输入(即任何给定用户同样可能会传递intiter 或字符串“all” . 但是我们可以安全地假设用户很可能永远不会传递字符串列表或字符串元组-非法iters)

这样做可以吗,还是我最好检查输入的类型并执行 if/elif/else (IEE) 代码块?在您看来,IEE 代码块会更容易阅读吗?

替代建议:结合使用 try/except 和 IEE 怎么样?例如,如果它是字符串文字 'all',try/except 可能会尝试降低输入,并且 IEE 将嵌套在 except 块中以检查替代情况(整数或迭代或非法类型)

更一般地说,如果不编写三个不同的函数并测试每个函数,我如何判断哪种方法最快?

更进一步的问题是,如果 Try/Except 平均比 If/Elif/Else 测试更快,但我们认为 If/Elif/Else 具有更好的可读性,那么 Try/Except 方法应该快多少?保证将可读性抛到窗外,还是在速度面前可读性总是占上风?还是由编码员/团队自行决定?

【问题讨论】:

  • Python 推荐 EAFP 模型(请求宽恕比许可更容易),因此在这种情况下,使用 try-except 将是 Python 的方式。就个人而言,我会走非 Pythonic 路线并使用 if isinstance(parameter, collections.Iterable) 来划分验证,以避免一连串的 try-excepts。至于性能,我建议您编写一个更简单的版本并使用 testit 模块进行测试。
  • 为了补充信息,我确实运行了这个比较的简化版本超过 100,000 次迭代,发现带有 isInstance 的 If/Elif/Else 实际上比 try/except 方法更快。 (虽然我没有使用 testit 模块。)所以在这种情况下使用 If/Else 方法似乎是可读性和效率双赢的。只是不知道为什么。 Try/Except 方法:1.34000015258789 秒超过 100,000 次循环 If/Elif/Else 方法:1.18899989128112 秒超过 100,000 次循环

标签: python if-statement try-except


【解决方案1】:

我认为您的输入函数应该负责验证输入,而不是调用它们的函数。之后,您可以让高级别功能保持高级别,并保持trying 使用其中之一,直到它成功:

def high_level_function(parameter=None):
  try:
    return str_input_function(parameter)
  except ValueError:  # Raised by str_input_function on bad input.
    pass

  try:
    return iter_input_function(parameter)  # MyException now propagates itself.
  except ValueError:  # Raised by iter_input_function on bad input.
    pass

  try:
    return int_input_function(parameter)
  except ValueError:  # Raised by int_input_function on bad input.
    pass

  # This should never be hit:
  raise ValueError("parameter has unsupported type: " + type(parameter).__name__)

【讨论】:

  • 感谢您的洞察力。它简单、干净、易读,并且仍然遵循 python 的 EAFP 方法。对自己过度思考这个问题有点生气。我倾向于用python来做到这一点。 Grrrr。
  • 没问题! FWIW,我认为你是在正确的轨道上。
  • 当我到达return 状态时,我应该离开high_level_function,对吗?我正在测试我的代码,看起来我正在遍历所有的 try 块,尽管每个 try 块都有一个 return 语句,我希望它能够成功,但它没有。确保我的期望和 python 所做的事情是一样的。
  • 如果它通过了所有它会抛出最后一个异常,你看到这种情况发生了吗?否则,说明它已经按预期提前返回了。
  • 对不起,我想通了。是由缺少 int() 函数引起的。 所以它像我想要的那样抛出了一个 AttributeError 但在错误的位置。 :-/
猜你喜欢
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多