Подтвердить что ты не робот

В python есть более простой способ написать 6 вложенных циклов?

Эта проблема уже давно на меня надвигается. Есть ли более простой способ писать вложенные петли for в python? Например, если мой код выглядит примерно так:

  for y in range(3):
    for x in range(3):
      do_something()
      for y1 in range(3):
        for x1 in range(3):
          do_something_else()

был бы более простой способ сделать это? Я знаю, что этот код работает, но когда вы отступаете вместо использования 2 пробелов, таких как я, это может стать проблемой.

В этом примере было всего 4 вложенных цикла for, чтобы упростить задачу.

4b9b3361

Ответ 1

Если вы часто повторяете декартово произведение, как в вашем примере, вы можете изучить Python 2.6 itertools.product - или напишите свой собственный, если вы находитесь на более раннем Python.

from itertools import product
for y, x in product(range(3), repeat=2):
  do_something()
  for y1, x1 in product(range(3), repeat=2):
    do_something_else()

Ответ 2

Это довольно часто встречается при переходе через многомерные пространства. Мое решение:

xy_grid = [(x, y) for x in range(3) for y in range(3)]

for x, y in xy_grid:
    # do something
    for x1, y1 in xy_grid:
        # do something else

Ответ 3

Когда вы сталкиваетесь с такой программной логикой, я бы, вероятно, разбил последовательность циклов на две или более отдельных функций.

Другой метод в Python заключается в том, чтобы использовать список понятий, где это возможно, вместо цикла.

Ответ 4

Предполагая, что каждый цикл имеет какое-то независимое значение, разбивайте его на именованные функции:

def do_tigers():
    for x in range(3):
        print something

def do_lions():
    do_lionesses()
    for x in range(3):
        do_tigers()

def do_penguins():
    for x in range(3):
        do_lions()

..etc.

Возможно, я мог бы выбрать лучшие имена. 8 -)

Ответ 5

Технически вы можете использовать itertools.product для получения декартова произведения из N последовательностей и повторить это:

 for y, x, y1, x1 in itertools.product(range(3), repeat=4):
   do_something_else()

Но я не думаю, что на самом деле вы выиграли у вас что-то читабельное.

Ответ 6

Итераторы Python и, в частности, генераторы, существуют точно, чтобы обеспечить хороший рефакторинг иначе-сложных циклов. Конечно, трудно получить абстракцию из простого примера, но предполагая, что параметр 3 должен быть параметром (может быть, весь range(3) должен быть?), А две функции, которые вы вызываете, нуждаются в некоторых параметрах, которые являются переменными цикла, вы можете реорганизовать код:

  for y in range(3):
    for x in range(3):
      do_something(x, y)
      for y1 in range(3):
        for x1 in range(3):
          do_something_else(x, y, x1, y1)

в, например:

def nestloop(n, *funcs):
  head = funcs[0]
  tail = funcs[1:]
  for y in range(n):
    for x in range(n):
      yield head, x, y
      if tail:
        for subtup in nestloop(n, *tail):
           yield subtup[:1] + (x, y) + subtup[1:]

for funcandargs in nestloop(3, do_something, do_something_else):
  funcandargs[0](*funcandargs[1:])

Точный вид рефакторинга, несомненно, нуждается в настройке для ваших точных целей, но общая точка, в которой итераторы (и обычно на самом деле просто простые генераторы) обеспечивают очень хорошие реорганизации циклов, остается - вся логика цикла заходит внутрь генератор и код уровня приложения оставлены с простыми циклами for и фактической обработкой приложений, полученными в циклах for.

Ответ 7

Мой личный аргумент состоял бы в том, что вы, вероятно, делаете что-то неправильно, если у вас есть 6 вложенных циклов...

Тем не менее, функциональная декомпозиция - это то, что вы ищете. Refactor, поэтому некоторые из циклов происходят в отдельных вызовах функций, а затем вызывают эти функции.

Ответ 8

Из вашего кода похоже, что вы хотите выполнить операцию с каждой возможной парой точек, где x и y находятся в диапазоне 0..2.

Для этого:

for x1,y1,x2,y2 in itertools.product(range(3), repeat=4):
    do_something_with_two_points(x1,y1,2,y2)

Операция do_something_with_two_points будет называться 81 раз - один раз для каждой возможной комбинации точек.

Ответ 9

Вы заглянули в List Comprehensions?

Что-то вроде:

[do_something() for x in range(3) for y in range(3)]

Ответ 10

Этот способ выглядит довольно просто и легко. Вы говорите, что хотите обобщить на несколько слоев циклов.... можете ли вы привести пример в реальной жизни?

Другим вариантом, который я мог бы подумать, было бы использовать функцию для генерации параметров, а затем просто применить их в цикле

def generate_params(n):
    return itertools.product(range(n), range(n))

for x,y in generate_params(3):
    do_something()

Ответ 11

вы также можете использовать map() function