본문 바로가기
Python/파이썬 기초

이터레이터형과 제너레이터형 - 파이썬 기초(8)

by 콩돌 2018. 11. 18.
반응형

참고 자료

https://docs.python.org/3/library/stdtypes.html

https://mingrammer.com/translation-iterators-vs-generators/

https://nvie.com/posts/iterators-vs-generators/


파이썬 버전 3.7 기준



파이썬 자료형 및 연산자(7)


먼저 이터레이터와 제너레이터를 이해하기 위해서는 컨테이너(container)와 이터레이블(iterable)에 대한 개념을 먼저 배워놓으면 도움이 되므로 이부터 먼저 소개한다. 

컨테이너(container)
  ○ 컨테이너는 쉽게 설명하면 데이터를 담아두는 그릇이나 박스라고 생각하면 된다.
  ○ 대표적으로 리스트(list), 집합(set, frozenset), 튜플(tuple), 딕셔너리(dictionary), 문자열(str) 등과 같이 시퀀스형이나 메핑형 자료형이 포함된다.
  ○ 이론적으로는, 어떤 객체가 특정 원소를 포함하고 있는지 아닌지를 판단 할 수 있는 경우를 컨테이너라 지칭한다.
    ▷ in 사용할 수 있는 자료형이라 생각하면 된다.

● 요약: 컨테이너는 데이터를 담는 객체이다.

사용 예)
In[5]: a=[1,2,3]
In[6]: 1 in a
Out[6]: True

In[7]: b=set([1,2,3])
In[8]: 4 in b
Out[8]: False


이터레이블(iterable)
  ○ 이 단어의 의미를 가장 쉽게 설명하면 반복 가능하다는 것을 의미한다고 보여진다.
  ○ 이터레이터(iterator)의 사전적의미는 반복자이다. 즉 반복가능한 자료형을 의미한다.
  ○ 몇몇 컨테이너에서는 __iter__() 메서드를 포함하고 있고, 대부분의 시퀀스형 자료형(컨테이너)에 대해 iter()함수를 적용하여 이터레이터형 자료형을 형성할 수 있다.
    ▷ 이터레이블(iterable)한 상태는 iter함수나 메서드를 적용할 수 있는 상태 즉 이터레이터 자료형을 만들 수 있는 상태를 의미한다고 보여진다.
  ○ 그렇다면, 이터레이블 하다는 것은 iter함수나 메서드를 적용할 수 있는 컨테이너와 함수를 포함할 수 있다.
    ▷ 대부분의 시퀀스형 자료형에서는 iter함수가 적용이 가능하므로 대부분의 시퀀스 자료형은 이터레이블하다고 볼 수 있다.
    ▷ 함수 혹은 메서드에서는 대표적으로 readline()가 이터레이블 하다.
  ○ 좀 더 쉽게 설명하면 for 문을 통해 반복작업이 가능한 형태이면 이터레이블 하다고 볼 수 있다.
  ○ 아래 예는 __iter__() 메서드와 iter()함수를 적용할 수 있는 방법과 이것이 이터레이블 하다는 것을 보여주는 예이다. 사실상 list로 다시 전환이 되기때문에 실제 코딩에서는 큰 의미는 없으므로 메서드와 함수 사용 방법만 참고하자.

● 요약 : 이터레이블은 반복가능함을 의미하며, iter함수(메서드)가 적용 가능한 것들을 의미한다.
           : for문이 적용 가능한 객체면 이터레이블하다. 
 
사용 예)
In[13]: a=[1,2,3]
In[14]: list(a.__iter__())
Out[14]: [1, 2, 3]

In[15]: b=set([1,2,3])
In[16]: list(iter(b))
Out[16]: [1, 2, 3]

In[17]: with open('text.txt') as file:
     ...:     print(iter(file.readlines()))
     ...: 
<list_iterator object at 0x0425BA70>


이터레이터(iterator)형 
  ○ 이터레이터의 사전적 의미는 위에서 설명 바와 같고, 좀 더 자세히 설명하자면 특정 자료형 혹은 함수나 메서드의 결과를 반복가능하게 만들어줄 수 있는 자료형이다.
  ○ 이터레이터형 자료형을 만들기 위해서는 위에서 언급한 __iter__() 메서드나 iter()함수를 이용하면 된다.
  ○ 이터레이터형 자료형을 반복 가능한 형태로 만들기 위해 next() 함수 혹은 __next__() 메서드라는 특별한 장치를 제공한다. 
    ▷ next(x) 형태로 사용하거나 x.__next__()로 사용하면 된다. 
    ▷ next 함수/메서드는 이터레이터 내부의 요소를 하나씩 꺼내여 반환하며, 모든 요소를 다 꺼낸 후 next() 함수/메서드를 사용하는 것을 시도할 경우에는 StopIteration 예외가 발생한다.

 사용 예)
In[12]: a = [1,2,3]
In[13]: b=iter(a)
In[14]: next(b)
Out[14]: 1
In[15]: b.__next__()
Out[15]: 2
In[16]: b.__next__()
Out[16]: 3


제너레이터(generator)형
  ○ 제너레이터의 사전적의미는 생성자 즉 무언가 만들어내는 것을 의미한다.  
  ○ 이터레이터가 기존에 있는 요소를 하나씩 꺼내는 식으로 반환을 했다면, 제너레이터는 필요할 때마다 직접 생성하여 요소를 반환한다. 
  ○ 제너레이터의 구현 방법은 yield 함수를 통한 방법이 있다. 
    ▷ 함수 내부에 yield를 삽입하고, 특정 변수에 함수값을 정의할 경우 제너레이터형 자료형이 정의된다. 
    ▷ 아래 사용 예중 func1으로 설명을 하자면,
      1. 변수에 함수 값을 정의한다. (필요시 함수에 값을 넣는다.)
      2. k 값을 그냥 출력함으로써 제너레이터 자료형인 것을 확인할 수 있다.(굳이 할 필요 없지만 제너레이터 자료형을 보여주기 위함)
      3. 처음 next 함수를 통하여 첫번째 yield 결과 값을 도출하는 것을 확인할 수 있다.
      4. next 함수를 계속 사용함으로 통해 그 다음 yield값을 계속해서 반환한다. 
      5. 하지만 더 이상 불러올 yield가 없다면 이터레이터형과 마찬가지로 StopIteration 예외를 발생시킨다.
    ▷ yield를 통해 계속해서 다음 값을 생성하고 싶다면 아래 예 func2처럼 무한루프를 사용하는 것도 방법이다.

사용 예)
In[48]: def func1(k):
     ...:      yield k+1
     ...:      yield k+10
     ...:      yield k+100
    
In[49]: k = func1(1)
In[50]: print(k)
<generator object func2 at 0x04CFE810>
In[51]: print(next(k))
2
In[52]: print(next(k))
11
In[53]: print(next(k))
101

In[54]: def func2(a):
     ...:     while 1:
     ...:         a += 1
     ...:         yield a
     ...:  
In[55]: k = func2(1)
In[56]: print(next(k))
2
In[57]: print(next(k))
3
In[58]: print(next(k))
4
In[59]: print(next(k))
5
In[60]: print(next(k))
6
In[61]: print(next(k))
7
In[62]: print(next(k))
8
In[63]: print(next(k))
9
In[64]: print(next(k))
10



반응형

댓글