[코딩도장] day27. 파이썬 제너레이터 사용하기 - yield
■ 들어가기
- 파이썬 코딩 도장 (남재윤/길벗). 을 공부하며 정리하는 블로그
▶ Unit40. 제너레이터 사용하기
- 40.1 제너레이터와 yield 알아보기
- 40.2 제너레이터 만들기
- 40.3 yield from으로 값을 여러 번 바깥으로 전달하기
0. 들어가기
- 제너레이터는 이터레이터를 생성해주는 함수
- 이터레이터는 클래스에 __iter__, __next__, __getitem__ 메서드를 구현해야 하는 반면
- 제너레이터는 함수 안에서 yield 라는 키워드만 사용하면 됨
>> 40.1 제너레이터와 yield 알아보기 <<
- 사용법 : yield 값
목적 : yield에 대해 알아본다. | |
소스 (yield.py) | 결과 |
def number_generator() : yield 0 yield 1 yield 2 for i in number_generator() : print(i) |
0 1 2 |
1. 제너레이터 객체가 이터레이터인지 확인하기
- dir 함수로 메서드 목록 확인
- 목록 중 __iter__ 가 있다면 이터레이터 가능 객체
>>> g = number_generator() >>> g <generator object number_generator at 0x02A93030> >>> dir(g) ['__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__next__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw'] |
- 제너레이터 객체 g의 __next__ 를 호출하면 이터레이터와 마찬가지로 0, 1, 2가 반환되며 이후 StopIteration 예외 발생
>>> g.__next__() 0 >>> g.__next__() 1 >>> g.__next__() 2 >>> g.__next__() Traceback (most recent call last): File "<pyshell#85>", line 1, in <module> g.__next__() StopIteration |
2. for와 제너레이터
- 제너레이터 함수를 통해 제너레이터 객체(이터레이터)가 호출되면 yield에 정의된 값을 반환
- 현재 함수를 잠시 중단하고 함수 바깥의 코드가 실행되도록 한다..... √ 무슨 말인지 모르겠음..;;
3. yield의 동작 과정 알아보기
- 사용법
변수 = next(제너레이터객체)
목적 : yield 동작 과정을 알아본다. | |
소스 (yield_next.py) | 결과 |
def number_generator() : yield 0 yield 1 yield 2 g = number_generator() a = next(g) print(a) b = next(g) print(b) c = next(g) print(c) |
0 1 2 |
>> 40.2 제너레이터 만들기 <<
- range(횟수)와 같이 동작하는 기능 구현
목적 : 시퀀스 자료형인 range(횟수)와 동일한 기능을 하는 함수 확인 | |
소스 (generator.py) | 결과 |
def number_generator(stop) : n = 0 # 숫자는 0부터 시작 while n < stop : yield n n += 1 for i in number_generator(3) : print(i) |
0 1 2 |
- number_generator 함수의 인자값으로 3을 건넸으므로 0, 1, 2 3번 발생함
- yield가 3번 나오므로 for 반복문도 3번 반복
1. yield에서 함수 호출하기
소스 (generator_yield_function.py) | 결과 |
def upper_generator(x) : for i in x : yield i.upper() fruits = ['apple', 'pear', 'grape', 'pineapple', 'orange'] for i in upper_generator(fruits) : print(i) |
APPLE PEAR GRAPE PINEAPPLE ORANGE |
- 만약 upper_generator 함수 내 yield 말고 print(i.upper())로 하면 안될까??
>> 출력은 되는데 마지막에 TypeError 발생! 왜??
Traceback (most recent call last): File "C:/project/generator_yield_function.py", line 11, in <module> for i in upper_generator(fruits) : TypeError: 'NoneType' object is not iterable |
>> 40.3 yield from으로 값을 여러 번 바깥으로 전달하기 <<
- yield 뒤에 값을 한 개씩 지정 가능하므로 여러 번 바깥으로 전달 필요 시 for/while 반복문 사용
- BUT, yield from 키워드로 반복 출력할 변수만 지정하면 ok!
- 단, 파이썬 3.3버전 이상부터 가능하며 "반복 가능한 객체", "이터레이터", "제너레이터" 객체를 지정
- 사용법
yield from 반복가능한객체
yield from 이터레이터
yield from 제너레이터객체
소스 (generator_yield_from_iterable.py) | 결과 |
def number_generator() : x = [1, 2, 3] yield from x # 리트스에 들어있는 요소를 한 개씩 바깥으로 전달 for i in number_generator() : print(i) |
1 2 3 |
1. yield from에 제너레이터 객체 지정하기
소스 (generator_yieldl_from_generator.py) | 결과 |
def number_generator(stop) : n = 0 while n < stop : yield n n += 1 def three_generator() : yield from number_generator(3) for i in three_generator() : print(i) |
0 1 2 |