Помощники цикла for в Python

В языке Python заложено много полезных инструментов, способных значительно упростить жизнь разработчику, если о них знать и уметь использовать. Мы рассмотрим четыре функции, которые помогут нам при работе с циклом for, а в некоторых случаях позволят вообще отказаться от него!

О операторах ветвления и циклах написано в уроке “Python. Урок 5. Условные операторы и циклы”.

В статье рассмотрим следующие функции:

Функция range

Функция range() создает объект, который внутри себя содержит итератор, выдающий элементы из диапазона, определяемого аргументами функции.

Создадим объект range.

>>> r = range(3)

Получим его итератор.

>>> ri = iter(r)

Используя next(), извлечем из него все элементы.

>>> next(ri)
0
>>> next(ri)
1
>>> next(ri)
2
>>> next(ri)
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    next(ri)
StopIteration

Через параметры функции range можно задать диапазон и шаг. Создадим range, генерирующий числа от 1 до 10 с шагом 3.

>>> ri2 = iter(range(1,10,3))
>>> next(ri2)
1
>>> next(ri2)
4
>>> next(ri2)
7
>>> next(ri2)
Traceback (most recent call last):
  File "<pyshell#25>", line 1, in <module>
    next(ri2)
StopIteration

Объект range идеально подходит для использования в цикле for. Работа цикла for организована следующим образом:

  • получаем итератор у объекта, который предоставляет данные;
  • используя функцию next(), извлекаем элементы на каждой итерации цикла;
  • если произошел выброс исключения StopIteration, то выходим из цикла.

Пример: выведем список целых чисел от 0 до 2 на экран.

>>> for i in range(3):
        print(i)

0
1
2

Список чисел от 1 до 10 с шагом 2.

>>> for i in range(1, 10, 2):
        print(i)

1
3
5
7
9

Range можно использовать в List Comprehensions.

>>> [i for i in range(3)]

[0, 1, 2]

Функция range() – мощный инструмент, позволяющий получать последовательности целых чисел в заданном диапазоне с определенным шагом, с доступом через итератор.

Функция enumerate

Функция enumerate() конструирует генератор по переданной в нее (через аргумент) объект. Она предоставляет кортежи, состоящие из двух элементов, первый из которых – индекс, а второй – значение, извлекаемое из объекта.

Рассмотрим простой пример: найти в строке первое вхождение символа ‘o’ и вывести номер его позиции. Эта задача может быть решена так.

>>> msg = "hello!"
>>> i = 0
>>> for sym in msg:
        if sym == 'o':
            print("index = ", i)
            break
        i += 1

index =  4

В этой программе нам пришлось заводить дополнительную переменную i, значение которой на каждой итерации цикла мы увеличивали на единицу. Это не очень удобно! Использование функции enumerate() позволит упростить решение.

>>> msg = "hello!"
>>> for tp in enumerate(msg):
        if 'o' in tp:
            print("index = ", tp[0])

index =  4

В процессе работы цикла for из объекта, созданного функцией enumerate(), будут последовательно извлекаться следующие кортежи:

(0, ‘h’)
(1, ‘e’)
(2, ‘l’)
(3, ‘l’)
(4, ‘o’)

После извлечения кортежа (4, ‘o’), на экран выведется соответствующее сообщение и цикл завершится. Выведем все кортежи, получаемые из строки “hello!” с помощью функции enumerate().

>>> for tp in enumerate(msg):
        print(tp)

(0, 'h')
(1, 'e')
(2, 'l')
(3, 'l')
(4, 'o')
(5, '!')

Функция enumerate() позволяет получить индексы элементов объекта при обходе его в цикле for без введения дополнительных переменных.

Функция map

Функция map() предоставляет возможность применить указанную функцию к каждому элементу объекта. В результате получим список из модифицированных элементов исходного объекта.

Решим задачу возведения в квадрат всех элементов списка с использованием цикла for.

>>> numbers = [1, 2, 3, 4, 5]
>>> sq_nums = []
>>> for num in numbers:
        sq_nums.append(num**2)
>>> sq_nums
[1, 4, 9, 16, 25]

Эту задачу можно также решить с использованием List Comprehensions.

>>> sq_nums = [num**2 for num in numbers]
>>> sq_nums
[1, 4, 9, 16, 25]

Точно такой же результат получим, если воспользуемся функций map().

>>> sq_nums = list(map(lambda x: x**2, numbers))
>>> sq_nums
[1, 4, 9, 16, 25]

На первый взгляд такой подход может показаться сложнее предыдущего, но вся его мощь заключается в первом аргументе – функции, которая используется для модификации значений элементов объекта. Это может быть как lambda-функция, как в нашем примере, так функция, созданная с использованием ключевого слова def.

Результат работы функции map() можно использовать в цикле for.

>>> msg = "simple"
>>> for sym in map(lambda x: x+'-', msg):
        print(sym, end='')

s-i-m-p-l-e-

Используйте map(), если вам необходимо обработать элементы объекта, используя определенную функцию .

Функция zip

Функция zip() позволяет в одном цикле for производить параллельную обработку данных. Это очень мощный инструмент! Zip принимает в качестве аргументов объекты, элементы которых будут объединены в кортежи, полученную структуру можно превратить в список кортежей, если это необходимо.

Решим следующую задачу, демонстрирующую возможности zip(): в нашем распоряжении есть два списка, построим третий, каждый элемент которого будет формироваться как сумма элемента из первого списка и элемента из второго, умноженного на два.

>>> a = [1, 3, 5, 7, 9]
>>> b = [2, 4, 6, 8, 10]
>>> c = []
>>> for (x, y) in zip(a, b):
        c.append(x + 2 * y)
>>> c
[5, 11, 17, 23, 29]

Результат объединения списков с помощью функции zip() представлен ниже. Элементы исходных списков группируются попарно, образуя кортежи.

>>> a = [1, 3, 5, 7, 9]
>>> b = [2, 4, 6, 8, 10]
>>> list(zip(a, b))
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]

Если в функцию zip() передать три списка, то получим кортежи, состоящие из трех элементов.

>>> a = [1, 3, 5, 7, 9]
>>> b = [2, 4, 6, 8, 10]
>>> c = [10, 11, 12, 13, 14]
>>> list(zip(a, b, c))
[(1, 2, 10), (3, 4, 11), (5, 6, 12), (7, 8, 13), (9, 10, 14)]

В случае, когда исходные списки имеют разную длину, итоговое количество кортежей будет равно числу элементов в самом коротком списке.

>>> a = [1, 3, 5, 7, 9]
>>> d = [20, 21]
>>> list(zip(a, d))
[(1, 20), (3, 21)]

С помощью функции zip() можно создавать словари.

>>> a = [1, 3, 5, 7, 9]
>>> keys = ['a', 'b', 'c', 'd', 'e']
>>> dict(zip(keys, a))
{'d': 7, 'c': 5, 'a': 1, 'b': 3, 'e': 9}

Используйте zip() для параллельной обработки данных и быстрого построения структур данных. Такое решение будет функциональным и лаконичным!

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *