본문 바로가기
AI 공부/파이썬

파이썬 (iterable & iterator와 Generator)

by AI Sonny 2022. 8. 9.
728x90

iterable & iterator

  • iterable 객체: 반복 가능한 객체(list,dict,set,tuple,str,range...)
  • iterator 객체: 값을 차례대로 꺼낼 수 있는 객체
    • 다 꺼내면 사라진다.
    • 꺼낼 때 데이터를 메모리에 생성해주는 방식
    • 꺼낼 수 있는 상태

 

- iter 함수

  • iterable 객체를 iterator 객체로 변환한다.
lst = [1,2,3]
iterator = iter(lst)
type(iterator)

=> list_iterator

 

 

for 문은 iterable, iterator 객체를 모두 반복해줄 수 있다.

 

for i in lst:
    print(i)
    
=>	1
	2
	3

 

 

- next 함수

  • iterator 객체를 순서대로 하나씩 꺼내주는 함수이다.
lst = [1,2,3]
iterator = iter(lst)

print(next(iterator))
print(next(iterator))
print(next(iterator))
print(next(iterator))   # 더이상 꺼낼 수 없어서 에러 발생!

=>	1
	2
	3
	---------------------------------------------------------------------------
	StopIteration                             Traceback (most recent call last)
	<ipython-input-14-7692d63fe37d> in <module>()
	      5 print(next(iterator))
	      6 print(next(iterator))
	----> 7 print(next(iterator))   # 더이상 꺼낼 수 없어서 에러 발생!

	StopIteration:

 

이와 같이 next 함수는 꺼낼 수가 없는 경우 에러가 발생한다.

 

그래서 출력값을 보면 1,2,3까지만 나오고 이 후에는 에러가 발생하는 것을 볼 수 있다.

 

next 함수는 zip 함수, enumerate함수와 같이도 쓸 수 있다.

 

또한 next 함수는 iterator 객체만 꺼낼 수 있다.

 

예시

 

next([1,2,3])

=>	File "<ipython-input-26-170b95b367ee>", line 1
  	next([1,2,3]
	            ^
	SyntaxError: unexpected EOF while parsing

 


 

Generator란?

  • iterator 를 생성해주는 표현식
  • iterator와 같은 동작을 하는 객체

- 소괄호를 이용한 제너레이터 객체 만드는 예시

 

gen = (x for x in range(3)) # 상태만 있고 꺼낼때마다 동작한다.
type(gen)

=> generator

'%%timeit'을 이용하여 속도를 비교하였을 때 제너레이터가 일반 for문보다 느렸다.

 

왜냐하면 객체가 생성된게 아니기 때문에 꺼낼 때마다 생성해야되기 때문에 느렸다.

 

그러나 메모리사이즈를 sys를 이용하여 비교하면 제너레이터가 리스트 컴프리헨션보다 빠르다는 특징이 있다.

 

예시

 

소괄호를 이용해서 다음의 리스트의 요소들의 제곱근을 꺼내는 제너레이터를 생성하시오.

 

lst = [20,40,60,80,34,90,10]

 

lst = [20,40,60,80,34,90,10]
gen = (x**0.5 for x in lst)

for i in gen:   # 제너레이터의 출력 방식
    print(i)
    
=>	400
	1600
	3600
	6400
	1156
	8100
	100

함수를 이용한 제너레이터 객체 만들기

  • yield 문을 이용하면 된다.
  • 쉽게 return과 비슷하다고 보면 된다.

yield는 함수 내부에서 함수 외부로 값을 순차적으로 전달하지만

 

return은 함수가 호출되면 값을 반환하고 함수를 종료시킨다.

 

또한 제너레이터 객체를 만들게 되면 이를 꺼내줄 for문이 필요하다.

 

그래서 결과값을 보고 싶으면 for문을 사용하여 출력해야한다.

 

예시

 

리스트를 입력 받아 None 값을 제외하고 꺼내주는 제너레이터를 생성하시오.


yield 문을 이용해서 함수로 만드세요.

 

lst = ["사과","딸기",None,"참외",None,"수박"]

def gen_list(lst):
    for i in lst:
        if i != None:
            yield i # yield앞에서 멈춘다.그래서 꺼내줄 무언가가 필요하다.
            		# yield 를 만나면 제너레이터로 변환
                    
gen = gen_list(lst)
for s in gen:   # 꺼내주기 위해 for문 구현
    print(s)
    
=>	사과
	딸기
	참외
	수박

 

- yield from 이용해서 간단히 제너레이터 만들기

 

from을 넣는 이유는 from을 이용해서 내가 설정한 곳으로 받아온 값을 yield 해주기 위해서이다.

 

예시

 

def gen_func(num):
    yield from range(num) # from 다음 iterable한 객체넣기
    
 gen = gen_func(5)
 for n in gen:
    print(n)
    
=>	0
	1
	2
	3
	4

 

이와 같이 range(5)로부터 받아온 값을 yield해준다는 것을 볼 수 있다.

 


 

이번에는 제너레이터에 대해 배웠는데 전보다 이해하는데 수월했다.

 

복습을 한 것이 크게 작용되어 강사님이 내주신 문제를 풀 수 있었다.

 

뿌뜻함을 느낄 수 있던 오전이였다.

 

728x90

댓글