>>> Две или больше
Функции map
можно подать на вход больше одной последовательности и обработать их параллельно. Например, просуммировать поэлементно две последовательности:
>>> s1 = [1, 2, 3]
>>> s2 = [4, 5, 6, 7]
>>> m = map(lambda x, y: x+y, s1, s2)
>>> list(m)
[5, 7, 9]
Обработка завершается, когда достигнут конец самой короткой последовательности. Так же ведет себя функция zip
, собирающая из нескольких последовательностей одну – с кортежами:
>>> z = zip(s1, range(5))
>>> list(z)
[(1, 0), (2, 1), (3, 2)]
>>> m = map(lambda x, y: (x, y), s1, range(5))
>>> list(m)
[(1, 0), (2, 1), (3, 2)]
>>> reduce
может
Если при вызове filter
вместо функции передано значение None, то результирующая последовательность будет состоять из элементов исходной, оцененных как True
.
>>> seq = [1, 0, 3, 0]
>>> f = filter(None, seq)
>>> list(f)
[1, 3]
Функцию reduce
(неожиданно) можно использовать для порождения последовательности, если аккумулятороом будет последовательность:
>>> from functools import reduce
>>> reduce(lambda a, x: a + [x**3], seq, [])
[1, 0, 27, 0]
>>> reduce(lambda a, x: a + [x] if x else a, seq, [])
[1, 3]
Первый пример имитирует работу map
, второй – работу filter
.
>>> Списковое включение
Списковое включение (list comprehension) – замечательная конструкция Python, позволяющая из последовательности или итератора построить новый список; при этом возможно как преобразование исходных значений элементов (аналог map
), так и фильтрация (аналог filter
). Пример:
>>> seq = [1, 2, 3, 4]
>>> [x**2 for x in seq]
[1, 4, 9, 16]
Здесь часть for x in seq
организует обход всех элементов исходной последовательности, а выражение x**2
в цикле вычисляет значение очередного элемента результирующего списка. Приведенный пример соответствует следующему фрагменту кода:
>>> res = []
>>> for x in seq:
... res.append(x**2)
...
>>> res
[1, 4, 9, 16]
Опциональная часть if
позволяет организовать фильтрацию элементов исходной последовательности:
>>> [x for x in seq if x%2]
[1, 3]
>>> [x**2 for x in seq if x%2]
[1, 9]
>>> Вложенные списковые включения
Итерации и фильтры в списковом включении могут быть вложенными, что позволяет, в частности, обрабатывать многомерные структуры данных:
>>> seq = [range(3), range(3), range(3)]
>>> [e for r in seq for e in r]
[0, 1, 2, 0, 1, 2, 0, 1, 2]
Приведенный пример соответствует следующему фрагменту кода:
>>> res = []
>>> for r in seq:
... for e in r:
... res.append(e)
...
>>> res
[0, 1, 2, 0, 1, 2, 0, 1, 2]
Получим декартово произведение последовательностей; отфильтуем элементы исходных последовательностей:
>>> alp = ['a', 'b', 'c']
>>> num = [101, 102]
>>> [(a, n) for a in alp for n in num]
[('a', 101), ('a', 102), ('b', 101), ('b', 102), ('c', 101), ('c', 102)]
>>> [(a, n) for a in alp for n in num if a != 'a' if n%2]
[('b', 101), ('c', 101)]
>>> Генераторное выражение
Генераторное выражение (generator expression) умеет все, что умеет списковое включение, но результатом его выполнения является не список, а объект-генератор. Генераторное выражение заключается в обычные скобки:
>>> g = (x**2 for x in range(6) if x%2)
>>> type(g)
<class 'generator'>
>>> g
<generator object <genexpr> at 0x0000020DAC65C308>
Генератор можно использовать в тех же контекстах, что и итератор, но нужно иметь в виду, что генератор является одноразовым и "расходуется" при использовании:
>>> for x in g:
... print(x)
...
1
9
25
>>> for x in g:
... print(x)
...
>>>
При передаче генераторного выражения в функцию в качeстве аргумента дублировать скобки не требуется:
>>> list(x**2 for x in range(6))
[0, 1, 4, 9, 16, 25]
Комментариев нет:
Отправить комментарий