使用 contextlib.suppress 代替函数内带有 return 语句的嵌套 try/else

问题描述 投票:0回答:1

我试图通过使用

contextlib.suppress
代替返回变量的函数中的嵌套 try/else 来遵守 flake8 准则。以下是我原来的功能:

def _get_early_stopping_rounds(model, **kwargs) -> int:
    """Returns the number of early stopping rounds."""
    try:
        n_rounds = kwargs["early_stopping_rounds"]
    except Exception:
        try:
            n_rounds = model.get_params()["early_stopping_rounds"]
        except Exception:
            try:
                n_rounds = None
            except Exception:
                pass

    return n_rounds

使用示例:

from xgboost import XGBClassifier

# Define xgb model object
>>> xgb = XGBClassifier(early_stopping_rounds=20)
>>> _get_early_stopping_rounds(xgb)
20

用 contextlib.suppress 替换嵌套的 try/else:

from contextlib import suppress

def _get_early_stopping_rounds(model, **kwargs) -> int:
    """Returns the number of early stopping rounds."""
    with suppress(Exception):
        n_rounds = kwargs["early_stopping_rounds"]
        with suppress(Exception):
            n_rounds = model.get_params()["early_stopping_rounds"]
            with suppress(Exception):
                n_rounds = None
    return n_rounds

使用示例:

>>> _get_early_stopping_rounds(xgb)
UnboundLocalError: local variable 'n_rounds' referenced before assignment

我不确定我是否理解收到的 UnboundLocalError。在返回变量的函数内部使用

contextlib.suppress
的正确方法是什么?

python try-catch suppress error-suppression
1个回答
0
投票

老问题,但我认为值得回答。

您收到 UnboundLocalError ,因为您尝试使用从未定义过的

n_rounds
。它从未被定义,因为定义它的行引发了异常。异常被抑制了,但是导致它的行没有被执行(因为它不能:它遇到了异常),所以在那里分配的变量最终没有被分配。

有两种可能的解决方案:

要么不要使用
suppress()
:

您可以简单地使用正常的

try/except
并定义发生异常时应该发生的情况:

try:
  my_assignment = something["some_key"]
except KeyError:
  my_assignment = "some fallback value"

那么

my_assignment
将始终被定义。

或者提前赋值


my_assignment = None

with contextlib.suppress(KeyError):
  my_assignment = something["some_key"]

那么

my_assignment
将始终存在,至少其值为
None
,即使对
something["some_key"]
的赋值失败。

这个选项可能会让类型检查器和 linter 不高兴,因为他们会看到一个变量被分配了两次而没有在中间使用。我认为这是他们的问题,因为他们没有考虑可能会跳过该行的情况,导致变量永远不会被分配。

© www.soinside.com 2019 - 2024. All rights reserved.