Понимание понимания списка по сравнению с традиционным циклом и сборкой

Я пытаюсь понять свое понимание и лучшее использование списков, я столкнулся с пониманием списков и много читал о них, но задыхаюсь от одного конкретного животрепещущего вопроса.

Учитывая эту задачу:

def matrix_mult(m1, m2):
    """
      >>> matrix_mult([[1, 2], [3,  4]], [[5, 6], [7, 8]])
      [[19, 22], [43, 50]]
      >>> matrix_mult([[1, 2, 3], [4,  5, 6]], [[7, 8], [9, 1], [2, 3]])
      [[31, 19], [85, 55]]
      >>> matrix_mult([[7, 8], [9, 1], [2, 3]], [[1, 2, 3], [4, 5, 6]])
      [[39, 54, 69], [13, 23, 33], [14, 19, 24]]
    """

Я создал это решение, мне оно показалось наиболее логичным и соответствовало моему предыдущему опыту программирования, я более или менее набирал так, как думал...

# 1 using a traditional List buildup method    
res = []
for i in range(len(m1)):
    sub = []
    for j in range(len(m2[0])):
        sub.append(row_times_column( m1, i, m2, j ))
    res.append(sub)
return res

Затем я нашел это решение, в котором использовалось «понимание списка» (я переименовал vars, чтобы они соответствовали моему, чтобы лучше понять различия между двумя решениями:

# 2 using list comprehension
res = [[0] * len(m1) for x in xrange(len(m2[0]))]
for i in range(len(res)):
   for j in range(len(res[i])):
       res[i][j] = row_times_column(m1, i, m2, j)
return res

Второе решение — построить матрицу с отсчетом от нуля, которая соответствует форме предполагаемого ответа, но этот метод подразумевается под "пониманием списка", или здесь происходит нечто большее?

Вот определение row_times_column() для полноты.

def row_times_column(m1, row, m2, column):
    """
      >>> row_times_column([[1, 2], [3, 4]], 0, [[5, 6], [7, 8]], 0)
      19
      >>> row_times_column([[1, 2], [3, 4]], 0, [[5, 6], [7, 8]], 1)
      22
    """
    i = 0
    for index, value in enumerate(m1[row]):
       i += value * m2[index][column]
    return i

Я подозреваю, что есть третий (и многие другие) способ решить эту проблему, используя лямбда, но я подумал, что сначала попрошу прокомментировать эти 2.

Пример взят из http://openbookproject.net/thinkcs/python/english2e/ch09.html< /а>

РЕДАКТИРОВАТЬ Теперь у вас есть гораздо лучшее понимание списка, спасибо за приведенные здесь ответы.

Тем не менее, может ли кто-нибудь объяснить логику создания пустой матрицы, в которую помещаются правильные ответы, а не просто создания нового списка?


person Cups    schedule 03.07.2011    source источник
comment
Если вы не создадите пустую матрицу раньше, синтаксис res[i][j] = выдаст ошибку, поскольку элемент не существует; так что вы должны использовать res.append(), который не так хорошо читается, как синтаксис здесь. Думаю, это единственная причина.   -  person littlegreen    schedule 16.04.2013
comment
PS. Вы еще не приняли ответ :-)   -  person littlegreen    schedule 16.04.2013


Ответы (5)


Понимание списков — это просто способ создания списка на основе другого списка. (Или другой итерируемый элемент)

Например, если у нас есть список a = [1, 2, 5, 7], мы могли бы создать список b, содержащий значения a, удвоенные двумя способами.

Без понимания списка

b = []
for e in a:
    b.append(2*e)

Со списками

b = [2*e for e in a]

Там нет ничего больше, чем это. Это просто хороший синтаксис для построения списков на основе списков.

Смотрите также:

person Sebastian Paaske Tørholm    schedule 03.07.2011

Первая строка представляет собой понимание списка. Остальное нет.

 return [[row_times_column(m1, i, m2, j) for j in range(len(res[i]))]
     for i in range(len(res))]
person Ignacio Vazquez-Abrams    schedule 03.07.2011

Следующее также использует понимание списка для умножения матриц.

def matrix_mult(m1, m2):
  return [[sum(m1[i][k]*m2[k][j] for k in range(len(m2))) for j in range(len(m2[0]))] for i in range(len(m1))]
person Howard    schedule 03.07.2011
comment
Спасибо, Говард, я подозревал, что такая вещь должна существовать, но не мог представить, как она будет выглядеть! Придется сломать это... - person Cups; 03.07.2011

Обоснование понимания списка в Python объясняется в PEP 202.

Включение списков обеспечивает более краткий способ создания списков в ситуациях, когда в настоящее время используются map() и filter() и/или вложенные циклы.

Так что никакой «особой хитрости» за этой идеей на самом деле нет. Это просто синтаксическое расширение, как это делает PEP.

ХТН

person mac    schedule 03.07.2011

Марк Пилгрим гораздо лучше объясняет понимание списков, чем я, в своей книге Dive into Python. Эта книга действительно хороша для начинающих изучать Python и просто хороша для чтения в целом. Рекомендуемые.

P.S.: Понимание списков для Python 3 также есть в Погружение в Python 3.

person Anshuman Bhaduri    schedule 04.07.2011