Ваш первый перевод должен быть
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 (и могут переводиться как таковые).