python

python 알고리즘 기초4 이터레이터(Iterator)+예제

멈머이 2023. 11. 16. 21:00
728x90

1. 0 이상 5 미만의 숫자를 나열하는 이터레이터

# 클래스 정의 하기
class MyIterator:
    ### 클래스 생성자 정의하기
    def __init__(self):
        self.current_value = 0
        
    ### 자신의 클래스를 반환하는 iter함수 정의
    def __iter__(self):
        return self
        
    ### 반복을 수행하는  next함수 정의
    def __next__(self):
        ### currnet_value의 값이 5보다 작을 떄까지 반복수행
        if self.current_value < 5:
            # - 반환할 변수에 current_value의 현재 값 저장
            result = self.current_value
            # - current_value의 현재값을 1증가
            self.current_value += 1
            # - result값 반환
            return result
        else:
            raise StopIteration

"이터레이터는 반복이 끝나면 종료시켜야 함, 종료시키는 방법은 강제로 오류 발생시킴"

### 이터레이터 실행 시키기
# - 클래스 생성하기
my_iterator = MyIterator()
for value in my_iterator:
    print(value)

결과 :

0
1
2
3
4

이터레이터 기능은 반복문 (for 또는 while)을 사용해야만 작동하는 기능이다.
최초 __ilter__() 함수를 호출하고, 출력 시 __next__() 함수가 한 번씩 수행하면서 값을 반환받아서 출력함.
한번 반환된 후 메모리는 초기화되며, 다음 반복 시 다시 메모리 사용
반복 수행하여 result값 출력하기

 

이터레이터를 사용하는 가장 큰 이유는 메모리를 효율적으로 사용할 수 있다는 것이다.

 

중간중간 작동하는 순서를 보기 위해 프린트함수를 써서 확인해 보겠다.

class MyIterator:
    def __init__(self):
        self.current_value = 0
        print(f"#1(__init__) : self={self} / self.current_value={self.current_value}")
        
    def __iter__(self):
        print(f"#2(__iter__) : self={self}")
        return self
        
    def __next__(self):
        print(f"#3(__next__) : self={self}")
        if self.current_value < 5:
            result = self.current_value
            self.current_value += 1
            print(f"#4 : resutl={result} / self.current_value={self.current_value}")
            return result
        else:
            print("#5 : StopIteration 예외발생!")
            raise StopIteration
my_iterator = MyIterator()

 

결과 : #1(__init__) : self=<__main__. MyIterator object at 0x0000021 C0442 B410> / self.current_value=0

 

결과를 출력하는 방법으로 한 번에 모든 값을 출력하는 법과 각각의 데이터로 뽑는 두 가지 방법이 있다.

*1번 방법 for문을 사용하여 한번에 출력

for value in my_iterator:
    print(value)

결과 : 

#2(__iter__) : self=<__main__. MyIterator object at 0x0000021 C0442 B410>
#3(__next__) : self=<__main__. MyIterator object at 0x0000021C0442B410>
#4 : resutl=0 / self.current_value=1
0
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C0442B410>
#4 : resutl=1 / self.current_value=2
1
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C0442B410>
#4 : resutl=2 / self.current_value=3
2
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C0442B410>
#4 : resutl=3 / self.current_value=4
3
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C0442B410>
#4 : resutl=4 / self.current_value=5
4
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C0442B410>
#5 : StopIteration 예외발생!

 

*2번 방법 각각의 데이터로 뽑기

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("이터레이터가 종료되었음.")

결과 : 

#3(__next__) : self=<__main__. MyIterator object at 0x0000021 C04704450>
#4 : resutl=0 / self.current_value=1
0
#3(__next__) : self=<__main__. MyIterator object at 0x0000021 C04704450>
#4 : resutl=1 / self.current_value=2
1
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C04704450>
#4 : resutl=2 / self.current_value=3
2
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C04704450>
#4 : resutl=3 / self.current_value=4
3
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C04704450>
#4 : resutl=4 / self.current_value=5
4
#3(__next__) : self=<__main__.MyIterator object at 0x0000021C04704450>
#5 : StopIteration 예외발생!/
이터레이터가 종료되었음.

자바의 try cath같이 파이썬에서는 try excep를 사용하여 예외 처리를 한다.

 

 

2. 두 개의 숫자(시작값, 종료값) 값을 이용해서, 짝수값만 반환하는 이터레이터

class EvenNumberIterator:
    def __init__(self, start, end):
        self.start = start
        self.end = end
    def __iter__(self):
        return self
    def __next__(self):
        ### start 부터 end까지 무조건 반복 샐행
        # - i 값은 사용안함
        # - 사용하는 값은 sel.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

 

 

3. 외부 함수를 이용해서 짝수값을 추출하는 이터레이터

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
### 짝수와 홀수로 판별하는 외부함수 정의하기
def is_even(num):
    return num%2 == 0
### 이터레이터 클래스 생성
even_iter = EvenNumberIterator(1, 10, is_even)

### 이터레이터 반복 수행하기
for even in even_iter:
    print(even)

결과 : 

2

4

6

8

10

 

 

4. 택스트 파일의 내용을 한 줄씩 변환하는 이터레이터

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):
        line = self.file.readline()
        if line:
            return line.strip()    
        else:
            self.file.close()
            raise StopIteration
### 이터레이터 클래스 생성하기
file_path = "./04_example.txt"
file_iter = FilelineIterator(file_path)
### 이터레이터 클래스 생성하기
file_path = "./04_example.txt"
file_iter = FilelineIterator(file_path)

결과 : 

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
sssssssssssssssssssssssssssssssssssssss
ddddddddddddddddddddddddddddddddddddddd
fffffffffffffffffffffffffffffffffffffff
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq

728x90