当测试变量是否具有值时,是否有一个基本原理来决定使用哪个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中的成员是否存在


当前回答

请忽略我的解决方案,如果我提供的代码是不明显的第一眼,你必须阅读代码样例后的解释。

我可以假设“无返回值”意味着返回值为None吗?如果是,或者如果“no value”是False布尔值,您可以执行以下操作,因为您的代码基本上将“no value”视为“不迭代”:

for r in function() or ():
    # process items

如果function()返回的值不是True,则迭代空元组,即不运行任何迭代。这本质上是LBYL。

其他回答

请忽略我的解决方案,如果我提供的代码是不明显的第一眼,你必须阅读代码样例后的解释。

我可以假设“无返回值”意味着返回值为None吗?如果是,或者如果“no value”是False布尔值,您可以执行以下操作,因为您的代码基本上将“no value”视为“不迭代”:

for r in function() or ():
    # process items

如果function()返回的值不是True,则迭代空元组,即不运行任何迭代。这本质上是LBYL。

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

一般来说,我得到的印象是例外应该为特殊情况保留。如果期望结果永远不为空(但可能为空,例如,如果磁盘崩溃等等),则第二种方法是有意义的。另一方面,如果一个空结果在正常条件下是完全合理的,那么使用If语句测试它更有意义。

我想到了(更常见的)场景:

# keep access counts for different files
file_counts={}
...
# got a filename somehow
if filename not in file_counts:
    file_counts[filename]=0
file_counts[filename]+=1

而不是等价的:

...
try:
    file_counts[filename]+=1
except KeyError:
    file_counts[filename]=1

bobince明智地指出,包装第二种情况也可以捕获循环中的TypeErrors,这不是您想要的。如果你真的想使用try,你可以在循环之前测试它是否可迭代

result = function();
try:
    it = iter(result)
except TypeError:
    pass
else:
    for r in it:
        #process items

如你所见,它相当难看。我不建议这样做,但为了完整起见,应该提到它。

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

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

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