Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Python

Генераторы Python

Генераторы Python

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

Видео:Генераторы Python

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

Существует много работы по созданию итератора в Python. Мы должны реализовать класс с __iter__() и __next__() метод, отслеживать внутренние состояния и поднимать StopIteration когда нет возвращаемых значений.

Это и долго, и контринтуитивно. Генератор приходит на помощь в таких ситуациях.

Генераторы Python — это простой способ создания итераторов. Вся упомянутая выше работа автоматически выполняется генераторами Python.

Проще говоря, генератор — это функция, которая возвращает объект (итератор), который мы можем перебирать (по одному значению за раз).

<час>

Создание генераторов в Python

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

Если функция содержит хотя бы один yield оператор (может содержать другие yield или return операторы), она становится функцией-генератором. Оба yield и return вернет некоторое значение из функции.

Разница в том, что в то время как return оператор полностью завершает функцию, yield Оператор приостанавливает функцию, сохраняя все ее состояния, а затем продолжает выполнение последующих вызовов.

<час>

Различия между функцией генератора и обычной функцией

Вот чем функция-генератор отличается от обычной функции.

Вот пример, иллюстрирующий все пункты, изложенные выше. У нас есть функция-генератор с именем my_gen(). с несколькими yield заявления.

# A simple generator function
def my_gen():
    n = 1
    print('This is printed first')
    # Generator function contains yield statements
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n

Интерактивный запуск в интерпретаторе приведен ниже. Запустите их в оболочке Python, чтобы увидеть результат.

>>> # It returns an object but does not start execution immediately.
>>> a = my_gen()

>>> # We can iterate through the items using next().
>>> next(a)
This is printed first
1
>>> # Once the function yields, the function is paused and the control is transferred to the caller.

>>> # Local variables and theirs states are remembered between successive calls.
>>> next(a)
This is printed second
2

>>> next(a)
This is printed at last
3

>>> # Finally, when the function terminates, StopIteration is raised automatically on further calls.
>>> next(a)
Traceback (most recent call last):
...
StopIteration
>>> next(a)
Traceback (most recent call last):
...
StopIteration

В приведенном выше примере следует отметить одну интересную вещь:значение переменной n запоминается между каждым вызовом.

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

Чтобы перезапустить процесс, нам нужно создать еще один объект-генератор, используя что-то вроде a = my_gen(). .

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

Это потому, что for цикл принимает итератор и перебирает его, используя next() функция. Он автоматически заканчивается, когда StopIteration Поднялся. Проверьте здесь, чтобы узнать, как на самом деле реализован цикл for в Python.

# A simple generator function
def my_gen():
    n = 1
    print('This is printed first')
    # Generator function contains yield statements
    yield n

    n += 1
    print('This is printed second')
    yield n

    n += 1
    print('This is printed at last')
    yield n


# Using for loop
for item in my_gen():
    print(item)

Когда вы запустите программу, вывод будет:

This is printed first
1
This is printed second
2
This is printed at last
3
<час>

Генераторы Python с циклом

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

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

Давайте рассмотрим пример генератора, который переворачивает строку.

def rev_str(my_str):
    length = len(my_str)
    for i in range(length - 1, -1, -1):
        yield my_str[i]


# For loop to reverse the string
for char in rev_str("hello"):
    print(char)

Вывод

o
l
l
e
h

В этом примере мы использовали range() функция для получения индекса в обратном порядке с помощью цикла for.

Примечание :эта функция-генератор работает не только со строками, но и с другими типами итерируемых объектов, такими как список, кортеж и т. д.

<час>

Выражение генератора Python

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

Аналогично лямбда-функциям, которые создают анонимные функции, выражения-генераторы создают анонимные функции-генераторы.

Синтаксис выражения генератора аналогичен синтаксису спискового понимания в Python. Но квадратные скобки заменяются круглыми скобками.

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

У них ленивое исполнение (производство предметов только по запросу). По этой причине генераторное выражение намного эффективнее использует память, чем эквивалентное понимание списка.

# Initialize the list
my_list = [1, 3, 6, 10]

# square each term using list comprehension
list_ = [x**2 for x in my_list]

# same thing can be done using a generator expression
# generator expressions are surrounded by parenthesis ()
generator = (x**2 for x in my_list)

print(list_)
print(generator)

Вывод

[1, 9, 36, 100]
<generator object <genexpr> at 0x7f5d4eb4bf50>

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

Вот как мы можем начать получать элементы из генератора:

# Initialize the list
my_list = [1, 3, 6, 10]

a = (x**2 for x in my_list)
print(next(a))

print(next(a))

print(next(a))

print(next(a))

next(a)

Когда мы запускаем указанную выше программу, мы получаем следующий вывод:

1
9
36
100
Traceback (most recent call last):
  File "<string>", line 15, in <module>
StopIteration

Выражения генератора могут использоваться в качестве аргументов функции. При таком использовании круглые скобки можно опустить.

>>> sum(x**2 for x in my_list)
146

>>> max(x**2 for x in my_list)
100
<час>

Использование генераторов Python

Есть несколько причин, которые делают генераторы мощной реализацией.

1. Легко реализовать

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

class PowTwo:
    def __init__(self, max=0):
        self.n = 0
        self.max = max

    def __iter__(self):
        return self

    def __next__(self):
        if self.n > self.max:
            raise StopIteration

        result = 2 ** self.n
        self.n += 1
        return result

Приведенная выше программа была длинной и запутанной. Теперь давайте сделаем то же самое, используя функцию-генератор.

def PowTwoGen(max=0):
    n = 0
    while n < max:
        yield 2 ** n
        n += 1

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

2. Эффективное использование памяти

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

Генераторная реализация таких последовательностей удобна для памяти и предпочтительнее, поскольку она создает только один элемент за раз.

3. Представлять бесконечный поток

Генераторы — отличные средства для представления бесконечного потока данных. Бесконечные потоки нельзя хранить в памяти, а поскольку генераторы производят только один элемент за раз, они могут представлять бесконечный поток данных.

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

def all_even():
    n = 0
    while True:
        yield n
        n += 2

4. Конвейерные генераторы

Можно использовать несколько генераторов для конвейерной последовательности операций. Лучше всего это проиллюстрировать на примере.

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

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

def fibonacci_numbers(nums):
    x, y = 0, 1
    for _ in range(nums):
        x, y = y, x+y
        yield x

def square(nums):
    for num in nums:
        yield num**2

print(sum(square(fibonacci_numbers(10))))

Вывод

4895

Эта конвейерная обработка эффективна и легко читается (и да, намного круче!).


Python

  1. Операторы Python
  2. Аргументы функции Python
  3. Словарь Питона
  4. Генераторы Python
  5. Замыкания Python
  6. Декораторы Python
  7. Лямбда-функции Python с ПРИМЕРАМИ
  8. Функция abs() в Python:примеры абсолютных значений
  9. Функция Python round() с ПРИМЕРАМИ
  10. Функция Python map() с ПРИМЕРАМИ