Вот рекурсивный подход с использованием аргумента по умолчанию. Пронумерованные пункты ниже относятся к пронумерованным комментариям в коде.
- (база) Глубина равна нулю. Мы закончили, поэтому выведите комбинацию,
comb
- (индуктивный) Глубина не менее 1. Для каждого
x
в диапазоне делегируйте рекурсивному генератору, используя x
в качестве новой начальной точки для вложенного диапазона, и добавьте x
к комбинации, comb
.
def nested_range (depth = 0, start = 0, end = 1, comb = ()):
if depth == 0:
yield comb #1
else:
for x in range(start, end): #2
yield from nested_range(depth - 1, x, end, comb + (x,))
Вот вложенный диапазон глубиной три (3) уровня -
for p in nested_range (3, 0, 4):
print(p)
# (0, 0, 0)
# (0, 0, 1)
# (0, 0, 2)
# (0, 0, 3)
# (0, 1, 1)
# (0, 1, 2)
# (0, 1, 3)
# (0, 2, 2)
# (0, 2, 3)
# (0, 3, 3)
# (1, 1, 1)
# (1, 1, 2)
# (1, 1, 3)
# (1, 2, 2)
# (1, 2, 3)
# (1, 3, 3)
# (2, 2, 2)
# (2, 2, 3)
# (2, 3, 3)
# (3, 3, 3)
Эта реализация является полной функцией и дает действительный результат, когда depth = 0
-
for p in nested_range (0, 0, 4):
print(p)
# ()
И для правильной меры, вот вывод вложенного диапазона глубиной в пять (5) уровней -
for p in nested_range (5, 0, 3):
print(p)
# (0, 0, 0, 0, 0)
# (0, 0, 0, 0, 1)
# (0, 0, 0, 0, 2)
# (0, 0, 0, 1, 1)
# (0, 0, 0, 1, 2)
# (0, 0, 0, 2, 2)
# (0, 0, 1, 1, 1)
# (0, 0, 1, 1, 2)
# (0, 0, 1, 2, 2)
# (0, 0, 2, 2, 2)
# (0, 1, 1, 1, 1)
# (0, 1, 1, 1, 2)
# (0, 1, 1, 2, 2)
# (0, 1, 2, 2, 2)
# (0, 2, 2, 2, 2)
# (1, 1, 1, 1, 1)
# (1, 1, 1, 1, 2)
# (1, 1, 1, 2, 2)
# (1, 1, 2, 2, 2)
# (1, 2, 2, 2, 2)
# (2, 2, 2, 2, 2)