我意识到已经有关于是否使用If / Else或Try / Except块的讨论。这样的问题位于这里:更好地尝试一些东西并捕获异常,或者测试是否有可能首先避免异常?
但我想将讨论扩展到嵌套的try/except和嵌套的if/elif/else逻辑块。这是设置...我想编写一个函数,该函数将允许用户提供字符串文字,整数或可迭代值。这是一个高级功能,它将为我编写的其他功能提供一定程度的抽象。我的代码是这样的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23def 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"。)可以安全地假设用户将极有可能永远不会传递字符串列表或字符串元组-非法iter)
这样可以吗?还是最好检查输入的类型并执行if / elif / else(IEE)代码块?您认为IEE代码块会更容易阅读吗?
替代建议:结合使用try / except和IEE怎么办?例如,如果try / except是字符串文字'all',则try / except可能会尝试降低输入,并且IEE将嵌套在except块中以检查替代情况(整数,迭代或非法类型)
而且更笼统地说,如何在不重复编写函数三次并测试每个函数的情况下才能判断哪种方法最快?
还有一个问题是,如果Try / Except平均比If / Elif / Else测试更快,但是我们认为If / Elif / Else具有更好的可读性,那么Try / Except方法应保证快得多以提高可读性窗外还是可读性总是在速度面前占主导地位?还是由编码人员/团队自行决定?
Python建议使用EAFP模型(比权限更容易获得宽恕),因此在这种情况下,使用try-except是可行的pythonic方法。 就我个人而言,我会走非pythonic路线,并使用if isinstance(parameters,collections.Iterable)来划分验证,以避免级联try-excepts。 至于性能,我建议您编写一个简单的版本并使用testit模块进行测试。
有关更多信息,我确实运行了该比较的简化版本,进行了100,000次迭代,发现带isInstance的If / Elif / Else实际上比try / except方法要快。 (尽管我没有使用testit模块。)因此,在这种情况下使用If / Else方法似乎是可读性和效率双赢的。 只是不确定为什么。 尝试/排除方法:100,000循环内1.34000015258789秒If / Elif / Else方法:100,000循环1.18899989128112秒
我认为您的输入函数应该负责验证输入,而不是调用它们的函数。 之后,您可以让高级功能保持高级,并保持try的状态以使用其中之一直到成功:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18def 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__)
感谢您的见解。 它简单,干净,可读并且仍然遵循python的EAFP方法。 对自己过度思考这个问题有些生气。 我倾向于用python做到这一点。 r
没问题! FWIW,我认为您的方向正确。
当我达到return陈述时,我应该离开high_level_function,对吗? 我正在测试我的代码,尽管每个try块都有一个return语句,但看起来我正在遍历所有try块,但我希望它能够成功,但没有成功。 确保我期望的和python做的是同一件事。
如果它通过所有一切,它将引发最终异常,您看到这种情况发生了吗? 否则,它意味着它已按预期返回。
抱歉,我知道了。 是由于缺少int()函数引起的。 因此,它抛出了我想要的AttributeError,但位置错误。 :-/