안녕하세요!
python Iterator(이터레이터)정리1 메모리 사용량 확인 본문
이터레이터
- 파이썬에서 반복 가능한 객체(클래스)를 표현하는데 사용되는 인터페이스
- 이터레이터는 iter()함수와 next() 함수를 이용하여 반복(Iterator)을 수행함.
이터레이터를 사용하는 이유를 세가지로 정리해보자면, 메모리의 효율성과 코드의 간결성, 그리고 특정한 조건동안 무한히 반복되는 요소를 처리하기 좋기 때문이다.
앞에서 언급했던 데코레이터는 내부함수로 메모리의 효율성을 줄였다면, 이터레이터는 클래스기준으로 사용을 하며 iter함수와 next함수로 (쌍으로 동반된다) 반복을 수행한다. 이를 통해 메모리에 계속적으로 올라가있지 않으며 for문대신하여 iter와 next함수가 사용되므로 간결해진다.
예를 들자면,
# 클래스 정의
class MyIterator:
def __init__(self) :
self.current_value = 0
def __iter__(self) :
return self
def __next__(self) :
if self.current_value < 5:
result = self.current_value
self.current_value += 1
return result
else:
print(f'#5 : iterator 종료 예외 발생!!')
raise StopIteration
my_iterator = MyIterator()
<__main__.MyIterator object at 0x000001EDEEBCE810>
이터레이터는 위에서 언급했듯, iter함수와 next함수가 동반된다. 이터레이터는 반복이 끝나면 종료시켜줘야 하는데, 이때강제로 오류를 발생시킨다. 해당 함수에서는 StopIteration으로 종료시켰다.
for value in my_iterator :
print(value)
0
1
2
3
4
#5 : iterator 종료 예외 발생!!
이런식으로 6번째부터는 종료 예외발생으로 결과가 나온다.
for문으로 원하는 숫자까지 실행한 뒤 오류로 종료시키는 방법도 있지만 한번씩 따로 실행시키는 경우도 존재한다.
print(next(my_iterator))
0
해당하는 방법으로 여러번 실행시켰을 시, 마찬가지로 숫자가 증가하고 5번이후인 6번부터는 오류가발생한다.
오류로 강제 종료시켰기에 우리는 예외처리를 이용하여 종료시 다른 문구를 보여주며 처리할 수 있다.
try :
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
print(next(my_iterator))
except :
print("~ ~ 이 터 레 이 터 종 료 ~ ~ ")
0
1
2
3
4
~ ~ 이 터 레 이 터 종 료 ~ ~
<예제> 문자열을 전달 받아서 문자 하나씩 추출하여 반환하는 이터레이터 생성하기
# 문자열 "Hello" 의 각 문자 하나씩 출력하는 프로그램을 작성해주세요
a = "Hello"
for i in a :
print(i)
H
e
l
l
o
예제의 문제처럼 Hello를 for문을 이용, index로 문자를 추출하면 이러한 결과를 얻을 수 있다.
이를 이터레이터로 표현하자면,
class StringIterator :
def __init__(self, text) :
self.text = text
self.num = 0
def __iter__(self) :
return self
def __next__(self) :
if self.num < len(self.hi) :
result = self.hi[self.num]
self.num += 1
return result
else:
raise SyntaxError
Stringiterator = StringIterator()
print(Stringiterator)
<__main__.StringIterator object at 0x000001EDEEF02B90>
for i in Stringiterator :
print(i)
H
e
l
l
o
이런식으로 가능하다.
여기서 제일 궁금한점은 메모리 사용량 일텐데, 그렇다면 메모리 사용량이 얼마나 차이나는지를 실험해보자.
이를 위해선 라이브러리를 하나 설치해줘야한다.
pip install memory-profiler
우리수업은 쥬피터노트북에서 진행하기때문에, 파이썬과 조금 실행과정이 달랐다. 해당하는 라이브러리를 임포트한다.
from memory_profiler import profile
이후 아랫줄처럼 입력해준다.
%load_ext memory_profiler
이제 코드를 작성후 메모리사용량을 체크해보자.
class SimpleIterator :
def __init__(self, limit) :
### 반복 범위를 지정할 값(반복의 끝 값)
self.limit = limit
self.current = 0
def __iter__(self) :
return self
def __next__(self) :
if self.current < self.limit :
self.current += 1
return self.current
else:
raise StopIteration
### 이터레이터를 사용하지 않고 메모리 사용량 확인하기
@profile
def no_iterator(limit) :
data = [i for i in range(1, limit + 1)]
### 이터레이터를 사용해서 메모리 사용량 확인하기
@profile
def yes_iterator(limit) :
data = SimpleIterator(limit)
for item in data :
pass
해당 실험은 100만번 반복만 처리하고 별도 출력은 없는상황으로 진행했다.
#데코레이터 함수 호출
limit = 1000000
try:
%memit no_iterator(limit)
%memit yes_iterator(limit)
except:
pass
ERROR: Could not find file C:\Users\user\AppData\Local\Temp\ipykernel_10084\2087811373.py
peak memory: 120.75 MiB, increment: 27.62 MiB
ERROR: Could not find file C:\Users\user\AppData\Local\Temp\ipykernel_10084\2087811373.py
peak memory: 94.75 MiB, increment: 0.00 MiB
자 이제 결과를 살펴보자. no_iterator와 yes_iterator의 차이는 두가지가 보인다. 피크메모리가 약 33% 차이나며, increment또한 27.62mb : 0mb다.
해당 결과로 보자면 지속적으로 사용하면 나중에 no_iterator의경우는 컴퓨터가 다운되는경우를 맞이할 수 있다는 사실이 도출된다.
분량이 너무 많으므로 2편으나눠서 진행하도록 하겠다.
'개발일지 > python' 카테고리의 다른 글
python generator(제너레이터) 간단 정리 (0) | 2023.11.16 |
---|---|
python Iterator(이터레이터)정리2 짝수반환, 텍스트 추출 (0) | 2023.11.16 |
python decorator(데코레이터) 간단 정리 (0) | 2023.11.15 |
python closure(클로저)를 알아보자 (2) | 2023.11.14 |
python 클래스를 이용한 도서 키오스크 만들기. (2) | 2023.11.13 |