当测试变量是否具有值时,是否有一个基本原理来决定使用哪个try或if结构?

例如,有一个函数要么返回一个列表,要么不返回值。我想在处理之前检查一下结果。下面哪个更可取,为什么?

result = function();
if (result):
    for r in result:
        #process items

or

result = function();
try:
    for r in result:
        # Process items
except TypeError:
    pass;

相关讨论:

检查Python中的成员是否存在


当前回答

你的第二个例子是坏的——代码永远不会抛出TypeError异常,因为你可以遍历字符串和列表。遍历空字符串或列表也是有效的——它将执行循环体0次。

其他回答

你经常听到Python鼓励EAFP风格(“请求原谅比请求许可更容易”)而不是LBYL风格(“三思而后行”)。对我来说,这是效率和可读性的问题。

在你的例子中(假设函数不是返回一个列表或空字符串,而是返回一个列表或None),如果你期望99%的时间结果实际上包含一些可迭代的东西,我会使用try/except方法。如果异常真的是异常,那么速度会更快。如果结果为None超过50%的时间,那么使用If可能更好。

为了支持这一点,我们进行了一些测量:

>>> import timeit
>>> timeit.timeit(setup="a=1;b=1", stmt="a/b") # no error checking
0.06379691968322732
>>> timeit.timeit(setup="a=1;b=1", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.0829463709378615
>>> timeit.timeit(setup="a=1;b=0", stmt="try:\n a/b\nexcept ZeroDivisionError:\n pass")
0.5070195056614466
>>> timeit.timeit(setup="a=1;b=1", stmt="if b!=0:\n a/b")
0.11940114974277094
>>> timeit.timeit(setup="a=1;b=0", stmt="if b!=0:\n a/b")
0.051202772912802175

因此,尽管if语句总是要花费你,但设置try/except块几乎是免费的。但是当异常实际发生时,代价要高得多。

道德:

使用try/是完全OK的(并且是“python式的”),除了流控制, 但当异常实际上是异常时,这是有意义的。

来自Python文档:

EAFP 请求原谅比 许可。这个常见的Python编码 风格假设有效的存在 键或属性和捕获 如果假设成立,则例外 假的。这种干净快速的风格是 特点是存在很多 尝试和except语句。的 技术与LBYL对比 许多其他语言共有的样式 如:C。

一般的经验法则是,永远不要使用try/catch或任何异常处理来控制流。即使幕后的迭代是通过引发StopIteration异常来控制的,您仍然应该更喜欢第一个代码片段而不是第二个。

下面哪个更可取,为什么?

在这种情况下,三思而后行更可取。使用异常方法,TypeError可能出现在循环体的任何地方,它会被捕获并丢弃,这不是您想要的,并且会使调试变得棘手。

(我同意Brandon Corfman的观点:为“没有项目”返回None而不是空列表是错误的。这是Java编码员的一个不愉快的习惯,在Python中不应该看到。或Java)。

就性能而言,使用try块的代码通常 不引发异常比每次都使用if语句更快。所以,决定取决于特殊情况的概率。

你的第二个例子是坏的——代码永远不会抛出TypeError异常,因为你可以遍历字符串和列表。遍历空字符串或列表也是有效的——它将执行循环体0次。