Как я могу сделать пирамиду for-loop более кратким в Python?

В твердой механике я часто использую Python и пишу код, который выглядит следующим образом:

for i in range(3): for j in range(3): for k in range(3): for l in range(3): # do stuff 

Я часто это делаю, и начинаю задаваться вопросом, есть ли более сжатый способ сделать это. Недостаток текущего кода: если я выполняю PEP8 , то я не могу превышать ограничение на 79 символов на строку, и осталось слишком много места, особенно если это снова функция класса.

4 Solutions collect form web for “Как я могу сделать пирамиду for-loop более кратким в Python?”

Основываясь на том, что вы хотите сделать, вы можете использовать модуль itertools для минимизации циклов for (или zip ). В этом случае itertools.product создаст то, что вы сделали с 4 циклами:

 >>> list(product(range(3),repeat=4)) [(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 1, 0), (0, 0, 1, 1), (0, 0, 1, 2), (0, 0, 2, 0), (0, 0, 2, 1), (0, 0, 2, 2), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 0, 2), (0, 1, 1, 0), (0, 1, 1, 1), (0, 1, 1, 2), (0, 1, 2, 0), (0, 1, 2, 1), (0, 1, 2, 2), (0, 2, 0, 0), (0, 2, 0, 1), (0, 2, 0, 2), (0, 2, 1, 0), (0, 2, 1, 1), (0, 2, 1, 2), (0, 2, 2, 0), (0, 2, 2, 1), (0, 2, 2, 2), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 0, 2), (1, 0, 1, 0), (1, 0, 1, 1), (1, 0, 1, 2), (1, 0, 2, 0), (1, 0, 2, 1), (1, 0, 2, 2), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 1, 0), (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 0), (1, 1, 2, 1), (1, 1, 2, 2), (1, 2, 0, 0), (1, 2, 0, 1), (1, 2, 0, 2), (1, 2, 1, 0), (1, 2, 1, 1), (1, 2, 1, 2), (1, 2, 2, 0), (1, 2, 2, 1), (1, 2, 2, 2), (2, 0, 0, 0), (2, 0, 0, 1), (2, 0, 0, 2), (2, 0, 1, 0), (2, 0, 1, 1), (2, 0, 1, 2), (2, 0, 2, 0), (2, 0, 2, 1), (2, 0, 2, 2), (2, 1, 0, 0), (2, 1, 0, 1), (2, 1, 0, 2), (2, 1, 1, 0), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 2, 0), (2, 1, 2, 1), (2, 1, 2, 2), (2, 2, 0, 0), (2, 2, 0, 1), (2, 2, 0, 2), (2, 2, 1, 0), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 2, 0), (2, 2, 2, 1), (2, 2, 2, 2)] 

И в вашем коде вы можете сделать:

 for i,j,k,l in product(range(3),repeat=4): #do stuff 

Эта функция эквивалентна следующему коду, за исключением того, что фактическая реализация не создает промежуточные результаты в памяти:

 def product(*args, **kwds): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools = map(tuple, args) * kwds.get('repeat', 1) result = [[]] for pool in pools: result = [x+[y] for x in result for y in pool] for prod in result: yield tuple(prod) 

Изменить : как @ PeterE говорит в комментарии product() может использоваться, даже если диапазоны имеют разную длину:

 product(range(3),range(4),['a','b','c'] ,some_other_iterable) 

Идея использовать itertools.product является хорошей. Вот более общий подход, который будет поддерживать диапазоны разного размера.

 from itertools import product def product_of_ranges(*ns): for t in product(*map(range, ns)): yield t for i, j, k in product_of_ranges(4, 2, 3): # do stuff 

Это не будет более кратким, поскольку это будет стоить вам функции генератора, но по крайней мере вы не будете обеспокоены PEP8:

 def tup4(n): for i in range(n): for j in range(n): for k in range(n): for l in range(n): yield (i, j, k, l) for (i, j, k, l) in tup4(3): # do your stuff 

(в python 2.x вы должны использовать xrange вместо range в функции генератора)

РЕДАКТИРОВАТЬ:

Вышеуказанный метод должен быть точным, когда известна глубина пирамиды. Но вы также можете создать генератор генератора без какого-либо внешнего модуля:

 def tup(n, m): """ Generate all different tuples of size n consisting of integers < m """ l = [ 0 for i in range(n)] def step(i): if i == n : raise StopIteration() l[i] += 1 if l[i] == m: l[i] = 0 step(i+ 1) while True: yield tuple(l) step(0) for (l, k, j, i) in tup(4, 3): # do your stuff 

(Я использовал (l, k, j, i) потому что в этом генераторе первый индекс сначала меняется)

Это эквивалентно:

 for c in range(3**4): i = c // 3**3 % 3 j = c // 3**2 % 3 k = c // 3**1 % 3 l = c // 3**0 % 3 print(i,j,k,l) 

Если вы делаете это все время, подумайте об использовании генератора для него:

 def nestedLoop(n, l): return ((tuple((c//l**x%l for x in range(n-1,-1,-1)))) for c in range(l**n)) for (a,b,c,d) in nestedLoop(4,3): print(a,b,c,d) 
  • объединить настраиваемый формат разреженной матрицы X с целевым массивом Y в Python
  • Пользовательское исключение: <unprintable ... object>
  • python, вставляющий переменную строку в качестве имени файла
  • Как форматировать вывод печати в фиксированную ширину?
  • Сортировка подсписок элементов в списке, оставляющий остальное на месте
  • Импорт Python работает при запуске модуля, но прерывается, когда этот модуль импортируется
  • Получение длины списка как значения в словаре в Python 2.7
  • Ускорение в петлеобразных структурах
  • Python - лучший язык программирования в мире.