Python iterator - "yield "キーワードの役割は?

Python generator class / python / iterator / generator / yield / coroutine

Pythonでの yield キーワードの使用とは何ですか?それは何をしますか?

たとえば、私はこのコードを理解しようとしています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:]))