Предупреждение Это немного запутанно, но работает. Я буду использовать пример, чтобы объяснить это.
Скажем 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)))]
is
[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)
person
Abhijit
schedule
06.01.2012