2013-06-09 4 views
51

Написал эту функцию в Python, что переставляет матрицу:ОДНОЛИНЕЙНАЯ Вложенные Для Loops

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. Каков порядок выполнения этого цикла?
  2. Если у меня был тройной вложенный цикл, какой порядок он выполнит?
  3. Что было бы равно равным безжизненному циклу?

Учитывая,

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

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

ответ

91

Лучшим источником информации является official Python tutorial on list comprehensions. Сопоставления списков почти такие же, как для циклов (конечно, любое понимание списка может быть записано как цикл for), но они часто бывают быстрее, чем использование цикла for.

Посмотрите на этом длинный список осмысление из учебника (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)] 

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

>>> 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 (где вы что-то делаете) происходит в начале, а не в конце.

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

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

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

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

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

Можно ли его моделировать другой структурой петли?

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

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

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

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

Интересно, что руководствовался их выбором заказа в двойном гнездовании. Я нахожу другой путь более естественным (для y, затем для x в вашем примере). Я просто понимаю, что после 3 лет работы с python (не сильно, но все же ...) и использования этих типов циклов! – Thomas

+1

хорошо сказанный, спасибо! –

3

Прежде всего, ваш первый код не использовать цикл сам по себе, но list comprehension.

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

    для J в диапазоне (0, ширина): для I в диапазоне (0, высота): м [I] [J]

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

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


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

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

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

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

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

    map(function, object) 
    

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

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

20

Вы могли бы быть заинтересованы в itertools.product, который возвращает итератор, сеющие кортежи значений из всех итерируемых вы проходите его.То есть, itertools.product(A, B) дает все значения вида (a, b), где значения a взяты из 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]