Проблема в понимании понимания списков Python

Что означает последняя строка в следующем коде?

import pickle, urllib                                                                                                                                                     

  handle = urllib.urlopen("http://www.pythonchallenge.com/pc/def/banner.p")
  data = pickle.load(handle)
  handle.close()

  for elt in data:
         print "".join([e[1] * e[0] for e in elt])

Моя попытка проблемы:

  • "". join... использует join -method для пустого текста
  • e [1] * e [0] умножает два последующих значения в последовательности, e
  • Я не уверен, что такое e
  • Я не уверен, что это значит, когда у вас есть что-то раньше для -loop, например: e[1] * e[0] for e in elt

Ответ 1

Может быть, лучше всего объяснить с помощью примера:

print "".join([e[1] * e[0] for e in elt])

- краткая форма

x = []
for e in elt:
  x.append(e[1] * e[0])
print "".join(x)

List comprehensions - это просто синтаксический сахар для циклов for, которые вызывают выражение из последовательности инструкций.

elt может быть произвольным объектом, так как вы загружаете его из соленья и e аналогичным образом. Использование предполагает, что это тип sequence, но это может быть просто все, что реализует протокол последовательности.

Ответ 2

Во-первых, вам нужно поместить http://перед URL, то есть:

handle = urllib.urlopen("http://www.pythonchallenge.com/pc/def/banner.p")

Выражение [e for e in a_list] - это понимание списка, которое генерирует список значений.

В случае строк Python оператор * используется для повторения строки. Попробуйте ввести команды одну за другой в интерпретатор, а затем посмотрите на данные:

>>> data[0]
[(' ', 95)]

Это показывает нам, что каждая строка данных является кортежем, содержащим два элемента.

Таким образом, выражение e[1] * e[0] фактически является строкой в e[0] повторенной e[1] раз.

Следовательно программа рисует баннер.

Ответ 3

[e[1] * e[0] for e in elt] - это понимание списка, которое оценивает сам список, перебирая другой список, в этом случае elt. Каждый элемент в новом списке e[1]*e[0], где e - соответствующий элемент в elt.

Ответ 4

Сам вопрос уже полностью ответил, но я хотел бы добавить, что понимание списка также поддерживает фильтрацию. Исходная строка

print "".join([e[1] * e[0] for e in elt])

может, в качестве примера, стать

print "".join([e[1] * e[0] for e in elt if len(e) == 2])

работать только с элементами в elt, которые имеют два элемента.

Ответ 5

join() - это строковый метод, который работает с разделителем в новой строке

>>> ':'.join(['ab', 'cd'])
>>> 'ab:cd'

и не должно быть понимания списка, генератора будет достаточно

Ответ 6

Энди - отличный ответ!

Если вы хотите увидеть каждый шаг цикла (с перерывами), попробуйте это:

for elt in data:
    for e in elt:
        print "e[0] == %s, e[1] == %d, which gives us:  '%s'" % (e[0], e[1], ''.join(e[1] * e[0]))