В чем причина того, что мы можем использовать вложенные циклы в списках - PullRequest
1 голос
/ 24 апреля 2020

Я изучал списочные понимания, и что-то останавливало меня на несколько дней.

Простое понимание списка имеет вид

[expression for item in iterable]

эквивалент for l oop is

li=[]
for item in iterable
    li.append(item)

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

Что бы ни происходило внутри for l oop, написано в начале liscomp.

Мы можем думать, что в listcomp Python допускается только одно выражение, а масти for l oop могут иметь только предложение if или вложенные циклы for.

Цитируя книгу, которую я читал, она гласит, что

Так как списочные выражения создают списки, то есть итерируемые, и поскольку синтаксис для списочных пониманий требует итерируемого, это можно вложить список пониманий. Это эквивалентно наличию вложенных циклов for … in.

Это сбило меня с толку.

Говорит ли это о причинах наличия listcomp типа [s+z for s in iterable_1 for z in iterable_2] * 1034? *

Может кто-нибудь объяснить, что это говорит.

1 Ответ

1 голос
/ 24 апреля 2020

Ваш первый перевод должен быть

li=[]
for item in iterable: 
    li.append( expression(item) )

Ваш пример [s+z for s in iterable_1 for z in iterable_2] переводится как

li=[]
for s in iterable_1:
    for z in iterable_2:
        li.append(s+z)

Поздравляю, вы обнаружили ... монады! по сути, это то, что вы описали, вложенные циклы .

Вложенные циклы просто создают простой поток результатов. Вложенные списки , когда сведены , также превращаются в простой поток элементов. Это сходство. A lazy append очень похож на yield.

Каждый тип монады определяется тем, как он реализует свою версию функции flatMap, которая карта с последующим выравниванием вложенной структуры Уплощение вложенной структуры на каждом уровне вложенности позволяет выравнивать произвольную глубину вложенности:

M [M (a)]  ==>  M (a)

M [M [M (a)]]  ==>   # flatten the outer two layers first:
                     M [M (a)]  ==>  M (a)
               OR:
               ==>  # flatten the inner two layers first:
                     M [M (a)]  ==>  M (a)

Видите разницу? Там нет ни одного! Любой тип, который делает вышеупомянутое, является «монадой». Нравится списки.

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

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

...