Причина проста — ограниченность памяти нашего компьютера. Теперь, когда вы имеете примерное представление о том, чем является генератор, у вас наверняка появилось желание увидеть как он работает. В первом вы увидите общий принцип работы генераторов.
- При первом вызове метода next() выполняется код функции с первой команды до yield.
- Проще говоря, иногда нужно спуститься на такой уровень, на котором выдача элементов наружу проста и контролируема — например, как вывод элементов на печать с помощью print().
- Генераторы работают одинаково, независимо от того, построены они на основе функции или выражения.
- Более того, когда next() вызывается для объекта-генератора (явно или неявно в цикле for), ранее полученная переменная num увеличивается, а затем возвращается снова.
- Такая функция не будет выполняться до тех пор, пока не будет вызван метод next() с вернувшимся объектом в качестве аргумента (то есть fib).
Рассмотрим несколько примеров итерируемых объектов, которые есть в языке
Протокол генератора в Python и выражение yield
python (кроме range). Эти измерения действительны не только для генераторов, созданных с помощью выражений. Они абсолютно идентичны и для генераторов, созданных с помощью функции. Ведь, как мы уже говорили выше, эти генераторы эквивалентны. Создание же бесконечной последовательности стопроцентно потребует от нас использования генератора.
Выражение yield предоставляют удобный способ реализации протокола итератора, который технически, представляет из себя объект генератора. Это выражение используется в теле функции и приводит к тому, что функция становится генератором. Выражение yield используется примерно как return, отличие в том, что функция возвращает генератор. Как и выражения создающие списки, выражения создающие генераторы позволяют быстро получить объект генератора с помощью всего одной строчки кода. Использоваться они могут в тех же случаях, что и выражения создающие списки, но при этом у них есть одно дополнительное преимущество. Их можно создавать не удерживая весь объект в памяти перед итерацией.
Представление бесконечного потока данных.
Несколько генераторов можно использовать для обработки сразу нескольких операций. Здесь выражение — это значение, которое будет возвращено для каждого элемент в итератор. В данном случае в генераторе списка берется каждый элемент из списка a и возводится в квадрат. Таким образом, 1) что делаем – возводим элемент в квадрат, 2) что берем – элемент, 3) откуда берем – из списка a. Здесь мы предполагаем, что изменение списка через одну переменную, будут видны через другую.
Однако если изменить список генератором, то переменные будут указывать на разные списки. Сначала рассмотрим генераторы списков, чтобы привыкнуть к синтаксической конструкции. А теперь мы познакомимся https://deveducation.com/ с тем, что действительно является генератором – оператором yield. С использованием yield есть несколько тонкостей, но мы сначала рассмотрим общий синтаксис, а затем уже про эти тонкости расскажем.
А генератор в каждый
отдельный момент удерживает только
Польза от генераторов в Python
одно значение — то, которое он возвращает. Когда мы применяем
генератор, нам также не приходится ждать
рендеринга всех значений. Поэтому условие в цикле while
всегда будет соблюдаться (всегда true). В
результате генератор even() продолжает
возвращать значение Even, пока мы не
№7 Строки в Python / Уроки по Python для начинающих
прервем выполнение цикла вручную
(сочетанием клавиш Ctrl+C).
Понимание работы генератора Python
Мы просто поместили внутрь списочного выражения, создающего словарь, еще 2 списочных выражения, создающих списки (в функцию zip()). Обратите внимание на формулировку «работает как итератор». В Python многое работает на соглашениях, поэтому если что-то ведет себя как итератор, то оно и считается итератором.
Когда вызывается генератор, его тело (код) не выполняется сразу же. Вместо этого возвращается объект генератора, который можно итерировать для получения значений. С другой стороны, объекты-генераторы – это особые объекты-функции, которые между вызовами сохраняют свое состояние.
Первые пять вызовов next() были успешными и возвращали соответствующий элемент последовательности Фибоначчи. А вот последний вернул исключение StopIteration, поскольку элементов, которые можно было бы вернуть, больше не осталось. Такая функция не будет выполняться до тех пор, пока генератор python не будет вызван метод next() с вернувшимся объектом в качестве аргумента (то есть fib). Обычная функция, возвращающая последовательность, создает всю последовательность в памяти, прежде чем вернуть результат. Это проблема, когда количество элементов в последовательности огромное.
Ближе к коду
Будут рассмотрены основные отличия от итераторов и обычных функций. Стоит обратить внимание, что если вызвать метод next() после вывода последнего элемента, генератор сотрет его из памяти и выдаст исключение StopIteration. В этом примере функция read_large_file создает генератор, который построчно читает файл.