유튜브 강의와 GPT로 정리하였습니다.
출처: 유튜브 - Generators - Advanced Python Tutorial #3
일반적인 함수는 호출되면 모든 코드를 한 번에 실행하고 끝난다.
하지만 Generator 함수는 yield를 사용하여 실행을 중간에 멈추고, 다시 호출하면 멈춘 지점부터 실행을 이어갈 수 있음.
next()
를 호출하여 한 번에 하나의 값을 가져올 수 있음.def my_generator():
print("Start")
yield 1
print("Step 2")
yield 2
print("Step 3")
yield 3
print("End")
gen = my_generator() # Generator 객체 생성
print(next(gen)) # 첫 번째 yield 실행
print(next(gen)) # 두 번째 yield 실행
print(next(gen)) # 세 번째 yield 실행
print(next(gen))
Start
1
Step 2
2
Step 3
3
End
Traceback (most recent call last):
...
StopIteration
next(gen)
호출 → "Start" 출력 후 yield 1 실행 → 1 반환 후 멈춤.next(gen)
호출 → "Step 2" 출력 후 yield 2 실행 → 2 반환 후 멈춤.next(gen)
호출 → "Step 3" 출력 후 yield 3 실행 → 3 반환 후 멈춤.next(gen)
호출 → "End" 출력 후 더 이상 yield가 없으므로 StopIteration 예외 발생.next()
는 Generator를 한 단계 진행하여 yield 값을 반환하는 역할.def simple_gen():
yield "A"
yield "B"
yield "C"
gen = simple_gen()
print(next(gen)) # A
print(next(gen)) # B
print(next(gen)) # C
print(next(gen)) # StopIteration 발생
메모리 효율적
- 한 번에 모든 데이터를 생성하지 않고 필요할 때마다 값을 반환.
- 대량의 데이터를 처리할 때 리스트보다 훨씬 적은 메모리 사용.
무한 시퀀스 처리 가능
- while True를 이용해 무한 루프를 생성 가능.
- 리스트는 크기가 제한되지만, Generator는 필요한 값만 계산해서 반환하므로 효율적.
def infinite_numbers():
num = 1
while True:
yield num
num += 1 # 계속 증가
gen = infinite_numbers()
print(next(gen)) # 1
print(next(gen)) # 2
print(next(gen)) # 3
=> 무한히 실행 가능
리스트(range())를 사용하면 메모리가 한계에 도달하지만, Generator는 메모리 낭비 없이 값을 하나씩 생성 가능.
Python의 리스트 컴프리헨션(List Comprehension) 과 유사한 방식으로 Generator를 만들 수도 있음.
# 리스트 컴프리헨션 (메모리를 차지함)
lst = [x * 2 for x in range(10)]
print(lst) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Generator 표현식 (메모리 효율적)
gen = (x * 2 for x in range(10))
print(next(gen)) # 0
print(next(gen)) # 2
print(next(gen)) # 4
여러 개의 Generator를 연결할 때 yield from을 사용하면 더 간결하게 코드 작성 가능.
def sub_generator():
yield 1
yield 2
yield 3
def main_generator():
yield from sub_generator() # sub_generator의 모든 값을 yield
yield 4
yield 5
gen = main_generator()
for value in gen:
print(value)
1
2
3
4
5
일반적으로 readlines()를 사용하면 전체 파일을 한 번에 읽어 메모리를 많이 차지하지만, Generator를 사용하면 한 줄씩 읽을 수 있어 메모리 절약 가능
def read_large_file(filename):
with open(filename, "r") as file:
for line in file:
yield line.strip() # 한 줄씩 반환
for line in read_large_file("large_data.txt"):
print(line) # 한 줄씩 출력
개념 | 설명 |
---|---|
yield | Generator에서 상태를 유지하면서 값을 반환 |
next() | Generator의 다음 yield 까지 실행 |
yield from | 다른 Generator 또는 Iterable의 모든 값을 가져오기 |
Generator 표현식 | () 를 사용하여 메모리를 절약하면서 값 생성 |
next()
를 사용해 값을 하나씩 생성하면서 사용할 수 있음yield from
을 사용하면 중첩된 Generator를 간결하게 처리 가능