举个例子:
def some_method():
errors = []
resp1 = func1(..., errors)
resp2 = func2(..., errors)
if errors:
print(f"Overall errors encountered: {errors}")
else:
print(f"Output={resp1+resp2}")
def func1(..., errors):
# Do some processing
if success:
return response
else:
if param1 != 1:
errors.append("Error occurred in func2")
elif param2 != 1:
errors.append("Error occurred in func2")
if errors:
return
else:
return response
def func1(..., errors):
# Do some processing
if success:
return response
else:
errors.append("Error occurred in func2")
return
我是否应该初始化一个局部变量并返回它,以便我们从被调用的函数 1 和 2 中获取一个元组。然后在
some_method
中我们扩展错误列表。
什么是更Pythonic的方式?通过列表是一种不好的做法吗?在这里它对我有利,因为对于每种方法,错误列表都会作为引用传递,因此原始列表会附加到每个调用的函数中。
编辑:请注意,
errors
参数是一个列表,因为func1
和func2
获取它们检查的多个参数。我们的想法不是一次引发一个异常,而是遍历所有输入,附加到错误列表并一次性引发异常。这将防止一次因多个不正确的值而引发一个错误。请参阅上面更新的func1()
。
明确地将可变对象传递给函数并让函数更改它并没有什么真正糟糕的。缺点是,如果出于任何原因函数分配给传递的对象而不是更改它,这些更改将丢失,因为您只是重新分配本地引用。
我想说,以这种方式传递错误列表并不是不好的做法,这并不是 pythonic。 AFAIK,标准库中没有方法的函数使用该模式,因此它可能会令其他用户感到困惑。不幸的是,除了从被调用者函数抛出自定义异常(包含错误消息)并让调用者处理它之外,我不知道有什么好方法。这种方式将更接近标准库函数的作用。
话虽如此,您可能有充分的理由使用该模式,就我而言,如果我发现它在特定用例中特别有效,我会毫不犹豫地使用它。我只是想告诉你,我不认为它是pythonic。
不要使用
None
作为发生某些未知错误的不透明信号,而是引发异常。
def func1(...):
# Do some processing
if success:
return response
else:
raise Exception("Error occurred in func2")
def func1(...):
# Do some processing
if success:
return response
else:
raise Exception("Error occurred in func2")
然后,some_method
可以catch来自一个或两个调用的异常,以按其认为合适的方式处理或传播。
def some_method():
errors = []
try:
resp1 = func1(...)
except Exception as e1:
errors.append(e1)
try:
resp1 = func2(...)
except Exception as e2:
errors.append(e2)
if errors:
print(f"Overall errors encountered: {errors}")
# raise ExceptionGroup("Errors", errors)
else:
return resp1 + resp2
请注意,必须记录引发异常组的函数,因为捕获异常组内引发的异常可能需要不同的语法。