Генераторы облегчают создание итераций в Python и, в свою очередь, пишут меньше кода. Это руководство познакомит вас с генераторами Python, их преимуществами и тем, как они работают.
основы
Генератор — это функция, которая возвращает объект генератора, для которого вы можете вызвать метод next()
, чтобы при каждом вызове он возвращал значение или следующее значение. Обычная функция Python использует ключевое слово return
для возврата значений, но генераторы используют ключевое слово yield
для возврата значений. Это означает, что любая функция Python, содержащая оператор yield
является функцией генератора.
Оператор yield
обычно останавливает функцию и сохраняет локальное состояние, чтобы его можно было возобновить с того места, где оно было остановлено. Функции генератора могут иметь один или несколько операторов yield
.
Генератор также является итератором, но что такое итератор? Прежде чем мы углубимся в детали генераторов, я думаю, что важно знать, что такое итераторы, потому что они составляют неотъемлемую часть этого обсуждения.
Python Iterators
Итератор Python — это просто класс, который определяет __iter__()
. Большинство объектов Python являются итеративными, что означает, что вы можете перебирать каждый элемент в объектах. Примеры итераций в Python включают строки, списки, кортежи, словари и диапазоны.
Давайте рассмотрим пример ниже, в котором мы перебираем список цветов:
1
2
3
4
5
|
colors= [“red”,”blue”,”yellow”]
def my_funct():
for color in colors:
print color
|
За кулисами оператор for
вызовет iter()
для объекта списка. Затем функция вернет объект итератора, который определяет метод __next__()
, который затем будет обращаться к каждому цвету, по одному за раз. Когда не осталось больше цветов, __next__
stopIteration
исключение stopIteration
, которое, в свою очередь, будет информировать цикл for
о завершении.
Перебор словаря
1
2
3
4
5
6
7
8
|
d = {‘x’: 10, ‘y’: 20, ‘z’: 30}
for k,v in d.items():
print k, v
#result
# y 20
# x 10
# z 30
|
Перебор строк в файле CSV
1
2
3
4
5
6
|
import csv
with open(‘file.csv’, newline=») as File:
reader = csv.reader(File)
for row in reader:
yield row
|
Итерация по строке
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
my_string = ‘Generators’
for string in my_string:
print (string)
#result
# G
# e
# n
# e
# r
# a
# t
# o
# r
# s
|
Преимущества использования генераторов
Давайте обсудим некоторые преимущества использования генераторов по сравнению с итераторами:
Легко реализовать
Построение итератора в Python потребует от вас реализации класса с помощью __iter__()
и __next__()
а также позаботится о любых ошибках, которые могут вызвать ошибку stopIteration
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
class Reverse:
«»»Iterator for looping over a sequence backwards.»»»
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index — 1
return self.data[self.index]
|
Как вы можете видеть выше, реализация очень длинная. Все это бремя автоматически обрабатывается генераторами.
Меньшее потребление памяти
Генераторы помогают минимизировать потребление памяти, особенно при работе с большими наборами данных, потому что генератор будет возвращать только один элемент за раз.
Лучшая производительность и оптимизация
Генераторы ленивы по своей природе. Это означает, что они генерируют значения только тогда, когда это необходимо. В отличие от обычного итератора, где все значения генерируются независимо от того, будут ли они использоваться или нет, генераторы генерируют только необходимые значения. Это, в свою очередь, приведет к тому, что ваша программа будет работать быстрее.
Как создать генератор в Python
Создать генератор очень просто. Все, что вам нужно сделать, это написать обычную функцию, но с оператором yield
вместо оператора return
, как показано ниже.
1
2
|
def gen_function():
yield «python»
|
В то время как оператор return
полностью завершает функцию, yield
просто приостанавливает функцию до тех пор, пока она не будет снова вызвана методом next()
.
Например, в приведенной ниже программе используются операторы yield
и next()
.
01
02
03
04
05
06
07
08
09
10
|
def myGenerator(l):
total = 1
for n in l:
yield total
total += n
newGenerator = myGenerator([10,3])
print(next(newGenerator))
print(next(newGenerator))
|
Как работают генераторы Python
Посмотрим, как работают генераторы. Рассмотрим пример ниже.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
# generator_example.py
def myGenerator(l):
total = 0
for n in l:
total += n
yield total
newGenerator = myGenerator([10,20,30])
print(next(newGenerator))
print(next(newGenerator))
print(next(newGenerator))
|
В функции выше мы определяем генератор с именем myGenerator
, который принимает список l
в качестве аргумента. Затем мы определяем переменную total
и присваиваем ей значение ноль. Кроме того, мы перебираем каждый элемент в списке и затем добавляем его в общую переменную.
Затем мы newGenerator
экземпляр newGenerator
и вызываем метод next()
для него. Это будет запускать код до тех пор, пока не будет получено первое значение total
, которое в этом случае будет равно 0
Затем функция сохраняет значение общей переменной до следующего вызова функции. В отличие от обычного оператора return
, который будет возвращать все значения одновременно, генератор будет продолжать с того места, где он остановился.
Ниже приведены остальные последующие значения.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
# generator_example.py
def myGenerator(l):
total = 0
for n in l:
yield total
total += n
newGenerator = myGenerator([10,20,30])
print(next(newGenerator))
print(next(newGenerator))
print(next(newGenerator))
# result
# 0
# 10
# 30
|
Если вы попытаетесь вызвать функцию после завершения цикла, вы получите ошибку StopIteration
.
StopIteration
next()
StopIteration
чтобы сигнализировать, что итератор не производит никаких других элементов.
1
2
3
4
5
6
7
|
0
10
30
Traceback (most recent call last):
File «python», line 15, in <module>
StopIterationNormal function
|
Пример 2
В этом примере мы покажем, как использовать несколько операторов yield в функции.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
# colors.py
def colors():
yield «red»
yield «blue»
yield «green»
next_color =colors()
print(next(next_color))
print(next(next_color))
print(next(next_color))
# result
# red
# blue
# green
|
В то время как нормальная функция возвращает все значения, когда функция вызывается, генератор ждет, пока метод next()
будет вызван снова. Когда вызывается next()
, функция colors возобновляется с того места, где она остановилась.
Вывод
Генераторы более эффективны при использовании памяти, особенно при работе с очень большими списками или большими объектами. Это потому, что вы можете использовать выходы для работы с меньшими битами, вместо того, чтобы хранить все данные в памяти одновременно.
Кроме того, не забудьте посмотреть, что у нас есть в наличии для продажи и для изучения на Envato Market , и не стесняйтесь задавать любые вопросы и предоставлять ценные отзывы, используя канал ниже.
Кроме того, если вы чувствуете, что застряли, в разделе курса есть очень хороший курс по генераторам Python .