Понимание понимания вложенного списка - PullRequest
70 голосов
/ 08 ноября 2011

Я хочу понять понимание вложенного списка. Ниже я перечислил выражение понимания списка и их эквивалент для цикла.
Интересно, правильно ли мое понимание этих вопросов?

Например,

[(min([row[i] for row in rows]),max([row[i] for row in rows])) 
for i in range(len(rows[0]))]

эквивалентно

result=[]
for i in range(len(rows[0])):
  innerResult=[]
  for row in rows:
    innerResult.append(row[i])
  innerResult2=[]
  for row in rows:
    innerResult2.append(row[i])
  tuple=(min(innerResult), max(innerResult2))
  result.append(tuple)

Если я могу обобщить, я думаю,

[exp2([exp1 for x in xSet]) for y in ySet]

форму можно перевести на следующую. (Надеюсь, я прав в этом)

result=[]
for y in ySet:
  innerResult =[]
  for x in xSet:
    innerResult.append(exp1)
  exp2Result = exp2(innerResult)
  result.append(exp2Result)

Для более простого случая,

[exp1 for x in xSet for y in ySet] 

равно

result=[] 
for x in xSet:
  for y in ySet: 
    result.append(exp1)
* * Тысяча двадцать-одина тогда, * * 1 022
[[exp1 for x in xSet] for y in ySet]

равно

result=[]
for y in ySet:
  innerResult=[]
  for x in xSet:
    innerResult.append(exp1)
  result.append(innerResult)

Я задал похожий вопрос по Эквивалент для циклического выражения для понимания сложного списка
Ответы, данные там, восстанавливают форму после понимания того, что она делает внутри.
Я хотел бы знать, как это работает систематически, чтобы я мог применить концепцию к другим слегка меняющимся примерам.

Ответы [ 2 ]

72 голосов
/ 08 ноября 2011

Действительно, вы правы.Это подробно описано в разделе Выражения в Справочнике по языку Python .

Обратите особое внимание на порядок вложения нескольких for с в одном понимании списка, которое всегда остаетсянаправо:

>>> matrix = [[1, 2], [3, 4]]
>>> [item for item in row for row in matrix] # oops!
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    [item for item in row for row in matrix]
NameError: name 'row' is not defined
>>> [item for row in matrix for item in row] # nesting is in left-to-right order
[1, 2, 3, 4]
70 голосов
/ 08 ноября 2011

Краткий ответ: да, вы правы в своем понимании .

Есть только одна загвоздка: способ, которым вы обычно используете понимание вложенного списка в коде Python, заключается в работе с многомерныммассивы.

Типичным примером является работа с матрицами:

>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [[el - 1 for el in row] for row in matrix]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]

Как вы можете видеть, «вложенность» работает, работая с каждым измерением матрицы.

В предоставленных вами примерах, похоже, что ySet [неудачное имя, кстати, поскольку наборы являются одним из типов, предоставляемых с python], это просто общий счетчик, который делаетнемного сложнее следить за тем, что происходит под капотом.

Что касается вашего первого примера:

>>> rows = ([1, 2, 3], [10, 20, 30])
>>> [(min([row[i] for row in rows]),max([row[i] for row in rows])) for i in range(len(rows[0]))]
[(1, 10), (2, 20), (3, 30)]

Возможно, вы захотите заглянуть во встроенный zip функция:

>>> zip(rows[0], rows[1])
[(1, 10), (2, 20), (3, 30)]

или для максимальной краткости и элегантности:

>>> zip(*rows)
[(1, 10), (2, 20), (3, 30)]

HTH!

...