Эта задача — логическое продолжение предыдущей. Мы имеем дело с генераторной функцией.
Значения отправляются генератору G путем вызова
Значения отправляются генератору G путем вызова
G.send(значение)
. Затем код генератора возобновляет выполнение, и выражение yield
в генераторе возвращает значение, переданное send
. Если вызывается обычный метод G.__next_() (или его эквивалент next(G))
для продвижения вперед, тогда yield
просто возвращает None
.
>>> next(G) # Сначала должен вызываться next(), чтобы запустить генератор
... 0
>>> G.send(77)
... 77
... 1
1. Создание генератора:
В этой строке создается объект генератора
2. Первый вызов
Когда вы вызываете
3. Второй вызов
Теперь, когда вы вызываете
Затем генератор продолжает выполнение, и значение
G = gen()
В этой строке создается объект генератора
G
, но код внутри функции gen()
не начинает выполняться, пока не будет вызван next(G)
.2. Первый вызов
next(G
):
print(next(G)) # 0
Когда вы вызываете
next(G)
в первый раз, генератор начинает выполнение с начала функции gen()
. Внутри функции запускается цикл for
и выполняется первая итерация, где i
становится равным 0. Затем происходит yield i
, что означает, что значение 0 возвращается, и генератор приостанавливается. Значение 0 выводится на экран.3. Второй вызов
next(G)
:
print(next(G)) # None 1
Теперь, когда вы вызываете
next(G
) во второй раз, генератор продолжает выполнение с той точки, где он был приостановлен (после yield
). В этот момент выполнение доходит до X = yield i
, и так как вызывается next(G)
без передачи аргумента, X
будет установлено в значение None
. Затем срабатывает print(X)
, и выводится None
.Затем генератор продолжает выполнение, и значение
X
становится равным 1.Что выведет код?
Anonymous Quiz
40%
[0, 1, 4, 9]
13%
[1, 4, 9, 16]
44%
<generator object <genexpr> at 0x104....>
2%
Error
Понятия итерируемых объектов и списковых включений были объединены в инструмент — генераторные выражения. Синтаксически они похожи на нормальные списковые включения и поддерживают весь их синтаксис, в том числе фильтры if и вложение циклов, но они помещаются в круглые скобки, а не в квадратные (подобно кортежам объемлющие круглые скобки часто необязательны):
Для принудительного вырабатывания всех результатов сразу можно использовать list():
>>> (х ** 2 for х in range(4)) # Генераторное выражение создает итерируемый объект
... <generator object <genexpr> at 0x10250ab50>
Для принудительного вырабатывания всех результатов сразу можно использовать list():
>>> list(x ** 2 for х in range(4))
... [О, 1, 4, 9]
В задаче используется генератор, и происходит разбивка строки по запятой.
1. Разбивка строки:
Этот метод разбивает строку на список строк по разделителю.
2. Генератор:
Здесь создается генератор, который перебирает каждую строку из полученного списка
— Для х = "ааа" будет "ааа\n"
— х = "bbb" будет "bbb\n"
— Для х = "ссс" будет "ссс\n"
3. Распаковка значений:
В этом выражении используется распаковка, чтобы присвоить значения переменным а, b и с. Генератор будет предоставлять значения по одному:
— а получит значение "
— b получит значение "
— с получит значение "
1. Разбивка строки:
"ааа,bbb,ссс".split(",") # ["ааа", "bbb", "ссс"]
Этот метод разбивает строку на список строк по разделителю.
2. Генератор:
(х + "\n" for х in ...)
Здесь создается генератор, который перебирает каждую строку из полученного списка
["ааа", "bbb", "ссс"]
и добавляет к каждой строке символ новой строки "\n":— Для х = "ааа" будет "ааа\n"
— х = "bbb" будет "bbb\n"
— Для х = "ссс" будет "ссс\n"
3. Распаковка значений:
а, b, с = (х + "\n" for х in "ааа,bbb,ссс".split(","))
В этом выражении используется распаковка, чтобы присвоить значения переменным а, b и с. Генератор будет предоставлять значения по одному:
— а получит значение "
ааа\n
"— b получит значение "
bbb\n
"— с получит значение "
ссс\n
"Какого метода в pandas не существует?
Anonymous Quiz
6%
pd.read_excel
25%
pd.read_parquet
25%
pd.read_docx
45%
Все существуют
В каких контекстах может появиться генераторное выражение?
Anonymous Quiz
17%
Циклы for
7%
Функции sum, map, sorted
3%
Функции any, all, list
72%
Все вышеперечисленное
Генераторные выражения вместо построения результирующего списка в памяти возвращают объект генератора — автоматически созданный итерируемый объект. В свою очередь этот итерируемый объект поддерживает протокол итерации, чтобы выдавать по одной порции результирующего списка за раз в любом итерационном контексте.
Итерируемый объект также сохраняет состояние генератора, пока он действует — переменную х в предшествующих выражениях наряду с местоположением в коде генератора. Мы получаем обратно объект, который запоминает оставленное им место после возвращения каждой части результата:
Обычно мы не видим внутренний итерационный механизм next генераторного выражения вроде показанного, т.к. циклы for запускают его автоматически:
Так поступает каждый итерационный контекст: циклы
Итерируемый объект также сохраняет состояние генератора, пока он действует — переменную х в предшествующих выражениях наряду с местоположением в коде генератора. Мы получаем обратно объект, который запоминает оставленное им место после возвращения каждой части результата:
G = (х ** 2 for х in range (4))
next(G) is G # 0
next(G) is G # 1
next(G) is G # 4
next(G) is G # 9
next(G) is G # Остановка итерации
Обычно мы не видим внутренний итерационный механизм next генераторного выражения вроде показанного, т.к. циклы for запускают его автоматически:
for num in (х ** 2 for х in range (4)): # Автоматически вызывает next ()
print (’%s, %s’ % (num, num / 2.0))
Так поступает каждый итерационный контекст: циклы
for
, встроенные функции sum
, map
и sorted
, списковые включения и другие итерационные контексты, в том числе встроенные функции any
, all
и list
. Будучи итерируемыми объектами, генераторные выражения могут появляться в любом итерационном контексте подобного рода в точности как результат вызова генераторной функции.Чем списковое включение отличается от генераторного выражения?
Anonymous Quiz
13%
С. включение лучше подходит для больших объемов данных
68%
С. включение вычисляет список на месте
9%
Только с. включение способно принимать функции
11%
Ничем не отличается
Какой код исполнится медленнее остальных?
Anonymous Quiz
30%
1
43%
2
19%
3
9%
Скорость исполнения случайна
Приведенное далее списковое включение производит такой же результат, как показанные после него эквиваленты в форме тар из Python З.Х и генераторов, но создает два физических списка; остальные генерируют только по одному целому числу за раз с помощью вложенных генераторов, а форма генераторного выражения может более четко отражать свое намерение:
Хотя результатом всех трех форм является объединение операций, генераторы делают это, не создавая множество временных списков.
[х * 2 for х in [abs(x) for x in (-1, -2, 3, 4)]] # Вложенные включения
list(map(lambda x: x * 2, map(abs, (-1, -2, 3, 4)))) # Вложенные отображения
list(x * 2 for x in (abs(x) for x in (-1, -2, 3, 4))) # Вложенные генераторы
Хотя результатом всех трех форм является объединение операций, генераторы делают это, не создавая множество временных списков.