【问题标题】:Python nested try except vs if, elif, elsePython 嵌套 try except vs if, elif, else
【发布时间】:2016-08-30 16:21:29
【问题描述】:

我正在尝试熟悉 Python 的最佳实践。根据 Python 之禅,请求宽恕比请求许可更容易,然而,它也说扁平比嵌套更好,可读性也很重要。您将如何处理:

我有 3 个字典。我有一个键,我想测试键是否在字典中。钥匙只会在其中一个中。根据它所在的字典,我想做不同的事情。

使用try/except,我得出以下解决方案:

try:
    val = dict1[key]
except KeyError:
    try:
        val = dict2[key]
    except KeyError:
        try:
            val = dict3[key]
        except KeyError:
            do_stuff_key_not_found()
        else:
            do_stuff_dict3()
    else:
        do_stuff_dict2()
else:
    do_stuff_dict1()

根据 Python 的 EAFP 原则,这是可行的方法,但它看起来很杂乱,而且可读性不强。

一个更简单的解决方案是:

if key in dict1:
    val = dict1[key]
    do_stuff_dict1()
elif key in dict2:
    val = dict2[key]
    do_stuff_dict2()
elif key in dict3:
    val = dict3[key]
    do_stuff_dict3()
else:
    do_stuff_key_not_found()

处理这种情况的更 Pythonic 的方式是什么?我应该坚持EAFP原则,还是扁平化和可读性更重要?

【问题讨论】:

  • 您的第二个解决方案更易于阅读,但是......为什么将值放在三个不同的字典中,然后不知道将它们放在哪里?为什么要调用三个具有基本相同名称的不同函数而不是一个带参数的函数?代码在做什么?
  • 我确切地知道哪个字典中的内容,但密钥是从输入文件加载的。我可以把所有的东西放在一本字典里,但这似乎是确定要做什么的最优雅的方式。此外,这些函数只是示例,在我的脚本中它们只是几行(非常不同的)代码。

标签: python if-statement try-except


【解决方案1】:

EAFP 在许多情况下是一个合理的格言,但它不是一个可以盲目遵循的格言。在您的示例中,我会说 if/elif 版本没有什么可怕的错误。

两个版本都涉及代码重复,因此如果您要处理大量案例,可能会变得笨拙。解决这个问题的一种方法是将字典/函数对拉到一个列表中,然后遍历该列表:

handlers = [ (dict1, do_stuff_dict1), (dict2, do_stuff_dict2), (dict3, do_stuff_dict3) ]
for whichDict, whichFunc in handlers:
    try:
        val = whichDict[key]
    except KeyError:
        continue
    else:
        whichFunc()
        break
else:
    do_stuff_not_found()

【讨论】:

    【解决方案2】:

    我更喜欢使用 dict.get(key, default_value) 来避免异常处理,例如:

    handlers = [(d1, func_1), (d2, func_2)]
    handlers_found = [(d, func) for d, func in handlers if d.get(key)]
    if handlers_found:
        handlers_found[0][1]()
    else:
        do_stuff_not_found()
    

    get(key[, 默认]) 如果 key 在 字典,否则默认。如果没有给出默认值,则默认为 无,因此此方法永远不会引发 KeyError。 https://docs.python.org/2/library/stdtypes.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 2021-03-15
      • 1970-01-01
      • 2013-11-21
      • 1970-01-01
      • 1970-01-01
      • 2017-05-03
      • 2017-07-03
      相关资源
      最近更新 更多