- №30 Генераторы / для начинающих
- Как создать генератор в Python?
- Функция генератора
- Генераторы в Python и их отличие от списков и функций
- 1. Что такое генераторы в Python?
- а. Синтаксис генератора в Python 3
- b. Как работает генератор в Python
- 2. Возврат значений в список
- 3. Разница между списком и генератором в Python
- 4. Разница между генератором и функцией в Python
- 5. Генераторные выражения в Python
- 6. Заключение
№30 Генераторы / для начинающих
В этой статье вы научитесь создавать и использовать функции и выражения генераторов в Python. Также узнаете, зачем и когда их стоит использовать в программах. Будут рассмотрены основные отличия от итераторов и обычных функций.
Отдельное внимание будет уделено инструкции yield . Она является частью генератора и заменяет ключевое слово return . Когда программа доходит до yield , то функция переходит в состояние ожидания и продолжает работу с того же места при повторном вызове.
Генератор в Python — это функция с уникальными возможностями. Она позволяет приостановить или продолжить работу. Генератор возвращает итератор, по которому можно проходить пошагово, получая доступ к одному значению с каждой итерацией.
Генератор предоставляет способ создания итераторов, решая следующую распространенную проблему.
Создание итератора в Python — достаточно громоздкая операция. Для этого нужно написать класс и реализовать методы __iter__() и __next__() . После этого требуется настроить внутренние состояния и вызывать исключение StopIteration , когда больше нечего возвращать.
Как создать генератор в Python?
Генератор — это альтернативный и более простой способ возвращать итераторы. Процедура создания не отличается от объявления обычной функции.
Есть два простых способа создания генераторов в Python.
Функция генератора
Генератор создается по принципу обычной функции.
Отличие заключается в том, что вместо return используется инструкция yield . Она уведомляет интерпретатор Python о том, что это генератор, и возвращает итератор.
Синтаксис функции генератора:
Генераторы в Python и их отличие от списков и функций
В этом уроке мы с вами разберем, что из себя представляют генераторы в программировании на языке Python. Кроме того, мы обсудим генераторные выражения и разницу между списками и генераторами, а также между функциями и генераторами.
1. Что такое генераторы в Python?
Генератор это подвид итерируемых объектов, как список или кортеж. Он генерирует для нас последовательность значений, которую мы можем перебрать. Эту последовательность можно использовать для итерации в цикле for, но нельзя проиндексировать (т. е., перебрать ее можно только один раз). Давайте посмотрим, как создается такая последовательность значений при помощи генератора.
а. Синтаксис генератора в Python 3
Для создания генератора в Python внутри функции вместо ключевого слова return используется ключевое слово yield. Обратите внимание на пример:
В этом примере мы определили генератор с именем counter() и назначили значение 1 локальной переменной i. Цикл while будет выполняться, пока i меньше или равно 10. Внутри цикла мы возвращаем (yield) значение i и увеличиваем его на единицу.
Затем мы используем этот генератор в цикле for.
b. Как работает генератор в Python
Чтобы разобраться в том, как работает этот код, давайте начнем с цикла for. Этот цикл выводит каждый элемент генератора (т. е., каждый элемент, возвращаемый генератором).
Мы начинаем с i=1. Таким образом, первый элемент, возвращаемый генератором, это 1. Цикл for выводит этот элемент на экран благодаря ключевому слову print. Затем i инкрементируется до 2. Весь процесс повторяется, пока i не инкрементируется до 11 (т. е., пока условие в цикле while не даст false).
Но если вы забудете добавить инкремент i, вы получите бесконечный генератор. Дело в том, что генератору в каждый момент времени нужно удерживать в памяти только одно значение. Таким образом, нет никаких ограничений памяти.
def even(x): while x%2==0: yield 'Even' for i in even(2): print(i)
Even Even Even Even Even Even Even Even Even Even Even Even Even
EvenTraceback (самый недавний вызов идет последним):
File “”, line 2, in print(i) KeyboardInterrupt
Поскольку 2 это четное число, 2%2 это всегда 0. Поэтому условие в цикле while всегда будет соблюдаться (всегда true). В результате генератор even() продолжает возвращать значение Even, пока мы не прервем выполнение цикла вручную (сочетанием клавиш Ctrl+C).
Обратите внимание, что генератор может содержать больше одного ключевого слова yield. Примерно так же, как функция может иметь больше одного ключевого слова return.
def my_gen(x): while( x> 0): if x%2==0: yield 'Even' else: yield 'Odd' x-=1 for i in my_gen(7): print(i)
Odd Even Odd Even Odd Even Odd
2. Возврат значений в список
Здесь все просто. Если вы примените функцию list() к вызову генератора, она вернет список возвращенных генератором значений, в том порядке, в котором они возвращались. В следующем примере генератор возвращает квадраты чисел, если эти квадраты четные.
def even_squares(x): for i in range(x): if i**2%2==0: yield i**2
Чтобы создать список из возвращаемых генератором значений, мы просто применяем функцию list() к вызову генератора. Мы не перебираем эти значения при помощи цикла for.
print(list(even_squares(10))) # Вывод: [0, 4, 16, 36, 64]
Как видите, для чисел в диапазоне 0-9 (не 10, потому что диапазон (10) это числа 0-9), четные квадраты это 0, 4, 16, 36 и 64. Остальные — 1, 9, 25, 49, 81 — нечетные. Поэтому они не возвращаются генератором.
3. Разница между списком и генератором в Python
Разница между ними очень проста. Список сразу удерживает в памяти определенное число значений. А генератор в каждый отдельный момент удерживает только одно значение — то, которое он возвращает. Вот почему генераторы требуют куда меньше памяти. Когда мы применяем генератор, нам также не приходится ждать рендеринга всех значений.
4. Разница между генератором и функцией в Python
Чтобы разобраться в различиях между генераторами и функциями, давайте сначала разберем разницу между ключевыми словами return и yield.
Когда интерпретатор доходит до ключевого слова return, выполнение функции полностью прекращается. Но когда он доходит до ключевого слова yield, программа приостанавливает выполнение функции и возвращает значение в итерируемый объект. После этого интерпретатор возвращается к генератору, чтобы повторить процесс для нового значения.
Кроме того, при прекращении выполнения функции ее локальные переменные стираются. В генераторах ситуация другая. Взгляните:
def mygen(): i=7 while i>0: yield i i-=1 for i in mygen(): print(i)
5. Генераторные выражения в Python
Для создания генераторов на скорую руку можно использовать выражения (как и для генераторов списка). Давайте возьмем для этого список:
>>> mylist = [1, 3, 6, 10] >>> (x**2 for x in mylist) at 0x7f7a06896af0>
Как видим, мы получили генератор. Но чтобы получить доступ к значениям, нужно сохранить его в переменной, а затем применить к этой переменной функцию next().
>>> a = (x**2 for x in mylist) >>> next(a) 1 >>> next(a) 9 >>> next(a) 36 >>> next(a) 100
Traceback (самый недавний вызов идет последним):
File “”, line 1, in next(a) StopIteration
Вот и все, что мы хотели рассказать вам о генераторах в Python. Надеемся, вам понравилось наше объяснение.
6. Заключение
Теперь, когда вы знаете о преимуществах генераторов по сравнению со списками и функциями, вы понимание их важность. Что-то мы можем делать при помощи генератора, что-то — при помощи функции или даже генератора списка. Но использование генераторов наиболее эффективно.