Одиночная Линия Вложенных Циклов For


написал эту функцию в python, которая транспонирует матрицу:

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

в процессе я понял, что я не полностью понимаю, как единую линию вложенных циклов выполнения. Пожалуйста, помогите мне понять, ответив на следующие вопросы:

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

дали,

[ function(i,j) for i,j in object ]
  1. какой тип должен быть объект, чтобы использовать это для структуры цикла?
  2. Каков порядок, в котором i и j назначаются элементам в объекте?
  3. может ли он быть смоделирован другой структурой цикла?
  4. может ли этот цикл for быть вложенным с аналогичной или другой структурой для цикла? И как это будет выглядеть?

дополнительная информация также приветствуется.

3 58

3 ответа:

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

посмотрите на этот более длинный список понимания из учебника (if часть фильтрует понимание, только части, которые передают оператор if, передаются в заключительную часть понимания списка (здесь (x,y)):

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

это точно так же, как этот вложенный цикл for (и, как говорится в учебнике, обратите внимание, как порядок for и if одинаковы).

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

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

на ваши вопросы:

какой тип должен быть объект, чтобы использовать это для петлевой структуры?

An iterable. Любой объект, который может генерировать (конечный) набор элементов. Это включает любой контейнер, списки, наборы, генераторы и т. д.

Каков порядок, в котором i и j назначаются элементам в объекте?

они назначаются в точно таком же порядке, как они генерируются из каждого списка, как если бы они были во вложенном цикле for (для вашего первого понимания вы получите 1 элемент для i, затем каждое значение из j, 2-й элемент в i, затем каждое значение из j и т. д.)

может ли он быть смоделирован другой структурой цикла?

да, уже показано выше.

может ли этот цикл for быть вложенным с аналогичной или другой структурой для цикла? И как это будет выглядеть?

конечно, но это не очень хорошая идея. Вот, например, дает вам список списков символов:

[[ch for ch in word] for word in ("apple", "banana", "pear", "the", "hello")]

вы можете быть заинтересованы в itertools.product, который возвращает итерационные кортежи значений из всех итераций, которые вы передаете ему. То есть, itertools.product(A, B) дает все значения вида (a, b), где значения A и b значения B. Например:

import itertools

A = [50, 60, 70]
B = [0.1, 0.2, 0.3, 0.4]

print [a + b for a, b in itertools.product(A, B)]

печатается:

[50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]

обратите внимание, как последний аргумент передается itertools.product является "внутренним". В общем,itertools.product(a0, a1, ... an) равна [(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]

во-первых, ваш первый код не использует цикл for per se, но a понимание.

  1. было бы эквивалентно

    для j в диапазоне (0, ширина): для i в диапазоне (0, высота): m[i] [j]

  2. точно так же, он обычно гнездится, как для петель, справа налево. Но синтаксис понимания списка более сложен.

  3. Я не уверен, что этот вопрос спрашиваю


  1. любой итерационный объект, который дает итерационные объекты, которые дают ровно два объекта (какой глоток-т. е. [(1,2),'ab'] будет действительным )

  2. порядок, в котором объект дает повторение. i идет на первый выход, j второй.

  3. да, но не так красиво. Я считаю, что это функционально эквивалентно:

    l = list()
    for i,j in object:
        l.append(function(i,j))
    

    или даже лучше использовать карта:

    map(function, object)
    

    но конечно функция должна была бы получить i,j сам по себе.

  4. разве это не тот же вопрос, что 3?