Итератор и Генератор

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

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

Введение

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

Достижения

  • Итератор
  • Генератор
  • Генераторное выражение

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python(("Python")) -.-> python/ErrorandExceptionHandlingGroup(["Error and Exception Handling"]) python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python/ControlFlowGroup -.-> python/for_loops("For Loops") python/ControlFlowGroup -.-> python/list_comprehensions("List Comprehensions") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/ErrorandExceptionHandlingGroup -.-> python/raising_exceptions("Raising Exceptions") python/AdvancedTopicsGroup -.-> python/iterators("Iterators") python/AdvancedTopicsGroup -.-> python/generators("Generators") subgraph Lab Skills python/for_loops -.-> lab-84{{"Итератор и Генератор"}} python/list_comprehensions -.-> lab-84{{"Итератор и Генератор"}} python/function_definition -.-> lab-84{{"Итератор и Генератор"}} python/classes_objects -.-> lab-84{{"Итератор и Генератор"}} python/raising_exceptions -.-> lab-84{{"Итератор и Генератор"}} python/iterators -.-> lab-84{{"Итератор и Генератор"}} python/generators -.-> lab-84{{"Итератор и Генератор"}} end

Итератор

Итератор - это объект, по которому можно итерироваться (перебирать в цикле). Объект, который возвращает данные по одному элементу за раз. В Python итератор создается из итерируемого объекта, такого как список, кортеж или строка.

Откройте новый интерпретатор Python.

python3

Для создания итератора в Python необходимо реализовать два метода в своем объекте: __iter__ и __next__.

__iter__ возвращает сам объект-итератор. Метод __next__ возвращает следующее значение из итератора. Если больше нет элементов для возврата, он должен вызывать исключение StopIteration.

Вот пример простого итератора, который перебирает список чисел:

class MyIterator:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        ## len() - количество элементов в списке
        if self.index >= len(self.data):
            raise StopIteration
        result = self.data[self.index]
        self.index += 1
        return result

iterator = MyIterator([1, 2, 3, 4, 5])
for x in iterator:
    print(x)

Результат:

1
2
3
4
5

Итераторы полезны, потому что позволяют получать элементы итерируемого объекта по одному, вместо того чтобы загружать все элементы сразу в память. Это особенно полезно при работе с большими наборами данных, которые не помещаются в память.

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

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

iterator = MyIterator([1, 2, 3, 4, 5])
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))

## StopIteration
print(next(iterator))

Результат:

1
2
3
4

## StopIteration

Вот некоторые общие сценарии использования итераторов в Python:

  1. Перебор элементов большего набора данных по одному элементу за раз.
  2. Реализация ленивой вычислительности большего набора данных.
  3. Реализация собственной логики итерации в классе.
  4. Итераторы - мощный инструмент в Python и могут быть использованы для написания эффективного и элегантного кода.

Генератор

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

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

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

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

def my_generator(data):
    for x in data:
        yield x**2

for x in my_generator([1, 2, 3, 4, 5]):
    print(x)

Результат:

1
4
9
16
25

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

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

Вот некоторые общие сценарии использования генераторов в Python:

  1. Генерация элементов по требованию, вместо генерации всех элементов сразу.
  2. Реализация ленивой вычислительности больших наборов данных.
  3. Реализация собственной логики итерации в функции.
  4. Генераторы - мощный инструмент в Python и могут быть использованы для написания эффективного и элегантного кода.

Различия между итератором и генератором

Основное отличие между итератором и генератором - это способ их реализации.

Итератор - это объект, который реализует два метода: __iter__ и __next__. Метод __iter__ возвращает сам объект-итератор, а метод __next__ возвращает следующее значение из итератора.

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

Вот краткое изложение основных различий между итераторами и генераторами:

  1. Итераторы - это объекты, которые реализуют методы __iter__ и __next__. Они создаются из итерируемых объектов, таких как списки, кортежи или строки.
  2. Генераторы - это функции, которые используют ключевое слово yield для возврата значения. Они создаются путем вызова функции-генератора.
  3. Итераторы могут быть реализованы с использованием класса, в то время как генераторы реализуются с использованием функции.
  4. Итераторы возвращают по одному элементу за раз, в то время как генераторы возвращают объект-генератор, который можно использовать для генерации элементов по требованию.
  5. Итераторы используются для доступа к элементам итерируемого объекта по одному, в то время как генераторы используются для генерации элементов по требованию.

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

Продвинутый пример: Генератор простых чисел

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

Сначала определим вспомогательную функцию _is_prime, которая возвращает True, если число простое, и False в противном случае:

def _is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

Теперь определим нашу функцию-генератор prime_numbers:

def prime_numbers(n):
    for i in range(2, n+1):
        if _is_prime(i):
            yield i

Протестируем наш генератор:

for prime in prime_numbers(20):
    print(prime)

Результат:

2
3
5
7
11
13
17
19

Генераторное выражение

Генераторное выражение похоже на списочное выражение, но вместо создания списка возвращает объект-генератор.

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

Вот пример генераторного выражения, которое генерирует квадраты чисел из списка:

generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in generator:
    print(x)

Результат:

1
4
9
16
25

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

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

Вот некоторые общие сценарии использования генераторных выражений в Python:

  1. Генерация элементов по требованию, вместо генерации всех элементов сразу.
  2. Реализация ленивой вычислительности больших наборов данных.
  3. Пишение компактного и эффективного кода.

Генераторные выражения - мощный инструмент в Python и могут быть использованы для написания эффективного и элегантного кода.

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

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

## Списочное выражение
squares = [x**2 for x in [1, 2, 3, 4, 5]]
print(squares)

## Генераторное выражение
squares_generator = (x**2 for x in [1, 2, 3, 4, 5])
for x in squares_generator:
    print(x)

Результат:

[1, 4, 9, 16, 25]
1
4
9
16
25

Списочные выражения и генераторные выражения имеют несколько сходств и различий:

Сходства

  1. И списочные выражения, и генераторные выражения используются для генерации последовательности элементов.
  2. Оба используют одинаковый синтаксис, с одной или несколькими инструкциями for и выражением для генерации элементов.

Различия

  1. Списочное выражение генерирует список, в то время как генераторное выражение генерирует объект-генератор.
  2. Списочное выражение генерирует все элементы списка сразу, в то время как генераторное выражение генерирует элементы по требованию.
  3. Списочное выражение использует больше памяти, так как хранит все элементы в списке, в то время как генераторное выражение использует меньше памяти, так как генерирует элементы по требованию.
  4. Списочное выражение обычно выполняется быстрее, так как генерирует все элементы сразу, в то время как генераторное выражение обычно медленнее, так как генерирует элементы по требованию.

В целом, и списочные выражения, и генераторные выражения - полезные инструменты для генерации последовательности элементов в Python. Списочные выражения обычно быстрее и используют больше памяти, в то время как генераторные выражения обычно медленнее и используют меньше памяти. Какой подход использовать, зависит от конкретных требований приложения.

Резюме

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