Как я могу заставить генератор 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
, но есть ли еще более питонический способ сделать это?
Ответы
Ответ 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