Использование itertools для произвольного числа вложенных циклов разных диапазонов с зависимостями?

Учитывая список верхних байт: B1, B2, .. BN;
Функции зависимостей: f1, …, fN-1,

Мне интересно, есть ли рецепт с использованием itertools или других классов в python для:

for i1 in range(0, B1): for i2 in range(f1(i1), B2): ... for iN in range(fN-1(iN-1), BN) dostuff(i1, i2, ... iN) 

Где N уровней гнездования?
Я хочу использовать эту вспомогательную функцию следующим образом:
зависимые продукты (Bs, fs, dostuff) ,
который возвращает список или повторяемый

В идеале реализация была бы итеративной, а не рекурсивной.

Итерационное решение с использованием настройки @ LaurentLAPORTE. Поместите этот код прямо под себя, и он должен работать. Мои args представляют собой стопку аргументов, подаваемых в dostuff когда он заполнен. Фактическое решение – это средняя часть, верхняя и нижняя части – это просто тестирование.

 stefan = [] def dostuff(*args): stefan.append(list(args)) args = [-1] while args: n = len(args) args[-1] += 1 if args[-1] >= B[n-1]: args.pop() elif n == len(B): dostuff(*args) else: args.append(F[n](args[-1]) - 1) assert expected == stefan 

Вот пример того, что вы хотите:

 B = [10, 15, 20, 5] F = [lambda x: x, lambda x: x * x, lambda x: x * 2 - 5] def dostuff(i0, i1, i2, i3): print((i0, i1, i2, i3)) expected = [] for i0 in range(0, B[0]): for i1 in range(F[0](i0), B[1]): for i2 in range(F[1](i1), B[2]): for i3 in range(F[2](i2), B[3]): expected.append([i0, i1, i2, i3]) 

Я нашел такое рекурсивное решение:

 def iter_rec(found, fL, bL): if fL and bL: ik = found[-1] if found else 0 fk = fL[0] bk = bL[0] for i in range(fk(ik), bk): for item in iter_rec(found + [i], fL[1:], bL[1:]): yield item else: yield found # prepend the null function to ensure F and B have the same size F = [lambda x: 0] + F current = [item for item in iter_rec([], F, B)] 

У нас такой же результат.

 assert expected == current 
Interesting Posts