Особенность этих классов
Несмотря на то что map, filter, zip, enumerate и reversed выглядят как функции, в Python 3 это классы. Они создают ленивые итераторы: значения вычисляются по одному при обходе. Итератор можно пройти только один раз.
m = map(str, [1, 2, 3])print(type(m))print(list(m))print(list(m))Второй list(m) вернёт пустой список: итератор уже исчерпан.
map
map(func, *iterables) применяет функцию к элементам:
print(list(map(str.upper, ["a", "b"])))print(list(map(lambda x: x * x, [1, 2, 3])))print(list(map(int, "123")))print(list(map(pow, [2, 3, 4], [1, 2, 3])))print(list(map(len, ["aa", "b", "cccc"])))При нескольких итерируемых обход останавливается на самом коротком.
Часто то же самое выражается через включение:
print([x * x for x in [1, 2, 3]])print(sum(int(ch) for ch in "12345"))map лучше смотрится, когда функция уже существует и не требует lambda:
print(list(map(str.strip, [" a ", " b"])))filter
filter(func, iterable) оставляет элементы, для которых функция возвращает истинное значение. Если вместо функции передать None, будут отброшены ложные элементы:
print(list(filter(lambda x: x % 2 == 0, range(10))))print(list(filter(None, [0, 1, "", "a", None, [], [0]])))print(list(filter(str.isdigit, ["1", "a", "22"])))itertools.filterfalse
Обратная операция:
from itertools import filterfalseprint(list(filterfalse(lambda x: x % 2, range(10))))zip
zip(*iterables, strict=False) склеивает элементы по позициям:
names = ["Anna", "Boris", "Clara"]ages = [25, 30, 28]cities = ["Moscow", "Berlin"]print(list(zip(names, ages)))print(list(zip(names, ages, cities)))Обход заканчивается на самой короткой последовательности. С параметром strict=True (Python 3.10+) разная длина вызывает ValueError:
try: list(zip([1, 2, 3], [1, 2], strict=True))except ValueError as e: print(e)Для выравнивания по самой длинной последовательности есть itertools.zip_longest:
from itertools import zip_longestprint(list(zip_longest([1, 2, 3], ["a"], fillvalue="-")))Транспонирование и разархивирование
pairs = [(1, "a"), (2, "b"), (3, "c")]nums, letters = zip(*pairs)print(nums)print(letters)matrix = [[1, 2, 3], [4, 5, 6]]print(list(zip(*matrix)))Создание словаря и попарный обход
keys = ["a", "b", "c"]values = [1, 2, 3]print(dict(zip(keys, values)))data = [1, 4, 9, 16]print([b - a for a, b in zip(data, data[1:])])enumerate
enumerate(iterable, start=0) возвращает пары (индекс, элемент):
for i, ch in enumerate("abc"): print(i, ch)for i, ch in enumerate("abc", start=1): print(i, ch)print(list(enumerate(["x", "y"], 10)))print(dict(enumerate("abc")))Это предпочтительная замена range(len(...)).
Поиск индекса по условию:
items = [4, 7, 10, 15]idx = next((i for i, v in enumerate(items) if v > 8), None)print(idx)reversed
reversed(seq) возвращает итератор по последовательности в обратном порядке. Работает с объектами, поддерживающими __reversed__ или __len__ и __getitem__:
print(list(reversed([1, 2, 3])))print("".join(reversed("abc")))print(list(reversed(range(5))))d = {"a": 1, "b": 2}print(list(reversed(d)))Для словарей reversed работает с Python 3.8. Нельзя применить reversed к итератору и множеству.
Обратите внимание на отличие от sorted(..., reverse=True): reversed не сортирует, а только разворачивает порядок.
Комбинации
words = ["apple", "fig", "banana"]print(list(map(len, filter(lambda w: "a" in w, words))))print(list(zip(range(3), map(str.upper, words))))for i, (w, n) in enumerate(zip(words, map(len, words)), 1): print(i, w, n)Сводка
| Класс | Сигнатура | Результат |
|---|---|---|
map | map(func, *iterables) | Итератор результатов функции |
filter | filter(func, iterable) | Итератор подходящих элементов |
zip | zip(*iterables, strict=False) | Итератор кортежей |
enumerate | enumerate(iterable, start=0) | Итератор пар (индекс, элемент) |
reversed | reversed(seq) | Итератор в обратном порядке |
Дополнительные встроенные функции для последовательностей
| Функция | Описание |
|---|---|
iter(obj) | Получить итератор |
iter(callable, sentinel) | Вызывать функцию до получения сторожевого значения |
next(it[, default]) | Следующий элемент |
sorted(iterable, key=None, reverse=False) | Отсортированный список |
min, max, sum | Агрегаты |
any, all | Логические агрегаты |
len | Длина |
it = iter([1, 2])print(next(it))print(next(it))print(next(it, "конец"))Задания
- Преобразуйте список строк с числами в список
int, пропустив некорректные значения. - Найдите попарные разности соседних элементов списка через
zip. - Транспонируйте матрицу и выведите её по строкам с номерами через
enumerate.
