티스토리 뷰

1. 이터레이터

- Iterator란?

- next 함수 호출 시 계속 그 다음 값을 리턴하는 객체

 

1) 리스트는 이터레이터일까?

a= [1,2,3]
next(a) # error

- 반복가능하다고해서 이터레이터는 아니다

 

2) 특징 : for문이나 next로 그 값을 한 번 읽으면 그 값을 다시는 읽을 수 없다

- next() 로 읽기

ia = iter(a)
type(ia) # list_interator

next(ia) # 1
next(ia) # 2
next(ia) # 3
next(ia) # error:StopIteration

 

- for문으로 읽기

a = [1,2,3]
ia = iter(a)

for i in ia:
    print(i)

#1
#2
#3
    
for i in ia:
    print(i)
    
# 출력 없음

 

3) 왜 사용할까?

- 메모리를 아낄 수 있고, 무한한 데이터도 다를 수 있다.

- 리스트를 만들면 모든 데이터를 메모리에 저장해야 한다.

- 이터레이터는 필요한 순간에만 데이터를 만들어 메모리를 절약할 수 있다.

class AppleIterator:
    def __init__(self):
        self.current = 1  # 현재 숫자
        self.end = 100    # 마지막 숫자

    def __iter__(self):
        return self  # 이터레이터 객체 자체를 반환

    def __next__(self):
        if self.current <= self.end:  # 끝에 도달하지 않았다면
            result = self.current    # 현재 값을 저장
            self.current += 1        # 다음 값을 준비
            return result            # 현재 값을 반환
        else:
            raise StopIteration       # 끝났음을 알림


# 이터레이터 객체 생성
apples = AppleIterator()

# 이터레이터 사용
print(next(apples))  # 1
print(next(apples))  # 2
print(next(apples))  # 3

 

4) python 내장 이터레이터

이터레이터 기능
range() 숫자 시퀀스를 생성
enumerate() 인덱스와 값을 동시에 반환
zip() 여러 이터러블 객체를 병렬처리
iter() 반복 가능한 객체를 이터레이터로 변환
map() 함수를 적용하여 이터레이터 반환
filter() 조건에 맞는 값을 이터레이터로 반환

 

2. 제너레이터

- 이터레이터를 생성해주는 함수

- 메모리에는 필요한 값만 저장되서 안전하다

- 제너레이터로 생성한 객체는 이터레이터와 마찬가지로 next 함수 호출 시 그 값을 차례대로 얻을 수 있다

- 일반 함수는 return을 만나면 종료되고, 다시 호출하면 처음부터 실행된다

- 제너레이터는 yield를 만나면 값을 반환하고, 멈춘 위치에서 다음 호출 때부터 이어서 실행된다. 

def generate_numbers():
    for x in range(5):
        yield x * x

gen = generate_numbers()  # 아무 계산도 하지 않음
print(next(gen))  # 0 계산됨
print(next(gen))  # 1 계산됨

 

1) 왜 쓸까?

- 메모리의 효율성

- 코드 단순화

- 지연 평가(lazy evaluation): 값이 실제로 필요할 때만 계산하거나 생성하는 방식

* 즉시 평가(eager evaluation): 데이터를 미리 한꺼번에 다 계산하거나 생성하는 방식- 리스트)

 

2) 언제 사용하는가?

- 무한히 증가하는 숫자 생성(메모리에는 필요한 값만 잠깐 저장된다)

def infinite_numbers():
    n = 0
    while True:
        yield n
        n += 1

gen = infinite_numbers()
print(next(gen))  # 0
print(next(gen))  # 1
print(next(gen))  # 2
# 계속 호출하면 숫자가 계속 증가

 

- 큰 파일 한 줄씩 읽기

def read_file(file_name):
    with open(file_name, "r") as file:
        for line in file:
            yield line.strip()

for line in read_file("example.txt"):
    print(line)  # 파일을 한 줄씩 읽어 처리

 

3. 이터레이터와 제너레이터 비교

구분 이터레이터 제너레이터
정의 __iter__()와 __next__() 메서드를 가진 객체 yield 키워드를 사용하는 함수
구현 방법 클래스를 만들어 직접 구현 간단한 함수로 작성 가능
작성 난이도 복잡한 코드가 필요함 코드가 훨씬 간결함
상태 유지 직정 상태를 관리해야함 (변수를 따로 저장) 상태를 자동으로 기억
언제쓸까? 세밀하게 조정하고 싶을 때
조건에 따라 상태를 직접 추적해야하고, 제너레이터로는 복잡하게 표현될 때
기존 객체에 반복 기능을 추가하고 싶을 때
쉽게 작성하고 싶을 때 
단순하고 빠른 데이터 생성
무한데이터
지연평가

 

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함