How generator works in opcode

다음과 같이 두개의 yield 구문을 포함해서  함수를 정의한다.

def gen_1_2():

# print 'gen return', 1
 arg = yield 1
 # print 'gen got', arg

# print 'gen return', 2
 arg = yield 2
 # print 'gen got', arg

yield 구문을 포함한 function은 일반 함수처럼 호출되지 않고  generator를 리턴한다. opcode는 확인해 보면 다음과 같다.

gen = gen_1_2()
 print type(gen_1_2), type(gen), gen
 # <type 'function'> <type 'generator'> 
 print dis.disassemble(gen.gi_code)
 # 10 0 LOAD_CONST 1 (1)
 # 3 YIELD_VALUE
 # 4 STORE_FAST 0 (arg)

# 14 7 LOAD_CONST 2[ (2)
 # 10 YIELD_VALUE
 # 11 STORE_FAST 0 (arg)
 # 14 LOAD_CONST 0 (None)
 # 17 RETURN_VALUE

generator를 시작하기 위해서는 한가지 주의할 부분이 있다. 가장 처음 send를 호출할때 None value를 넘겨주어야 한다.
처음 send 이후에 last instruction을 확인해 보면(‘–>’를 가르키고 있는 곳) 첫번째 YIELD_VALUE opcode를 가르키고 있습니다.

# TypeError: can't send non-None value to a just-started generator
 # num = gen.send(11)
 print 'caller send None'
 num = gen.send(None)
 print 'caller got', num
 print "disassemble w/ lasti with gen", type(gen)
 print dis.disassemble(gen.gi_code, gen.gi_frame.f_lasti)
 # disassemble w/ lasti with gen <type 'generator'>
 # 10 0 LOAD_CONST 1 (1)
 # --> 3 YIELD_VALUE
 # 4 STORE_FAST 0 (arg)

# 14 7 LOAD_CONST 2 (2)
 # 10 YIELD_VALUE
 # 11 STORE_FAST 0 (arg)
 # 14 LOAD_CONST 0 (None)
 # 17 RETURN_VALUE

이제 2번째 send를 호출한 후 last instruction을 확인해 보면 2번째 YIELD_VALUE를 가르키고 있습니다.

caller = 21
print 'caller send', caller
num = gen.send(caller)
print 'caller got', num

print "disassemble w/ lasti with gen", type(gen)
print dis.disassemble(gen.gi_code, gen.gi_frame.f_lasti)
# caller send 21
# caller got 2
# disassemble w/ lasti with gen <type 'generator'>
# 10 0 LOAD_CONST 1 (1)
# 3 YIELD_VALUE
# 4 STORE_FAST 0 (arg)

# 14 7 LOAD_CONST 2 (2)
# --> 10 YIELD_VALUE
# 11 STORE_FAST 0 (arg)
# 14 LOAD_CONST 0 (None)
# 17 RETURN_VALUE

즉 YIELD_VALUE를 통해서 generator와 caller간에 context switch가 일어 나고 있는 것을 확인 할 수 있습니다.

Happy Coding~:)

Advertisements

About rookiecj

Hi all. Today is the day.
This entry was posted in python and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s