我试图通过使用
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
的正确方法是什么?
老问题,但我认为值得回答。
您收到 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 不高兴,因为他们会看到一个变量被分配了两次而没有在中间使用。我认为这是他们的问题,因为他们没有考虑可能会跳过该行的情况,导致变量永远不会被分配。