Использование во время распознавания списков или выражений генератора

Я могу использовать if и for в выражениях выражений/генераторов списков как

list(i for i in range(100) if i*i < 30)

Я знаю, что это не самый эффективный, но нести меня, поскольку условие может быть намного сложнее, и это просто пример. Тем не менее, это все еще проходит через сотни итераций и дает только значение в первом 6. Есть ли способ сообщить генераторному выражению, где остановиться с чем-то вроде этого:

list(i for i in range(100) while i*i < 30)

Однако while не понимается в выражениях генератора. Итак, мой вопрос: как написать выражение генератора с условием остановки, чтобы он не продолжал вычисление, даже если он не дает новых значений.

Ответы

Ответ 1

Различные функции в itertools (takewhile() приходят на ум) могут помочь.

Ответ 2

Поскольку синтаксис takewhile() и dropwhile() не самый ясный, вот примеры вашего вопроса:

>>> [i for i in itertools.takewhile(lambda x: x*x<30, range(10))]
[0, 1, 2, 3, 4, 5]
>>> [i for i in itertools.dropwhile(lambda x: x*x<30, range(10))]
[6, 7, 8, 9] 

Знайте, что автор itertools поставил под сомнение, следует ли осуждать эти функции.