如何让 Python 生成器返回 Nothing 而不是 StopIteration?

我使用生成器在列表中执行搜索,比如下面这个简单的例子:

>>> a = [1,2,3,4]
>>> (i for i, v in enumerate(a) if v == 4).next()
3

(只是为了给这个例子定义一个框架,与上面的列表相比,我使用了更长的列表,并且这些条目比 int要复杂一些。我这样做是为了每次搜索时不会遍历整个列表)

现在,如果我将它改为 i == 666,它将返回一个 StopIteration,因为它在 a中找不到任何 666条目。

我怎样才能让它返回 None而不是?我当然可以用 try ... except子句包装它,但是有没有更简洁的方法呢?

40638 次浏览

您可以使用(无,)链接生成器:

from itertools import chain
a = [1,2,3,4]
print chain((i for i, v in enumerate(a) if v == 6), (None,)).next()

但是我认为 a.index (2)不会遍历整个列表,当找到2时,搜索就结束了。你可以试试这个:

>>> timeit.timeit("a.index(0)", "a=range(10)")
0.19335955439601094
>>> timeit.timeit("a.index(99)", "a=range(100)")
2.1938486138533335

如果您正在使用 Python 2.6 + ,那么您应该使用 next内置函数,而不是 next方法(在3.x 中用 __next__替换了 next方法)。如果迭代器用完了,next内置参数会返回一个可选的缺省参数,而不是引发 StopIteration:

next((i for i, v in enumerate(a) if i == 666), None)