파이썬의 리스트는 힙 메모리 영역에 저장되어 있는 객체의 주소를 모아둔 하나의 객체이며 컬렉션(collection)입니다. 파이썬의 리스트는 동적 리스트이며 리스트를 추가하고 제거하는데 인덱스를 걱정할 필요가 없으며 여러 자료형들을 하나의 리스트에 담을 수 있다는 장점이 있습니다.
하지만 이런 리스트는 메모리에 저장되기 때문에 메모리를 매우 많이 사용하게 됩니다. 이런 상황을 해결하기 위해서 yield를 사용할 수 있습니다.
1. yield
파이썬에서 yield는 제너레이터 함수를 만드는 데 사용하는 키워드입니다.
제너레이터는 이터레이터를 생성하는 함수입니다. 여기서 이터레이터는 iterable 한 객체를 __next__ 매직메서드를 사용해서 요소들을 순차적으로 반환시켜 주는 객체입니다.
함수에서 yield 키워드를 사용하면 제너레이터 함수가 됩니다.
이렇게 만들어진 제너레이터 함수를 사용하면 다른 일반적인 함수처럼 함수 실행 후 return을 하는 대신 제너레이터 객체를 반환해 줍니다. 그리고 개발자는 해당 객체를 next 메서드를 사용하면서 값을 순차적으로 하나씩 얻습니다.
사용자가 next로 제너레이터 객체를 호출하면 yield까지 실행한 후에 값을 반환하고 함수를 중지합니다. 이후 next로 다시 호출되었을 때 중지된 지점 이후부터 다시 yield까지 함수를 실행하고 반환합니다. 더 이상 반환할 값이 없으면 StopIteration 에러를 발생시킵니다.
def test():
for i in range(3):
yield i
print(f"{i} 가 반환되었습니다.")
a = test()
print(next(a)) # 0
print(next(a)) # 0 가 반환되었습니다. \n 1
print(next(a)) # 1 가 반환되었습니다. \n 2
print(next(a)) # 2 가 반환되었습니다. \n StopIteration
제너레이터는 일반적인 함수처럼 return으로 한번 반환하는 게 아니라 yield로 값을 여러 번 반환하는 걸 볼 수 있습니다.
해당 코드를 보면 yield를 사용하고 print문을 사용했기 때문에 일단 값이 반환되고 다음 호출 때 반환된 값에 대한 print문을 호출합니다.
2. 제너레이터
제너레이터는 데이터를 미리 만들지 않고 하나씩 순차적으로 만들어내는 객체를 말합니다.
def a():
return list('abc')
def b():
yield 'a'
yield 'b'
yield 'c'
for i in a(): print(i) # a\n b\n c\n
for i in b(): print(i) # a\n b\n c\n
print(a()) # ['a', 'b', 'c']
print(b()) # <generator object b at 0x10210a4b0>
함수와 제너레이터를 for문으로 실행만 하면 같게 보일 수 있지만 a()는 리스트를 반환하고 b()는 제너레이터 객체를 반환하는 것을 볼 수 있습니다.
함수를 사용하면 return 할 때 반환값을 모두 메모리에 올려놔야 하지만 제너레이터는 한 글자씩 반환하기 때문에 한 글자의 크기만 메모리에 올리면 됩니다.
예시를 들어서 10만 개의 정수를 리스트에 저장하면 4byte * 10만 만큼의 메모리 공간을 차지하게 되는데 yield를 사용하게 되면 한 번에 하나씩만 숫자를 생성하기 때문에 값을 반환하는 4byte만 사용하면 되어서 엄청나게 메모리를 절약할 수 있습니다.
이런 방식을 이용해서 서버에서 영상이나 파일데이터를 스트리밍 할 때나 큰 파일을 읽을 때 사용하면 더 효율적으로 작동하게 만들 수 있습니다.
def a():
i = 0
while True:
yield i
i += 1
b = (a for i in my_list if my_list in a)
무한으로 데이터를 생성하거나 컴프리핸션 방식으로도 제너레이터를 사용할 수 있습니다.
'python' 카테고리의 다른 글
Python - 멀티스레드, GIL (Global Interpreter Lock) (0) | 2024.11.25 |
---|---|
Python list append, extend, += (0) | 2024.10.07 |
Python mutable 변경 가능, immutable 변경 불가능 (0) | 2024.09.23 |
Python 잘 쓰는법: 리스트, 딕셔너리 (1) | 2024.09.09 |
Python 다중 상속, super() (0) | 2024.09.02 |