Одиночная Линия Вложенных Циклов 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) ]
в процессе я понял, что я не полностью понимаю, как единую линию вложенных циклов выполнения. Пожалуйста, помогите мне понять, ответив на следующие вопросы:
- в каком порядке выполняется этот цикл for?
- если бы у меня был тройной вложенный цикл for, что бы его выполнить?
- что было бы равно равному незаполненному для петля?
дали,
[ function(i,j) for i,j in object ]
- какой тип должен быть объект, чтобы использовать это для структуры цикла?
- Каков порядок, в котором i и j назначаются элементам в объекте?
- может ли он быть смоделирован другой структурой цикла?
- может ли этот цикл for быть вложенным с аналогичной или другой структурой для цикла? И как это будет выглядеть?
дополнительная информация также приветствуется.
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 понимание.
было бы эквивалентно
для j в диапазоне (0, ширина): для i в диапазоне (0, высота): m[i] [j]
точно так же, он обычно гнездится, как для петель, справа налево. Но синтаксис понимания списка более сложен.
Я не уверен, что этот вопрос спрашиваю
любой итерационный объект, который дает итерационные объекты, которые дают ровно два объекта (какой глоток-т. е.
[(1,2),'ab']
будет действительным )порядок, в котором объект дает повторение.
i
идет на первый выход,j
второй.да, но не так красиво. Я считаю, что это функционально эквивалентно:
l = list() for i,j in object: l.append(function(i,j))или даже лучше использовать карта:
map(function, object)
но конечно функция должна была бы получить
i
,j
сам по себе.разве это не тот же вопрос, что 3?