Подтвердить что ты не робот

Как я могу заставить генератор Python возвращать None, а не StopIteration?

Я использую генераторы для выполнения поиска в списках, как этот простой пример:

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

(Просто, чтобы немного нарисовать пример, я использую очень большие списки по сравнению с приведенным выше, а записи немного сложнее, чем int. Я делаю это так, чтобы все списки выиграли ' t быть пройденным каждый раз, когда я их ищу)

Теперь, если бы я вместо этого изменил это на i == 666, он вернул бы StopIteration, потому что он не смог найти запись 666 в a.

Как я могу заставить его возвращать None? Я мог бы, конечно, обернуть его в предложение try ... except, но есть ли еще более питонический способ сделать это?

4b9b3361

Ответ 1

Если вы используете Python 2.6+, вы должны использовать встроенную функцию next, а не метод next (который был заменен на __next__ в 3.х). Встроенный next принимает необязательный аргумент по умолчанию для возврата, если итератор исчерпан, вместо повышения StopIteration:

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

Ответ 2

Вы можете связать генератор с помощью (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