iterator - бесконечный генератор python - Что делает ключевое слово "yield"?

iter python / python / generator / yield / coroutine

Какое использование ключевого слова yield в Python и что оно делает?

Например, я пытаюсь понять этот код 1 :

def _get_child_candidates(self, distance, min_dist, max_dist):
    if self._leftchild and distance - max_dist < self._median:
        yield self._leftchild
    if self._rightchild and distance + max_dist >= self._median:
        yield self._rightchild  

А это звонящий:

result, candidates = [], [self]
while candidates:
    node = candidates.pop()
    distance = node._get_dist(obj)
    if distance <= max_dist and distance >= min_dist:
        result.extend(node._values)
    candidates.extend(node._get_child_candidates(distance, min_dist, max_dist))
return result

iliketocode



Answer #1

В продолжении стиля передачи (CPS)продолжения являются обычными функциями (только в языках,где функции являются первоклассными),которые программист явно управляет и передает подпрограммам.В этом стиле состояние программы представлено замыканиями (и переменными,которые в них кодируются),а не переменными,которые находятся где-то на стеке.Функции,управляющие потоком управления,принимают продолжения в качестве аргументов (в некоторых вариациях CPS функции могут принимать несколько продолжений)и манипулируют потоком управления,просто вызывая их и возвращаясь после.Очень простым примером стиля передачи продолжений является следующий:

def save_file(filename):
  def write_file_continuation():
    write_stuff_to_file(filename)

  check_if_file_exists_and_user_wants_to_overwrite(write_file_continuation)

Теперь поговорим о генераторах в Python. Генераторы - это особый подтип продолжения. В то время как продолжения обычно могут сохранять состояние вычисления (т. Е. Стек вызовов программы), генераторы могут сохранять только состояние итерации по итератору . Хотя это определение немного вводит в заблуждение для некоторых случаев использования генераторов. Например:

def f():
  while True:
    yield 4
class Generator():
  def __init__(self,iterable,generatorfun):
    self.next_continuation = lambda:generatorfun(iterable)

  def next(self):
    value, next_continuation = self.next_continuation()
    self.next_continuation = next_continuation
    return value
def generatorfun(iterable):
  if len(iterable) == 0:
    raise StopIteration
  else:
    return (iterable[0], lambda:generatorfun(iterable[1:]))