📍이터레이터는 init() 함수와next() 함수를 이용하여 반복(Iterator)을 수행함
📍__iter__() 메서드
iter 메서드는 이터레이터 객체 자체를 반환한다. 이터레이터 객체는 __iter__() 메서드를 가지고 있어야 한다. 이는 파이썬에서 "순회 가능한(iterable)" 객체의 특징이다.
📍__next__() 메서드
next 메서드는 다음 요소를 반환한다. 만약 더 이상 반환할 요소가 없으면 StopIteration 예외를 발생시켜 순회를 종료시킨다. 이 메서드가 호출될 때마다, 다음 요소를 반환하고 내부 상태를 업데이트하여 다음 호출 시에 이전 요소의 다음 요소를 반환할 수 있도록 한다.
반복문 사용하여 이터레이터 사용하기
### 클래스 정의하기
- 아래 코드는 MyIterator 클래스를 정의하고 객체를 생성한 후, for 루프를 사용하여 이터레이터를 순회하고 있다. 이터레이터 객체를 생성하면 __init__ 메서드가 호출되고, 그 후에 __iter__ 메서드가 호출되어 이터레이터 객체를 반환한다. 그리고 for 루프에서 각 단계마다 __next__ 메서드가 호출되어 반복이 수행된다. 반복이 끝나면 StopIteration 예외가 발생하여 순회가 종료된다
### 클래스 정의하기
class MyIterator :
### 클래스 생성자 정의하기
def __init__(self) :
self.current_value = 0
print(f"#1 (__init__) : self={self} / self.current_value={self.current_value}")
### 자신의 클래스를 반환하는 iter 함수 정의
def __iter__(self) :
print(f"#2 (__iter__) : self={self}")
return self
### 반복을 수행하는 next 함수 정의
def __next__(self) :
print(f"#3 (__next__) : self={self}")
### current_valu의 값이 5보다 작을 때까지 반복 수행
if self.current_value < 5 :
# - 반환할 변수에 current_value의 현재값 저장
result = self.current_value
# - result 값 반환
self.current_value += 1
print(f"#4 : result={result} / self.current_value={self.current_value}")
# - return 값 반환
return result
else :
print("#5 : StopIteration 예외 발생")
### 이터레이터는 반복이 끝나면 종료시켜야함
# - 종료시키는 방법은 강제로 오류 발생시킴
raise StopIteration
### 이터레이터 실행시키기
- 클래스 생성하기
my_iterator = MyIterator()
#1 (__init__) : self=<__main__.MyIterator object at 0x0000014EF4FF4510> / self.current_value=0
### 반복문 실행시키기
- 이터레이터 기능은 반복문(for or while)을 사용해야만 작동하는 기능임
- 최초 __iter__() 함수를 호출하고, 출력 시 __next__() 함수가 한 번씩 수행하면서 값을 반환받아서 출력함
#3 (__next__) : self=<__main__.MyIterator object at 0x0000014EF601D110> #5 : StopIteration 예외 발생 이터레이터 종료
간단 실습
### 이터레이터 클래스 생성해서 Hello 각 단어 출력하기
- 클래스 이름 : StringIterator
- 임의 문자열을 받아서 처리한다.
- 임의 문자열은 외부에서 클래스 생성 시 넣어준다.
내가 만든 코드
class StringIterator:
def __init__(self, word):
self.word = word
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.word):
result = self.word[self.index]
self.index += 1
return result
else:
raise StopIteration
- 코드실행
string_iter = StringIterator("안녕하세요")
for v in string_iter:
print(v)
안 녕 하 세 요
강사님 코드
- p_text 지역변수, 매개변수로써의 의미
- self.text 는 멤버 변수
- 둘이 저장되는 위치가 다름
class StringIterator_:
### 클래스 생성자
def __init__(self, p_text) :
# - next 함수에서 1씩 증가시키면서 반복 조건에 사용할 변수
self.index = 0
# - 받아온 문자열
self.text = p_text
### 반복수행을 위한 iter 함수 정의
def __iter__(self):
return self
### 한건 한건 처리를 위한 next 함수 정의
def __next__(self) :
if self.index < len(self.text) :
### 문자열에서 문자 하나씩 추출하기
result = self.text[self.index]
self.index += 1
return result
else:
raise StopIteration
- 코드 실행
### 이터레이터 기능 사용하기
# 반복문을 이용해서 추출하기
# - 클래스 생성하기
msg = "Hello"
string_iter_ = StringIterator_(msg)
### 이터레이터를 사용하지 않고 메모리 체크하기
@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
class EvenNumberIterator :
def __init__(self, start, end) :
self.start = start
self.end = end
def __iter__(self) :
return self
def __next__(self) :
if self.start <= self.end and self.start % 2 == 0 :
self.start % 2 == 0
result = self.start
self.start += 2
return result
else :
self.start += 1
raise StopIteration
- 코드 실행
num_iterator = EvenNumberIterator(1, 20)
for v in num_iterator :
print(v)
2 4 6 8 10 12 14 16 18 20
강사님 코드
class EvenNumberIterator :
def __init__(self, start, end) :
self.start = start
self.end = end
def __iter__(self) :
return self
def __next__(self) :
# - 사용하는 값은 self.start 값만 사용
for i in range(self.start, self.end, 1) :
### self.start가 짝수인지 체크
if self.start % 2 == 0:
### 반환할 변수에 저장
result = self.start
# - self.start값은 1 증가
self.start += 1
# - 반환하기 : 반환하면 for문은 종료됨
return result
### 짝수가 아니면
else :
# - 1증가만 시키고 반복을 계속 수행
self.start += 1
### for문을 이용한 경우에는, 이터레이터 반복 종류 후 마지막에 아래 추가
raise StopIteration
- 코드 실행
even_iter = EvenNumberIterator(1, 10)
for even in even_iter :
print(even)
2 4 6 8
외부 함수를 이용해서 짝수값 추출하는 이터레이터 만들기
1. 이터레이터 클래스 생성하기
class EvenNumberIterator :
### 클래스 생성자 정의
def __init__(self, start, end, func):
# - 시작값
self.start = start
# - 종료값
self.end = end
# - 외부함수
self.func = func
### 반복을 위한 이터레이터 함수 정의
def __iter__(self):
return self
### 반복 결과값을 처리할 함수 정의
def __next__(self):
### 시작부터 종료까지 while 반복
while self.start <= self.end :
### 외부함수로 짝수 or 홀수 체크
# - 짝수면 True, 홀수면 False
if self.func(self.start) :
result = self.start
self.start += 1
return result
else :
self.start += 1
### 이터레이터 종료하기
raise StopIteration
2. 짝수와 홀수를 판별하는 외부함수 정의하기
def is_even(num) :
return num % 2 == 0
3. 이터레이터 클래스 생성하기
- 함수 이름을 그대로 변수로 넣으면 함수 자체를 실행
even_iter = EvenNumberIterator(1, 10, is_even)
### 이터레이터 반복 수행하기
for v in even_iter :
print(v)
텍스트 파일의 내용을 한줄씩 반환하는 이터레이터 만들기
1. 이터레이터 클래스 생성하기
- 파일명은 클래스가 받아서 처리
- readline() : 파일 정보중에 줄 하나 가지고 오는 함수
>> 최초 이후부터는 다음 줄이 있는지 자동으로 체크 후 가지고 온다
>> 다음 줄이 없으면 안가지고 온다.
class FileLineIterator :
def __init__(self, file_path) :
# 파일 경로를 인스턴스 변수에 저장
self.file_path = file_path
# 파일 열기
self.file = open(file_path, "r", encoding = "utf-8")
def __iter__(self):
return self
def __next__(self):
print("#1 ---------------------")
# 파일에서 한 줄 읽어오기
line = self.file.readline()
# 읽어온 줄이 있으면 반환하고, 없으면 종료
if line:
# strip은 문자열의 양 끝에서 공백 문자(공백, 탭, 개행문자 등)을 제거하는 역할
return line.strip()
else :
# 파일 닫기와 StopIteration 예외 발생
print("#4 : 이터레이터 종료")
self.file.close()
raise StopIteration