3 декабря 2012 г.

Send и next


Расширенный протокол функций-генераторов: send и next

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

При использовании расширенного протокола значения передаются генератору G вызовом метода G.send(value). После этого выражение yield возвращает значение, полученное от метода send. Когда вызывается обычный метод G.__next__() (или выполняется эквивалентный вызов next(G)), выражение yield возвращает None.
Например:

>>> def gen():
...     for i in range(10):
...         X = yield i
...         print(X)
...
>>> G = gen()
>>> next(G)    # Чтобы запустить генератор, необходимо сначала вызвать next()
0
>>> G.send(77) # Переход к следующему значению 
77             # и передача значения выражению yield
1
>>> G.send(88)
88
2
>>> next(G)    # next() и X.__next__() передают значение None
None
3

-------------------------------------------------------------------------

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


Выражения-генераторы итераторы и генераторы списков:
>>> [x ** 2 for x in range(4)]     # Генератор списков: создает список
[0, 1, 4, 9]
>>> (x ** 2 for x in range(4))     # Выражение-генератор: создает 
<generator object at 0x011DC648>   # итерируемый объект

>>> list(x ** 2 for x in range(4)) # Эквивалент генератора списков
[0, 1, 4, 9]

Использование протокола итераций для объекта сгенерированного списка:
>>> G = (x ** 2 for x in range(4))
>>> next(G)
0
>>> next(G)
1
>>> next(G)
4
>>> next(G)
9
и т.д.


Механика действий выражений-генераторов:
>>> for num in (x ** 2 for x in range(4)):
...     print(‘%s, %s’ % (num, num / 2.0))
...
0, 0.0
1, 0.5
4, 2.0
9, 4.5

Функции-генераторы и выражения-генераторы:
Например, четырежды повторим каждый символ в ис
ходной строке:
>>> G = (c * 4 for c in ‘SPAM’)  # Выражение-генератор
>>> list(G)                      # Принудительно получить сразу все результаты
[‘SSSS’, ‘PPPP’, ‘AAAA’, ‘MMMM’]

Аналог с использованием обьекта функции:
>>> def timesfour(S):  # Функция-генератор
...     for c in S:
...         yield c * 4
...
>>> G = timesfour(‘spam’)
>>> list(G)           # Выполнит итерации автоматически
[‘ssss’, ‘pppp’, ‘aaaa’, ‘mmmm’]

Ручная итерация:
>>> G = (c * 4 for c in ‘SPAM’)
>>> I = iter(G)        # Итерации выполняются вручную
>>> next(I)
‘SSSS’
>>> next(I)
‘PPPP’
>>> G = timesfour(‘spam’)
>>> I = iter(G)
>>> next(I)
‘ssss’
>>> next(I)
‘pppp’

Комментариев нет:

Отправить комментарий