Однорядне вкладене для петель


102

Написав цю функцію в 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. Яким є порядок виконання цього циклу?
  2. Якби у мене було потрійне вкладене для циклу, який наказ він би виконував?
  3. Що було б рівним необмеженим для циклу?

Дано,

[ function(i,j) for i,j in object ]
  1. Який тип повинен бути об’єктом, щоб використовувати це для структури циклу?
  2. Який порядок, в якому i і j присвоюються елементам об’єкта?
  3. Чи може це моделювати інша для структури циклу?
  4. Чи може це для циклу вкладати подібну чи іншу структуру для циклу? А як би це виглядало?

Також цінується додаткова інформація.

Відповіді:


169

Найкращим джерелом інформації є офіційний навчальний посібник Python щодо розуміння списку . Означення списку майже такі ж, як і для циклів (звичайно, будь-яке розуміння списку може бути записане у вигляді циклу 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)]

Це точно так само, як це вкладено для циклу (і, як говорить підручник, зауважте, як порядок для і якщо вони однакові).

>>> 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 (де ви щось робите) настає на початку, а не в кінці.

Ваші запитання:

Який тип повинен бути об’єктом, щоб використовувати це для структури циклу?

Ітерацію . Будь-який об'єкт, який може генерувати (скінченний) набір елементів. До них належать будь-який контейнер, списки, набори, генератори тощо.

Який порядок, в якому i і j присвоюються елементам об’єкта?

Вони призначаються в такому ж порядку, як і генеровані з кожного списку, як якщо б вони були вкладеними для циклу (для вашого першого розуміння ви отримаєте 1 елемент для i, а потім кожне значення j, 2-й елемент в i, то кожне значення від j тощо)

Чи може це моделювати інша для структури циклу?

Так, вже показано вище.

Чи може це для циклу вкладати подібну чи іншу структуру для циклу? А як би це виглядало?

Звичайно, але це не чудова ідея. Ось, наприклад, наводить список списків символів:

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

Цікаво, чим керувався їх вибір замовлення у подвійному гніздуванні. Я вважаю інший спосіб більш природним (для y тоді для x у вашому прикладі). Я просто усвідомлюю, що через 3 роки роблю пітон (не дуже, але все-таки ...) і користуюся цими видами циклів !!
Томас

@Thomas Я також вважаю інший спосіб більш інтуїтивним. Я вважаю, що вибір був суто зручним. Зробити це більш інтуїтивно зрозумілим способом означає, що доведеться мати справу з невирішеними символами, доки вони не знайдуть їх згодом у заяві. Спробуйте розібрати для кожного banana.peel в кожному банані для кожного city.bananastore в кожному місті на папері. Не так просто. Хоча, навпаки, приємно і легко.
Піжонг

29

Можливо, вас зацікавить 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]


4

Перш за все, ваш перший код використовує не цикл per se, а розуміння списку .

  1. Було б рівнозначно

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

  2. Приблизно так само, як правило, гніздиться, як для петель, праворуч ліворуч. Але синтаксис розуміння списку складніший.

  3. Я не впевнений, що задає це питання


  1. Будь-який ітерабельний об’єкт, який дає ітерабельні об'єкти, які дають рівно два об'єкти (що за рот - тобто [(1,2),'ab']було б дійсним)

  2. Порядок, в якому об'єкт поступається ітерацією. iйде до першої врожайності, jдругої.

  3. Так, але не так симпатично. Я вважаю, що він функціонально еквівалентний:

    l = список ()
    для i, j в об'єкті:
        l.append (функція (i, j))
    

    або ще краще використовувати карту :

    map(function, object)

    Але, звичайно , функція б отримати i, jсам.

  4. Це не те саме питання, що і 3?


2

Ви можете використовувати два для циклу в одному рядку, використовуючи zipфункцію

Код:

list1 = ['Abbas', 'Ali', 'Usman']
list2 = ['Kamran', 'Asgar', 'Hamza', 'Umer']
list3 = []
for i,j in zip(list1,list2):
    list3.append(i)
    list3.append(j)
print(list3)

Вихід:

['Abbas', 'Kamran', 'Ali', 'Asgar', 'Usman', 'Hamza']

Отже, використовуючи функцію zip, ми можемо використовувати два для циклів або ми можемо повторити два списки в одному рядку.


-1

Нижче наведено код найкращих прикладів для вкладених циклів, при цьому використовуючи два для циклів, будь ласка, пам’ятайте, що вихід першого циклу вводиться для другого циклу. Закінчення циклу також важливе під час використання вкладених циклів

for x in range(1, 10, 1):
     for y in range(1,x):
             print y,
        print
OutPut :
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.