dmswl
[파이썬 문법] 2. 제너레이터(Generator)와 range 본문
1️⃣ 제너레이터란?
루프의 반복(iteration) 동작을 제어할 수 있는 루틴 형태.
제너레이터가 없다면 메모리 어딘가에 만들어낸 숫자 1억 개를 보관하고 있어야 함.
제너레이터를 이용하면, 단순히 제너레이터만 생성해두고 필요할 때 언제든 숫자를 만들어낼 수 있다.
2️⃣ yield 구문
yield 구문을 사용하면 제너레이터를 리턴할 수 있음.
기존의 함수 | vs | yield |
return | 제너레이터가 여기까지 실행 중이던 값을 내보낸다. 중간 값을 리턴한 다음 함수는 종료되지 않고 계속해서 맨 긑에 도달할 때까지 실행된다. |
이 경우 함수의 리턴 값은 제너레이터가 됨.
만약 다음 값을 생성하려면 next()로 추출하면 된다.
예를 들어, 100개의 값을 생성하고 싶다면 다음과 같이 100번 동안 next()를 수행하면 된다.
3️⃣ range
제너레이터의 방식을 활용하는 대표적인 함수.
주로 for문에서 쓰이는 range() 함수의 쓰임은 다음과 같다.
>>> list(range(5))
[0, 1, 2, 3, 4]
>>> range(5)
range(0, 5)
>>> type(range(5))
<class 'range'>
>>> for i in range(5):
print(i, end=' ')
0 1 2 3 4
range()는 range 클래스를 리턴. for 문에서 사용할 경우 내부적으로는 제너레이터의 next()를 호출하듯 매번 다음 숫자를 생성해내게 된다.
4️⃣ 리스트 컴프리헨션 vs range()
생성 조건만 정해두고 나중에 필요할 때 생성해서 꺼내 쓰기 때문에 리스트 컴프리헨션보다 메모리 측면에서 유용하게 사용 가능!!!!!!
>>> a = [n for n in range(100000)
>>> b = range(100000)
실제로 len()으로 길이 비교를 해보면 둘 다 동일하게 10만 개 출력됨. 비교연산자에서도 둘이 같다고 함.
>>> len(a)
100000
>>> len(b)
100000
>>> len(a) == len(b)
True
그러나, a에는 이미 생성된 값이 담겨 있고, b는 생성해야 한다는 조건만 존재.
>>> b
range(0, 100000)
>>> type(b)
<class 'range'>
실제 두 변수의 메모리 점유율을 비교해보면
>>> sys.getsizeof(a)
8697464
>>> sys.getsizeof(b)
48
똑같이 숫자 10만개를 가지고 있으나 range 클래스를 이용하는 b 변수의 메모리 점유율이 훨씬 작음.
10만 개가 아니라 1억 개라도 b 변수의 메모리 점유율은 동일. (=생성 조건만 보관하고 있기 때문)
게다가 미리 생성하지 않은 값은 인덱스에 접근이 안될 거라 생각할 수 있으나, 인덱스로 접근 시에는 바로 생성하도록 구현되어 있기 때문에 다음과 같이 리스트와 거의 동일한 느낌으로 불편 없이 사용할 수 있다.
>>> b[999]
999
'코테 공부 > 알고리즘' 카테고리의 다른 글
[DFS, BFS] 기본 (0) | 2023.02.24 |
---|---|
[파이썬 문법] 3. enumerate (0) | 2023.02.22 |
[파이썬 문법] 1. 리스트 컴프리헨션 (0) | 2023.02.22 |
[백준] 1251. 단어 나누기 (0) | 2023.02.15 |
[백준] 2798. 블랙잭 (0) | 2023.02.15 |