2012-11-29 2 views
2

저는 파이썬 생성기의 미묘한 세부 사항을 이해하려고합니다.동일한 생성기에서 값을 보내고받는 것

def injector(): 
    while True: 
     try: 
      print 'a' 
      v = yield 
      print 'b', v 
      yield v 
      print 'c' 
     except GeneratorExit: 
      print 'exit' 
      break 

g = injector() 

print 'send none' 
g.send(None) 
print 'send 2' 
g.send(2) 
print 'receiving' 
v = g.next() 
print 'received', v 

g.close() 

이 프로그램에 대한 예상 출력은 다음과 같습니다 :

send none 
a 
send 2 
b 2 
receiving 
received 2 
c 
a 
exit 

테스트 프로그램 중 하나는 내가 모두 같은 발전기로/값을 전송하고 선택적으로 읽을 수 있다면 다음과 같은 것을 볼 쓴 내가 얻는 결과는 다음과 같습니다.

이제 분명히 위의 결과물을 얻을 수 있습니까? 발전기 작동 방식에 대해 내가 이해하지 못했던 것은 무엇입니까?

답변

3

이후에 굴복하지 않기 때문에 저를 명확히 해보자 검색 결과가 없습니다 : 여기

def injector(): 
    while True: 
     try: 
      print 'a' 
      v = yield 
      print 'b', v 
      yield v 
      print 'c' 
     except GeneratorExit: 
      print 'exit' 
      break 

g = injector() 

print 'send none' 
g.send(None) 

코 루틴이 시작됩니다. .send()에서 결과가 반환 된 첫 번째 수익률까지 실행되었지만 버려졌습니다.

코 루틴은 a을 인쇄하고 아무 것도 출력하지 않으므로 None입니다. 따라서 버리는 것은 좋습니다.

print 'send 2' 
g.send(2) 

여기서 coroutine에 2를 보내서 왼쪽에서 계속 진행합니다. v = 2.

2을 인쇄하고 v을 다시 산출합니다. 전화가 g.send() 일 것입니다. 그래서 수신 v을 폐기 한 후, 당신은 당신이 얻을 수있는, 다시 None을 산출, 다음은, 다음 ac을 인쇄 다시 코 루틴에 제어 할 수

print 'receiving' 
v = g.next() 

을한다. v에 따라서

print 'received', v 

인쇄 None. 당신은 아마 원하는 것은

g = injector() 

print 'send none' 
g.send(None) 
print 'send 2' 
v = g.send(2) 
print 'received', v 

g.close() 

입니다 (이하이 마지막 블록이 더 깨끗하게 잘 쓸 수 있습니다 :

from contextlib import closing 
with closing(injector()) as g: 
    print 'send none' 
    g.send(None) 
    print 'send 2' 
    v = g.send(2) 
    print 'received', v 

)

+1

주'그 다음에()' 'send (None)'과 정확히 같다. http://www.python.org/dev/peps/pep-0342/ – ecatmur

0

따라서 문제는 마지막 호출입니다. 먼저 코드가 중단 된 곳에서 시작하여 'c'을 먼저 인쇄하는 것으로 보입니다. 그런 다음 명령문이 생성되지 않았으므로 while 루프에서 계속 인쇄합니다 ('a'). 마지막으로 출력이 생성됩니다. 없음은 아무 것도 'a'

관련 문제