2017-04-13 10 views
5

yield from 문을 중첩 할 수 있습니까?중첩 "yield from"문 (생성자 위임)이 'None'값 종료를 생성하는 이유는 무엇입니까?

간단한 형태는 분명하다 : 나는 발전기를 중첩 한

0 
1 
2 

하지만 경우 : 생산

def try_yield1(): 
    x = range(3) 
    yield from x 

?

def try_yield_nested(): 
    x = [range(3) for _ in range(4)] 
    yield from ((yield from y) for y in x) 

이 생성됩니다

0 
1 
2 
None # why? 
0 
1 
2 
None # ... 
0 
1 
2 
None # ... 

나는 (이 중첩 된 경우에도) yield from를 사용하면 왜 None을 생산 하는가? 같은 출력 (인 내가 기대하는 것)을 None을 떠나 생산

from itertools import chain 

def try_yield_nested_alternative(): 
    x = [range(3) for _ in range(4)] 
    yield from chain.from_iterable(x) 

:

는 내가 뭔가를 할 수있어. 나는 중첩 된 위임을 사용하는 것이 더 파이썬 것이라고 생각 (바람직도 yield from x from y 또는 yield from x for x in y을, 그러나 그것은 올바른 구문되지 않습니다),

for x in [range(3) for _ in range(3)]: 
    yield from x 

그러나 : 나는 또한 간단한 루프를 작성할 수 있습니다. 내가 예상 한대로 작동하지 않는 이유는 무엇입니까?

답변

7

yield은 표현식입니다. send(value)이 무엇이든 평가할 것입니다. 간단히 말해서 아무 것도 보내지 않으면 yield의 값이 None이 될 것이므로 None 출력이 표시됩니다.

yield from 자체는 None과 같으며 두 개를 사용하고 있습니다. 두 번째 yield from에서는리스트를 반복하는 목록을 생성합니다. 목록의 항목을 사용하여 생성기를 입력하지만, yield from을 사용하여 해당 생성자 표현식을 반환합니다.이 생성기 표현식은 목록을 반환하고 각 반복마다 None과 동일합니다 , 따라서 각 항목 반복의 범위 후에 당신은 None을 얻는다. ,

  1. (yield from y) for y in x의 값을 산출한다 [0, 1, 2]
  2. yield from는 이전의 값을 산출하고, None 인 이전부터도 yield from :

    본질적이 발생되는 것이다.

  3. [0, 1, 2]로 평가 한 후 yield from로 인해 None을 추가하면 (yield from y) for y in x에 있습니다.

불행히도 표현의 특성으로 인해 None 출력을 제거 할 수있는 방법이 없습니다. from_iterable을 사용하는 것이 좋습니다.

수확량 표현을 설명하는 출처; https://docs.python.org/2.5/ref/yieldexpr.html