【发布时间】:2017-04-05 14:41:14
【问题描述】:
我意识到已经讨论过是否使用 If/Else 或 Try/Except 块。这样的问题位于:Better to 'try' something and catch the exception or test if its possible first to avoid an exception?
但我想将讨论进一步扩展到 nested try/except 和 nested 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” . 但是我们可以安全地假设用户很可能永远不会传递字符串列表或字符串元组-非法iters)
这样做可以吗,还是我最好检查输入的类型并执行 if/elif/else (IEE) 代码块?在您看来,IEE 代码块会更容易阅读吗?
替代建议:结合使用 try/except 和 IEE 怎么样?例如,如果它是字符串文字 'all',try/except 可能会尝试降低输入,并且 IEE 将嵌套在 except 块中以检查替代情况(整数或迭代或非法类型)
更一般地说,如果不编写三个不同的函数并测试每个函数,我如何判断哪种方法最快?
更进一步的问题是,如果 Try/Except 平均比 If/Elif/Else 测试更快,但我们认为 If/Elif/Else 具有更好的可读性,那么 Try/Except 方法应该快多少?保证将可读性抛到窗外,还是在速度面前可读性总是占上风?还是由编码员/团队自行决定?
【问题讨论】:
-
Python 推荐 EAFP 模型(请求宽恕比许可更容易),因此在这种情况下,使用 try-except 将是 Python 的方式。就个人而言,我会走非 Pythonic 路线并使用 if isinstance(parameter, collections.Iterable) 来划分验证,以避免一连串的 try-excepts。至于性能,我建议您编写一个更简单的版本并使用 testit 模块进行测试。
-
为了补充信息,我确实运行了这个比较的简化版本超过 100,000 次迭代,发现带有 isInstance 的 If/Elif/Else 实际上比 try/except 方法更快。 (虽然我没有使用 testit 模块。)所以在这种情况下使用 If/Else 方法似乎是可读性和效率双赢的。只是不知道为什么。 Try/Except 方法:1.34000015258789 秒超过 100,000 次循环 If/Elif/Else 方法:1.18899989128112 秒超过 100,000 次循环
标签: python if-statement try-except