Python: генераторы списков

Автор: | 24/03/2015
 

PythonГенераторы списков позволяют записать в одну строку то, что обычно делается в несколько cтрок.

Возьмём такой пример:

>>> list = []
>>> for i in range(1,5):
...   list.append(i)
...
>>> list
[1, 2, 3, 4]

И этот же пример – но с помощью генератора списка:

>>> list = [i for i in range(1,5)]
>>> list
[1, 2, 3, 4]

Генератор условно делится на три части:

  • действие над элементом (в данном примере – ничего), результат которого будет добавлен в новый список;
  • сам элемент (i);
  • объект для получения элементов цикл (range(1,5)).

Усложним пример:

>>> list1 = range(1,5)
>>> list1
[1, 2, 3, 4]
>>> list2 = [i*2 for i in list1]
>>> list2
[2, 4, 6, 8]

Тут выполняется действие *2 над каждым элементом i в объекте list1.

Можно использовать и более сложные примеры, например – исключить часть данных из обработки:

>>> list1 = range(1,5)
>>> list2 = [i*2 for i in list1 if i != 1]
>>> list2
[4, 6, 8]

Или использовать несколько условий:

>>> list2 = [i*2 for i in list1 if i != 1 or i != 2]
>>> list2
[2, 4, 6, 8]
>>> list2 = [i*2 for i in list1 if i != 1 and i != 2]
>>> list2
[6, 8]

Ещё один пример – генератор писка из словаря:

>>> dic = {'a':'one', 'b':'two', 'c':'three'}
>>> list = (["key: %s = value: %s" % (x, y) for x, y in dic.items()])
>>> list
['key: a = value: one', 'key: c = value: three', 'key: b = value: two']
>>> print 'n'.join(list)
key: a = value: one
key: c = value: three
key: b = value: two

Другой пример – получения списка из случайных чисел от 1 до 8:

>>> from random import randint
>>> list = [randint(1, 9) for i in range(10)]
>>> list
[1, 6, 8, 3, 3, 2, 3, 6, 5, 8]

Вложенные циклы в генераторах списков:

>>> list1 = [i+1 for i in range(5)]
>>> list2 = [(i+1)*10 for i in range(5)]
>>> list1
[1, 2, 3, 4, 5]
>>> list2
[10, 20, 30, 40, 50]
>>> list3 = [i*j for i in list1 for j in list2]
>>> list3
[10, 20, 30, 40, 50, 20, 40, 60, 80, 100, 30, 60, 90, 120, 150, 40, 80, 120, 160, 200, 50, 100, 150, 200, 250]
>>> list3 = [i*j for i in list1 for j in list2 if j != 50]
>>> list3
[10, 20, 30, 40, 20, 40, 60, 80, 30, 60, 90, 120, 40, 80, 120, 160, 50, 100, 150, 200]