파이썬에서 **제너레이터(generator)**와 **이터레이터(iterator)**는 큰 데이터를 효율적으로 처리하거나 지연 평가(lazy evaluation)를 구현할 때 유용하게 사용됩니다. 제너레이터와 이터레이터는 메모리를 효율적으로 사용하며, 데이터가 필요할 때마다 하나씩 생성하여 반환하는 방식으로 동작합니다.
1. 이터레이터 (Iterator)
이터레이터는 반복 가능한 객체에서 순차적으로 요소를 반환하는 객체입니다. 파이썬에서 __iter__()와 __next__() 메서드를 구현한 객체는 이터레이터로 사용할 수 있습니다.
이터레이터 기본 사용 예제
# 리스트에서 이터레이터 생성
numbers = [1, 2, 3]
iterator = iter(numbers)
# next()를 통해 요소를 순차적으로 가져오기
print(next(iterator)) # 결과: 1
print(next(iterator)) # 결과: 2
print(next(iterator)) # 결과: 3
# print(next(iterator)) # StopIteration 오류 발생
설명: iter() 함수는 반복 가능한 객체에서 이터레이터를 반환하며, next() 함수를 사용해 각 요소를 순차적으로 가져옵니다. 요소를 모두 가져오면 StopIteration 예외가 발생하여 반복이 끝났음을 알립니다.
2. 사용자 정의 이터레이터 만들기
__iter__()와 __next__() 메서드를 가진 클래스를 만들어 이터레이터를 정의할 수 있습니다.
class MyIterator:
def __init__(self, max_value):
self.current = 0
self.max_value = max_value
def __iter__(self):
return self
def __next__(self):
if self.current < self.max_value:
self.current += 1
return self.current - 1
else:
raise StopIteration
# 이터레이터 사용
my_iter = MyIterator(3)
for number in my_iter:
print(number) # 결과: 0, 1, 2
설명: MyIterator 클래스는 __next__() 메서드에서 self.current 값을 반환하며, self.current가 max_value에 도달하면 StopIteration을 발생시켜 반복을 종료합니다.
3. 제너레이터 (Generator)
제너레이터는 함수처럼 작성되지만, 데이터를 반환할 때 return 대신 yield 키워드를 사용하여 데이터를 하나씩 반환합니다. 제너레이터는 값을 "지연 생성"하므로 메모리를 효율적으로 사용할 수 있습니다.
제너레이터 기본 사용 예제
def my_generator():
yield 1
yield 2
yield 3
gen = my_generator()
print(next(gen)) # 결과: 1
print(next(gen)) # 결과: 2
print(next(gen)) # 결과: 3
# print(next(gen)) # StopIteration 오류 발생
설명: yield 키워드는 값을 반환하고 함수의 실행 상태를 유지합니다. 다시 호출되면 이전 상태에서 실행을 이어가며 다음 yield까지 진행합니다. 제너레이터가 값을 모두 반환하면 StopIteration이 발생합니다.
4. 제너레이터와 for 문 사용
제너레이터는 for 문에서 자동으로 이터레이터로 동작하며, StopIteration을 처리할 필요 없이 순차적으로 모든 값을 출력할 수 있습니다.
def my_generator():
for i in range(3):
yield i
for value in my_generator():
print(value) # 결과: 0, 1, 2
설명: 제너레이터는 for 문과 함께 사용할 때 자동으로 StopIteration을 처리해 반복을 종료합니다.
5. 제너레이터 표현식
제너레이터는 컴프리헨션 방식으로도 정의할 수 있으며, 이는 메모리를 효율적으로 사용하는 지연 생성 리스트와 유사한 역할을 합니다.
gen_exp = (x * x for x in range(5))
print(list(gen_exp)) # 결과: [0, 1, 4, 9, 16]
설명: gen_exp는 제너레이터 표현식으로 정의되며, x * x 결과를 순차적으로 반환합니다. 이를 리스트로 변환하여 모든 값을 한 번에 출력할 수 있습니다.
6. 제너레이터를 활용한 무한 수열 생성
제너레이터는 필요할 때까지 데이터를 생성하여 반환하므로, 무한히 큰 데이터도 메모리 부담 없이 처리할 수 있습니다.
def infinite_sequence():
num = 0
while True:
yield num
num += 1
gen = infinite_sequence()
print(next(gen)) # 결과: 0
print(next(gen)) # 결과: 1
print(next(gen)) # 결과: 2
# 계속해서 값을 반환함
설명: infinite_sequence 제너레이터는 무한히 큰 수열을 생성합니다. next() 함수를 호출할 때마다 num이 1씩 증가해 무한히 값을 반환합니다.
7. 제너레이터로 큰 데이터 처리하기
제너레이터는 데이터를 한 번에 메모리에 올리지 않고, 필요한 만큼만 생성하여 반환하기 때문에 대용량 파일이나 큰 데이터셋을 처리할 때 유용합니다.
def read_large_file(file_path):
with open(file_path, "r") as file:
for line in file:
yield line.strip()
for line in read_large_file("large_file.txt"):
print(line) # 파일의 각 줄을 순차적으로 처리
설명: read_large_file 제너레이터는 파일을 한 줄씩 읽어 반환하므로, 메모리를 절약하면서 대용량 파일을 처리할 수 있습니다.
8. 제너레이터와 yield from
yield from 구문을 사용하면 다른 제너레이터나 반복 가능한 객체에서 값을 간편하게 가져올 수 있습니다.
def generator1():
yield from range(3)
yield from "ABC"
for value in generator1():
print(value)
결과:
0
1
2
A
B
C
설명: yield from은 제너레이터를 중첩 호출할 때 사용되며, range(3)과 "ABC"의 모든 값을 순차적으로 반환합니다.
요약
- 이터레이터는 __iter__()와 __next__() 메서드를 구현한 객체로, next() 함수를 통해 값을 순차적으로 반환합니다.
- 제너레이터는 yield 키워드를 사용하여 데이터를 "지연 생성"하며, 메모리 효율적으로 대용량 데이터를 처리할 수 있습니다.
- 제너레이터 표현식을 사용하면 지연 생성 리스트처럼 작동하는 제너레이터를 간단히 생성할 수 있습니다.
- 무한 수열 생성이나 대용량 파일 처리 등에 제너레이터를 활용하면 메모리 효율성을 크게 높일 수 있습니다.
제너레이터와 이터레이터를 활용하면 데이터 처리 효율을 높이고, 메모리 사용을 최소화할 수 있습니다.
'파이썬 Python' 카테고리의 다른 글
파이썬 Python 튜플(Tuple) 사용법 (0) | 2024.11.27 |
---|---|
파이썬(Python) JSON 처리 (0) | 2024.11.26 |
파이썬 Python 날짜와 시간 다루기 (0) | 2024.11.26 |
파이썬 Python 파일 경로 다루기 (0) | 2024.11.23 |
파이썬 Python 데코레이터 활용하기 (0) | 2024.11.21 |
파이썬 Python 문자열 다루기 (0) | 2024.11.21 |
파이썬 Python 패키지 관리자 (pip) (0) | 2024.11.18 |
파이썬 Python 모듈과 라이브러리 사용하는 방법 (0) | 2024.11.18 |