Yield — это ключевое слово в Python, которое используется для возврата из функции с сохранением состояния ее локальных переменных, и при повторном вызове такой функции выполнение продолжается с оператора yield, на котором ее работа была прервана. Любая функция, содержащая ключевое слово yield, называется генератором. Можно сказать, yield — это то, что делает ее генератором. Хотя оператор yield в Python не отличается популярностью, но он имеет множество достоинств, о которых стоит знать.
Код #1: Демонстрация работы yield
# Код на Python3 для демонстрации
# использования ключевого слова yield
# генерация нового списка, состоящего
# только из четных чисел
def get_even(list_of_nums) :
for i in list_of_nums:
if i % 2 == 0:
yield i
# инициализация списка
list_of_nums = [1, 2, 3, 8, 15, 42]
# вывод начального списка
print ("До фильтрации в генераторе: " + str(list_of_nums))
# вывод только четных значений из списка
print ("Только четные числа: ", end = " ")
for i in get_even(list_of_nums):
print (i, end = " ")
Вывод
До фильтрации в генераторе: [1, 2, 3, 8, 15, 42]
Только четные числа: 2 8 42
Код #2
# Данная Python программа выводит
# числа от 1 до 15, возведенные в куб,
# используя yield и, следовательно, генератор
# Функция ниже будет бесконечно генерировать
# последовательность чисел в третьей степени,
# начиная с 1
def nextCube():
acc = 1
# Бесконечный цикл
while True:
yield acc**3
acc += 1 # После повторного обращения
# исполнение продолжится отсюда
# Ниже мы запрашиваем у генератора
# и выводим ровно 15 чисел
count = 1
for num in nextCube():
if count > 15:
break
print(num)
count += 1
Вывод:
1
8
27
64
125
216
343
512
729
1000
1331
1728
2197
2744
3375
Преимущества yield:
- Поскольку генераторы автоматически сохраняют и управляют состояниями своих локальных переменных, программист не должен заботиться о накладных расходах, связанных с выделением и освобождением памяти.
- Так как при очередном вызове генератор возобновляет свою работу, а не начинает с самого начала, общее время выполнения сокращается.
Недостатки yield:
- Иногда использование yield может вызвать ошибки, особенно если вызов функции не обрабатывается должным образом.
- За оптимизацию времени работы и используемой памяти приходится платить сложностью кода, поэтому иногда трудно сходу понять логику, лежащую в его основе.
Практическое применение
Один из вариантов практического применения генераторов заключается в том, что при обработке большого объема данных и поиске в нем, выгодно использовать yield, так как зачастую нам не нужно повторно осматривать уже проверенные объекты. Такой подход значительно сокращает затраченное программой время. В зависимости от конкретной ситуации существует множество различных вариантов использования yield.
# Код Python3 для демонстрации
# использования ключевого слова yield
# Поиск слова pythonru в тексте
# Импорт библиотеки для работы
# с регулярными выражениями
import re
# Этот генератор создает последовательность
# значений True: по одному на каждое
# найденное слово pythonru
# Также для наглядности он выводит
# обработанные слова
def get_pythonru (text) :
text = re.split('[., ]+', text)
for word in text:
print(word)
if word == "pythonru":
yield True
# Инициализация строки, содержащей текст для поиска
text = "В Интернете есть множество сайтов, \
но только один pythonru. \
Программа никогда не прочтет \
последнее предложение."
# Инициализация переменной с результатом
result = "не найден"
# Цикл произведет единственную итерацию
# в случае наличия в тексте pythonru и
# не сделает ни одной, если таких слов нет
for j in get_pythonru(text):
result = "найден"
break
print ('Результат поиска: %s' % result)
Вывод
В
Интернете
есть
множество
сайтов
но
только
один
pythonru
Результат поиска: найден