반복자가 또 다른 제너레이터인 경우, 하위 제너레이터의 본체가 yield from 표현식의 대상 안에 들어 가는 것과 동일한 효과가 발생하고 하위 제너레이터는 값을 가진 return문을 이용해서 값을 반환하며 yield from표현식의 값이 된다.
동작 특징
하위 제너레이터가 생성하는 값은 모두 제너레이터의 호출자에 바로 전달
send()를 통해 대표 제너레이터에 전달한 값은 모두 하위 제너레이터에 직접 전달되고, 값이 None이면 하위 제너레이터의 next() 메서드가 호출된다.
제너레이터나 하위 제너레이터에서 return expr 문을 실행하면, 제너레이터를 빠져나온 후 StopIteration(expr) 예외가 발생
하위 제너레이터가 실행을 마친 후 발생한 StopIteration 예외의 첫 번째 인수가 yield from 표현식의 값이 된다.
동작처리 중 예외
대표 제너레이터에 던져진 GeneratorExit이외의 하위 제너레이터의 throw()메서드에 전달된다. throw()메서드를 호출해서 StopIteration 예외가 발생하면 대표 제너레이터의 실행이 재개되고, 예외는 대표 제너레이터에 전달
GeneratorExit 예외가 대표 제너레이터에 던져지거나 대표 제너레이터의 close() 메서드가 호출되면 하위 제너레이터의 close() 메서드가 호출되고, 그 결과 예외가 발생하면 발생한 예외가 대표 제너레이터에 전파가 되며 그렇지 않을 경우 제너레이터에서 GeneratorExit 예외가 발생한다.
RESULT = yield from EXPR
#대표 제너레이터 안의 RESULT = yield from EXPR 문에 해당하는 단순화한 의사코드, 여깃선 단순화한 가정에 따라 thorw()와 close() 메서드를 지원하지 않고, StopIteration예외만 지원한다.
_i = iter(EXPR)
try:
_y = next(_i)
except StopIteration as _e:
_r= _e.value
else:
while 1:
_s = yield _y
try:
_y = _i.send(_s)
except StopIteration as _e:
_r = _e.value
break
RESULT = _r
RESULT = yield from EXPR
#대표 제너레이터에서 RESULT = yield from EXPR문과 대등한 의사코드
_i = iter(EXPR)
try:
_y = next(_i)
except StopIteration as _e:
_r = _e.value
else:
while 1:
try:
_m = _i.close
except AttributeError:
pass
else:
_m()
raise _e
except BaseException as _e:
_x = sys.exc_info()
try:
_m = _i.thorw
except AttributionError:
raise _e
else:
try:
_y = _m(*_x)
except StopIteration as _e:
_r = _e.value
break
else:
try:
if _s is None:
_y = next(_i)
else:
_y = _i.send(_s)
except StopIteration as _e:
_r = _e.value
break
RESULT = _r