Предупреждение Это немного запутанно, но делает свою работу.Я буду использовать пример, чтобы объяснить это.
Допустим, expensive_function = math.sin
infinite generator = collections.count(0.1,0.1)
тогда
[z for z in (y if y < 5 else next(iter([]))
for y in (math.sin(x) for x in itertools.count(0.1,0.1)))]
равно
[0.09983341664682815,
0.19866933079506122,
0.2955202066613396,
0.3894183423086505,
0.479425538604203]
Итак, ваша проблема сводится к
[z for z in (y if y < 0.5 else next(iter([])) \
for y in (expensive_function(x) for x in generator))]
Хитрость заключается в том, чтобы заставить StopIteration
из генератора и ничего элегантного, чем next(iter([]))
Здесь expensive_function
вызывается только один раз за итерацию.
Расширение бесконечного генератора конечным генератором с условием остановки.Поскольку генератор не допускает raise StopIteration
, мы выбираем извилистый способ, то есть next(iter([]))
И теперь у вас есть конечный генератор, который можно использовать в понимании списка
Поскольку OP занимался приложениемописанного выше метода для немонотонной функции здесь вымышленная немонотонная функция
дорогая немонотонная функция f(x) = random.randint(1,100)*x
условие останова = < 7
[z for z in (y if y < 7 else next(iter([])) for y in
(random.randint(1,10)*x for x in itertools.count(0.1,0.1)))]
[0.9,
0.6000000000000001,
1.8000000000000003,
4.0,
0.5,
6.0,
4.8999999999999995,
3.1999999999999997,
3.5999999999999996,
5.999999999999999]
Кстати: sin
в истинном смысле не является монотонным во всем диапазоне (0,2pi)