generator

박경은·2022년 1월 13일
0

제너레이터 사용하기

  • 제너레이터
    • 발생자
    • 이터레이터는 클래스에 iter, next 또는 getitem 메서드를 구현해야 하지만 제너레이터는 함수 안에서 yield라는 키워드만 사용하면 끝입니다. 그래서 제너레이터는 이터레이터보다 훨씬 간단하게 작성
    • 배열이나 리스트를 리턴하는 함수와 비슷하며, 호출을 할 수 있는 파라메터를 가지고 있고, 연속적인 값들을 만들어 낸다.→ but, yield 구문을 이용해 한 번 호출될 때마다 하나의 값만을 리턴해서 적은 메모리를 필요로 한다
  • 제너레이터 사용이유
    • 데이터셋이 클 때 메모리 문제 때문에 제너레이터 사용
  • 제너레이터 객체가 이터레이터인지 확인
    • yield를 사용해서 제너레이터를 만들고 for 반복문에서 0, 1, 2 숫자 세 개를 출력
>>> def number_generator():
>>>    yield 0
>>>    yield 1
>>>    yield 2
 
>>>for i in number_generator():
>>>    print(i)
0
1
2

>>> g = number_generator()
>>> g
<generator object number_generator at 0x03A190F0>
>>> 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']
  • yield의 동작 과정
    • yield가 호출된다고 해서 함수가 종료되는 것이 아니다
    • yield호출→함수 잠시 정지→next가 호출되면 정지된 시점부터 다시 로직 실행
    • return은 호출되면 바로 함수 종료
## next 함수로 __next__ 메서드를 직접 호출

>>> def number_generator():
>>>    yield 0    # 0을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
>>>    yield 1    # 1을 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
>>>    yield 2    # 2를 함수 바깥으로 전달하면서 코드 실행을 함수 바깥에 양보
 
>>>g = number_generator()
 
>>>a = next(g)    # yield를 사용하여 함수 바깥으로 전달한 값은 next의 반환값으로 나옴
>>>print(a)       # 0
 
>>>b = next(g)
>>>print(b)       # 1
 
>>>c = next(g)
>>>print(c)       # 2

0
1
2
  • 함수호출
#1

>>> def upper_generator(x):
>>>     for i in x:
>>>         yield i.upper()    # 함수의 반환값을 바깥으로 전달
 
>>> fruits = ['apple', 'pear', 'grape', 'pineapple', 'orange']
>>> f=upper_generator(fruits)
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))

APPLE
PEAR
GRAPE
PINEAPPLE
ORANGE

---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
/tmp/ipykernel_13/3198256348.py in <module>
     10 print(next(f))
     11 print(next(f))
---> 12 print(next(f))

StopIteration:

#2
>>> 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

#3
>>> my_nums = (x*x for x in [1, 2, 3, 4, 5]) 

>>> print(my_nums)

>>> for num in my_nums:
>>>     print(num)

<generator object <genexpr> at 0x7f07ec2fa0b0>
1
4
9
16
25

*list 표현식
>>> my_nums = [x*x for x in [1, 2, 3, 4, 5]]  

>>> print(my_nums)

>>> for num in my_nums:
>>>     print(num)
      
[1, 4, 9, 16, 25]
1
4
9
16
25

# 4 
# yield from 사용
>>> def upper_generator(x):
>>>     yield from fruits

>>> fruits = ['apple', 'pear', 'grape', 'pineapple', 'orange']
>>> f=upper_generator(fruits)
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))
>>> print(next(f))

APPLE
PEAR
GRAPE
PINEAPPLE
ORANGE

0개의 댓글