coroutine - python - 파이썬 제너레이터 출력 - "수익"키워드의 기능은 무엇입니까?

Yield 구문 / python / iterator / generator / yield

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
>>> def func():
...     yield 'I am'
...     yield 'a generator!'
... 
>>> type(func)                 # yield를 가진 함수는 여전히 함수입니다
<type 'function'>
>>> gen = func()
>>> type(gen)                  #하지만 생성기를 반환합니다.
<type 'generator'>
>>> hasattr(gen, '__iter__')   # 반복 가능합니다.
True
>>> hasattr(gen, 'next')       # 및 .next (Python 3에서는 .__ next__)
True                           # implements the iterator protocol.

생성기 유형은 반복기의 하위 유형입니다.

>>> import collections, types
>>> issubclass(types.GeneratorType, collections.Iterator)
True

필요한 경우 다음과 같이 유형을 확인할 수 있습니다.

>>> isinstance(gen, types.GeneratorType)
True
>>> isinstance(gen, collections.Iterator)
True
>>> list(gen)
['I am', 'a generator!']
>>> list(gen)
[]

기능을 다시 사용하려면 다른 기능을 만들어야합니다 (각주 2 참조).

>>> list(func())
['I am', 'a generator!']

다음과 같이 프로그래밍 방식으로 데이터를 생성 할 수 있습니다.

def func(an_iterable):
    for item in an_iterable:
        yield item
def func(an_iterable):
    yield from an_iterable
def bank_account(deposited, interest_rate):
    while True:
        calculated_interest = interest_rate * deposited 
        received = yield calculated_interest
        if received:
            deposited += received


>>> my_account = bank_account(1000, .05)
>>> first_year_interest = next(my_account)
>>> first_year_interest
50.0
>>> next_year_interest = my_account.send(first_year_interest + 1000)
>>> next_year_interest
102.5

def money_manager(expected_rate):
    # .send ()로부터 입금액을 받아야합니다 :
    under_management = yield                   # yield None to start.
    while True:
        try:
            additional_investment = yield expected_rate * under_management 
            if additional_investment:
                under_management += additional_investment
        except GeneratorExit:
            '''TODO: write function to send unclaimed funds to state'''
            raise
        finally:
            '''TODO: write function to mail tax info to client'''
        

def investment_account(deposited, manager):
    '''very simple model of an investment account that delegates to a manager'''
    # 관리자를 큐업해야합니다.
    next(manager)      # <-manager.send (None)과 동일
    # 관리자에게 초기 입금을 보내는 곳 :
    manager.send(deposited)
    try:
        yield from manager
    except GeneratorExit:
        return manager.close()  # 대리인?

이제 기능을 하위 생성기에 위임 할 수 있으며 위와 같이 생성기에서 사용할 수 있습니다.

my_manager = money_manager(.06)
my_account = investment_account(1000, my_manager)
first_year_return = next(my_account) # -> 60.0

이제 계정에 1,000을 더 추가하고 계정 수익 (60.0)을 추가하는 것을 시뮬레이션합니다.

next_year_return = my_account.send(first_year_return + 1000)
next_year_return # 123.6
my_account.close()

생성기에서 처리하거나 사용자에게 다시 전파 할 수있는 예외를 throw 할 수도 있습니다.

import sys
try:
    raise ValueError
except:
    my_manager.throw(*sys.exc_info())
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "<stdin>", line 6, in money_manager
  File "<stdin>", line 2, in <module>
ValueError

문법은 현재 목록 이해의 모든 표현을 허용합니다.

expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
                     ('='(수율 _ 표현식 | testlist_star_expr)) *)
...
yield_expr: '수율'[yield_arg]
yield_arg: '에서'테스트 | 테스트 목록

예를 들어, range 객체는 재사용이 가능하기 때문에 반복 가능하더라도 Iterator 가 아닙니다 . 목록과 마찬가지로 __iter__ 메서드는 반복기 객체를 반환합니다.