web-dev-qa-db-ja.com

PythonジェネレータでStopIterationではなくNoneを返すにはどうすればよいですか?

私はジェネレーターを使用して、この単純な例のようなリストで検索を実行しています:

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

(この例を少しフレーム化するために、私は上記のものと比較して非常に長いリストを使用しており、エントリはintよりも少し複雑です。この方法で行うと、リスト全体が表示されなくなります検索するたびにトラバースされる)

これをi == 666に変更すると、StopIteration666エントリが見つからないため、aが返されます。

代わりにNoneを返すようにするにはどうすればよいですか?もちろん、それをtry ... except句でラップすることもできますが、それを行うためのよりPython的な方法はありますか?

47
c00kiemonster

Python 2.6+を使用している場合は、_ next 組み込み関数を使用する必要があります。nextメソッド(交換された __next__ 3.xで)。 nextビルトインは、StopIterationを発生させる代わりに、イテレータが使い果たされた場合に返すオプションのデフォルト引数を取ります:

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

(None、)でジェネレータをチェーンできます:

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
7
HYRY