嵌套Try/Except或If/Else - 如何判断使用哪一个?
我意识到已经讨论过是否使用If/Else或Try/Except块。这样的问题所在位置:Better to 'try' something and catch the exception or test if its possible first to avoid an exception?嵌套Try/Except或If/Else - 如何判断使用哪一个?
但我想讨论一点点进一步扩大到嵌套try/except
和嵌套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)
在这种情况下,让我们假设我不知道是什么类型的输入的大多数用户都会喜欢(即它同样可能是任何给定的用户将通过其中一个int
,一个iter
,或字符串'all'。但是我们可以安全地假设用户很可能永远不会传递字符串或字符串列表-illegal iter
s)
这是好的做还是我会更好地检查输入类型并执行if/elif/else(IEE)代码块?在您看来,IEE代码块是否会更容易阅读?
备选建议:使用try/except和IEE的组合怎么样?例如,try/except可能尝试降低输入,如果它是字符串文字'all',并且IEE将嵌套在except
块中以检查备选情况(整数或iter或非法类型)
在更一般的情况下,如何在三个不同的时间写入函数并测试每一个函数来判断哪个方法最快?
更进一步的问题是,如果Try/Except平均比If/Elif/Else测试更快,但我们认为If/Elif/Else具有更好的可读性,Try/Except方法应该快多少为了保证将可读性抛出窗外,或者在速度方面总是占优势?还是由编码员/团队决定?
我认为你的输入函数应该负责验证输入,而不是调用它们的函数。在此之后,你可以让高级的功能,保持较高的水平,并保持try
ING使用其中的一个,直到成功:在这种情况下
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__)
感谢您的洞察。它简单,干净,可读,并且仍然遵循EAFP的python方法。过度思考这个问题对我自己很生气。我倾向于用python来做到这一点。 GRRRR。 – boymeetscode
没问题! FWIW,我认为你是在正确的轨道上。 –
当我达到“返回”状态时,我应该离开high_level_function,对吧?我正在测试我的代码,看起来像我正在经历所有的try块,尽管每个try块都有一个return语句,我期望它能成功,但事实并非如此。确保我所期望的和python的做法是一回事。 – boymeetscode
Python的建议EAFP模型(更容易请求原谅比许可),所以使用尝试 - 除了pythonic路要走。就个人而言,我会去非pythonic路线,并使用if isinstance(参数,collections.Iterable)来划分验证,以避免级联try-excepts。至于性能,我会建议您编写一个更简单的版本并使用testit模块进行测试。 –
有关更多信息,我确实运行了比较的简化版本超过100,000次迭代,发现使用isInstance的If/Elif/Else比try/except方法更快。 (尽管我没有使用testit模块。)因此,在这种情况下,使用If/Else方法似乎是可读性和双赢的。只是不知道为什么。 尝试/除法:超过100,000循环的1.34000015258789秒 如果/ Elif/Else方法:1.18899989128112超过100,000循环的秒数 – boymeetscode