Темы, связанные с генераторами в Python

PythonPythonBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом разделе рассматриваются некоторые дополнительные темы, связанные с генераторами, в том числе выражения-генераторы и модуль itertools.

Выражения-генераторы

Генераторная версия списочного выражения.

>>> a = [1,2,3,4]
>>> b = (2*x for x in a)
>>> b
<generator object at 0x58760>
>>> for i in b:
...   print(i, end=' ')
...
2 4 6 8
>>>

Различия от списочных выражений.

  • Не строит список.
  • Единственная полезная цель - итерация.
  • После использования нельзя переиспользовать.

Общая синтаксис.

(<expression> for i in s if <conditional>)

Он также может служить аргументом функции.

sum(x*x for x in a)

Может быть применен к любому итерируемому объекту.

>>> a = [1,2,3,4]
>>> b = (x*x for x in a)
>>> c = (-x for x in b)
>>> for i in c:
...   print(i, end=' ')
...
-1 -4 -9 -16
>>>

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

f = open('somefile.txt')
lines = (line for line in f if not line.startswith('#'))
for line in lines:
  ...
f.close()

С использованием генераторов код работает быстрее и использует мало памяти. Это похоже на фильтр, применяемый к потоку.

Почему генераторы

  • Многие проблемы лучше выражаются в терминах итерации.
    • Перебор коллекции элементов и выполнение какого-либо действия (поиск, замена, модификация и т.д.).
    • Трубы обработки могут быть применены к широкому спектру задач обработки данных.
  • Лучшая эффективность использования памяти.
    • Генерируют значения только по необходимости.
    • В отличие от построения гигантских списков.
    • Может работать с потоковым данными
  • Генераторы способствуют повторному использованию кода
    • Отделяет итерацию от кода, который использует итерацию
    • Можно создать набор полезных функций итерации и совмещать их в разных комбинациях.

Модуль itertools

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

itertools.chain(s1,s2)
itertools.count(n)
itertools.cycle(s)
itertools.dropwhile(predicate, s)
itertools.groupby(s)
itertools.ifilter(predicate, s)
itertools.imap(function, s1,... sN)
itertools.repeat(s, n)
itertools.tee(s, ncopies)
itertools.izip(s1,..., sN)

Все функции обрабатывают данные итеративно. Они реализуют различные виды итерационных паттернов.

Больше информации в руководстве Generator Tricks for Systems Programmers из PyCon '08.

В предыдущих упражнениях вы писали код, который следил за строками, записываемыми в файл журнала, и анализировал их в последовательность строк. В этом упражнении продолжаем развивать этот код. Убедитесь, что stocksim.py по-прежнему работает.

Упражнение 6.13: Выражения-генераторы

Выражения-генераторы представляют собой генераторную версию списочного выражения. Например:

>>> nums = [1, 2, 3, 4, 5]
>>> squares = (x*x for x in nums)
>>> squares
<generator object <genexpr> at 0x109207e60>
>>> for n in squares:
...     print(n)
...
1
4
9
16
25

В отличие от списочного выражения, выражение-генератор можно использовать только один раз. Таким образом, если вы попытаетесь использовать другой цикл for, ничего не получится:

>>> for n in squares:
...     print(n)
...
>>>

Упражнение 6.14: Выражения-генераторы в аргументах функции

Выражения-генераторы иногда помещаются в аргументы функций. Это может выглядеть немного странно вначале, но попробуйте этот эксперимент:

>>> nums = [1,2,3,4,5]
>>> sum([x*x for x in nums])    ## Списочное выражение
55
>>> sum(x*x for x in nums)      ## Выражение-генератор
55
>>>

В приведенном выше примере второй вариант с использованием генераторов потребовал бы значительно меньше памяти, если бы обрабатывался большой список.

В файле portfolio.py вы выполняли несколько вычислений, в которых использовались списочные выражения. Попробуйте заменить их на выражения-генераторы.

✨ Проверить решение и практиковаться

Упражнение 6.15: Пространение кода

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

def filter_symbols(rows, names):
    for row in rows:
        if row['name'] in names:
            yield row

Можно написать что-то вроде этого:

rows = (row for row in rows if row['name'] in names)

Измените программу ticker.py так, чтобы использовать выражения-генераторы по необходимости.

✨ Проверить решение и практиковаться

Резюме

Поздравляем! Вы завершили лабораторную работу "Больше о генераторах". Вы можете практиковаться в других лабораторных работах в LabEx, чтобы улучшить свои навыки.