Найти тему
programmer's notes (python and more)

Основы программирования на языке Python. Генераторы в Python. Приложение к уроку 28

Оглавление

Доброго времени суток, читатели, зрители моего канала programmer's notes.

Статьи-ссылки на материалы моего канала о программировании на языке Python | programmer's notes (python and more) | Дзен

Приложение к видео-уроку 28

Генераторы в Python

Что же такое генераторы? Можно сказать, что это итераторы, тем более, что свойства у них такие же. Но у них другие функции. Они на заменяют коллекции, а наоборот используются для создания коллекций. Кроме того, итераторы и генераторы относятся к разным классам (объекты разных классов), если говорить на языке объектного подхода.

Генерация коллекций

Самое интересное в вопросе о генераторах это создание на основе их коллекций.

ls = [t for t in range(1, 11)]
st = {t for t in range(1, 11)}
dc = {t:t^2 for t in range(1, 11)}
print(ls)
print(st)
print(dc)

Результат выполнения фрагмента

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
{1: 3, 2: 0, 3: 1, 4: 6, 5: 7, 6: 4, 7: 5, 8: 10, 9: 11, 10: 8}

Т.е. в результате выполнения создается: список, множество, словарь. Здорово, правда? Т.е. первый способ создание генератора это скобка (квадратная или фигурная) и обычный цикл, но записанный строчно. Такая запись очень удобна, так как сокращает программный код. Кроме того, сам генератор можно использовать в других выражениях и это совсем уже здоров, так как позволяет писать программы в одну строчку. Но к этому мы вернемся позднее.

Разумеется генераторы могут быть вложенными, например

ls = [t for t in [y * y for y in range(0, 100, 2)]]

В результате получается список

[0, 4, 16, 36, 64, 100, 144, 196, 256, 324, 400, 484, 576, 676, 784, 900, 1024, 1156, 1296, 1444, 1600, 1764, 1936, 21
16, 2304, 2500, 2704, 2916, 3136, 3364, 3600, 3844, 4096, 4356, 4624, 4900, 5184, 5476, 5776, 6084, 6400, 6724, 7056,
7396, 7744, 8100, 8464, 8836, 9216, 9604]

Из генератора можно получить и строку

s = ''.join([chr(i) for i in range(48, 58)])
print(s)

Результат выполнения программы

0123456789

Поясню, если кому-то не понятно последнее. Цифры (как символы) имеют код от 48 до 58 включительно. Функция chr() преобразует код в символ. Имейте в виду, что по умолчанию работает кодировка utf-8.

Условия в генераторах

При генерации элементов коллекций можно осуществлять отбор по тому или иному условию.

s = 'we qw e ddff dfsdfsdfsdf ass aa  AQAsA SAS SDSDdf ff f ffffrw ee qwww erwqetqre yuiio pdddds s'
ls = [t for t in  s.split() if len(t) > 2 and len(t) < 6]
print(ls)

Здесь осуществляется отбор по длине слова.

Результат выполнения фрагмента

['ddff', 'ass', 'AQAsA', 'SAS', 'qwww', 'yuiio']

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

ls = [t if t % 2 == 0 else t * t  for t in range(1, 11)]
print(ls)

Результат выполнения фрагмента

[1, 2, 9, 4, 25, 6, 49, 8, 81, 10]

По сути мы получили ветвление внутри самого генератора.

Генератор похож на итератор

Если для генератора используются круглые скобки, то получиться объект-генератор, а не кортеж, как можно было бы подумать.

gn = (t for t in range(1, 11))

gn это именно объект типа (класса) генератор.

По своим свойствам он ведет себя как итератор.

gn = (t for t in range(1, 11))
print(next(gn))
print(next(gn))
print(*gn)

К нему применимы функция next(), и при извлечении из него элемента, этот элемент удаляется из генератора.

Результат выполнения данного фрагмента

1
2
3 4 5 6 7 8 9 10

Генератор может быть преобразован к коллекции

ls = list(gn)

При этом все элементы будут из него удалены.

К элементам генератора нельзя обращаться по индексу и нельзя узнать его длину, с помощью функции len().

Сделать из коллекции генератор просто - используем уже известные нам конструкции

ls = ['a', 'b', 'c', 'd']
gn = (t for t in ls) # получили генератор
print(*gn)

Результат работы фрагмента

a b c d

Создание генератора с помощью функции

Можно создать свой собственный генератор как функцию, если использовать оператор yield.

primer79.py, текст ниже
primer79.py, текст ниже
primer79.py

Выше представлен пример создания генератора с помощью функции. Генерируются числа в заданном промежутке, которые делятся на 3. При этом gn - самый настоящий генератор, в том смысле, о котором мы говорили выше

Результат выполнения программы

3 6 9

Использование функций для создания генераторов удобно тем, что к ней можно обращаться многократно, не переписывая выражений.

Примеры

Ну и на последок два пример.

ls = [[i for i in range(j, 10 + j)] for j in range(0, 100, 10)]
print(ls)

Фрагмент генерирует двумерный массив. Результат выполнения

[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18, 19], [20, 21, 22, 23, 24, 25, 26, 27, 28, 29], [30, 31, 32, 33, 34, 35, 36, 37, 38, 39], [40, 41, 42, 43, 44, 45, 46, 47, 48, 49], [50, 51, 52, 53, 54, 55, 56, 57, 58, 59], [60, 61, 62, 63, 64, 65, 66, 67, 68, 69], [70, 71, 72, 73, 74, 75, 76, 77, 78, 79], [80, 81, 82, 83, 84, 85, 86, 87, 88, 89], [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]]

Ну и пример генератора, обрабатывающего две последовательности.

l1 = [1, 2, 3, 4, 5, 6]
l2 = ['A', 'B', 'C', 'D', 'E', 'F']
ls = [(l1[i], l2[j]) for i in range(len(l1)) for j in range(len(l2)) if j == i]
print(ls)

Результат выполнения фрагмента

[(1, 'A'), (2, 'B'), (3, 'C'), (4, 'D'), (5, 'E'), (6, 'F')]

Пока все. Всего наилучшего. Оставляйте свои комментарии, не забывайте про лайки и подписывайтесь на мой канал programmer's notes.

Сегодня я программировал на Python, но минут 20, а вчера, ну целый день писал на С++
Сегодня я программировал на Python, но минут 20, а вчера, ну целый день писал на С++
Статьи-ссылки на материалы моего канала о программировании на языке Python | programmer's notes (python and more) | Дзен