많은 프로그래밍 언어들에서 i, j, k와 같은 인덱스(index) 변수를 증가시키면서 for 루프를 돌린다.
하지만 파이썬에서는 enumerate()라는 내장 함수를 통해 이러한 인덱스 변수를 사용하지 않고 루프를 돌리는 방식이 선호되며 이런 코딩 스타일을 소위 Pythonic, 즉 파이썬 답다한다.
파이썬의 enumerate() 함수에 대해 알아보자.
For 루프
먼저 파이썬에서 for 문을 사용해서 루프를 돌리는 가장 기본적인 방법부터 짚고 넘어가보자
for <원소> in <목록>:
<목록> 에는 리스트(list), 튜플(tuple), 문자열(string), 반복자(iterator), 제너레이터(generator) 등 순회가 가능한 왠만한 모든 데이터 타입을 사용할 수 있다.
<원소> 에는 흔히 순회 변수(loop variable)라고 하는데, <목록> 에 넘긴 객체가 담고 있는 원소들이 루프가 도는 동안 하나씩 차례로 할당된다.
예를 들어, 3개의 글자를 담고 있는 리스트를 대상으로 루프를 돌면서 각 글자를 출력하는 for 문 코드
>>> for letter in ['A', 'B', 'C']:
... print(letter)
...
A
B
C
원소 뿐만 아니라 인덱스(index)도 함께 출력하고 싶을 때, 아래와 같이 작성한 것을 볼 수 있다.
>>> i = 0
>>> for letter in ['A', 'B', 'C']:
... print(i, letter)
... i += 1
...
0 A
1 B
2 C
이 방법이 틀린 것은 아니지만, i 변수가 for 반복문이 종료된 이 후에도 네임 스페이스에 남아있기 때문에 이상적이지 않는다.
또 다른 방법으로는 range()와 len() 내장 함수를 이용하여 만든 인덱스 목록을 대상으로 루프를 돌리는 것인데,
>>> letters = ['A', 'B', 'C']
>>> for i in range(len(letters)):
... letter = letters[i]
... print(i, letter)
...
0 A
1 B
2 C
이 방법은 이전 방법보다는 나아보이지만, 파이썬 커뮤니티에서는 이러한 코드를 소위 파이썬 답지(Pythonic) 않아 보인다고 한다.
enumerate() 함수
좀 더 파이썬답게 인덱스(index)와 원소를 동시에 접근하면서 루프를 돌리기 위해 enumerate() 함수를 사용한다.
for 문의 in 뒷 부분을 enumerate() 함수로 한 번 감싸주면 되는데, 아래와 같이 나온다.
>>> for entry in enumerate(['A', 'B', 'C']):
... print(entry)
...
(0, 'A')
(1, 'B')
(2, 'C')
enumerate() 함수는 기본적으로 인덱스와 원소로 이루어진 튜플(tuple)을 만든다. 따라서 인덱스와 원소를 각각 다른 변수에 할당하고 싶다면 인자 풀기(unpacking)를 해야한다.
>>> for i, letter in enumerate(['A', 'B', 'C']):
... print(i, letter)
...
0 A
1 B
2 C
+시작 인덱스 변경
루프를 돌리다보면 인덱스를 0이 아니라, 1로 시작하고 싶을 때는 enumerate() 함수를 호출할 때 start 인자에 시작하고 싶은 숫자를 넘기면 된다.
>>> for i, letter in enumerate(['A', 'B', 'C'], start=101):
... print(i, letter)
...
101 A
102 B
103 C
enumerate() 원리
파이썬에서 for 문은 내부적으로 in 뒤에 오는 목록을 대상으로 계속해서 next() 함수를 호출하고 있다고 생각할 수 있다.
따라서, 일반 리스트를 iter() 함수에 넘겨 반복자(iterator)로 만든 후 next() 함수를 호출해보면 원소들이 차례로 얻어지는 것을 알 수 있다.
>>> iter_letters = iter(['A', 'B', 'C'])
>>> next(iter_letters)
'A'
>>> next(iter_letters)
'B'
>>> next(iter_letters)
'C'
enumerate() 함수를 호출한 결과를 대상으로 next() 함수를 계속해서 호출해보면, 인덱스와 원소의 쌍이 튜플(tuple)의 형태로 차례로 얻어지는 것을 확인할 수 있다.
>>> enumerate_letters = enumerate(['A', 'B', 'C'])
>>> next(enumerate_letters)
(0, 'A')
>>> next(enumerate_letters)
(1, 'B')
>>> next(enumerate_letters)
(2, 'C')
enumerate() 함수는 인자로 넘어온 목록을 기준으로 인덱스와 원소를 차례대로 접근하게 해주는 반복자(iterator) 객체를 반환해주는 함수로, 이 부분은 enumerate() 함수의 반환 값을 리스트로 변환해보면 좀 더 명확하게 확인 가능하다.
>>> list(enumerate(['A', 'B', 'C']))
[(0, 'A'), (1, 'B'), (2, 'C')]
+ range 보다는 iterrows 를 쓰면 더 빠르다고 한다.
출처 : https://www.daleseo.com/python-enumerate/
'공부' 카테고리의 다른 글
[BigQuery] 빅쿼리 성능 최적화 종류 (0) | 2024.09.13 |
---|---|
[BigQuery] 빅쿼리 데이터 구조 및 기본적인 사용방법과 문법 (0) | 2024.09.13 |
[SQL} SELECT 문 정리 (FROM, WHERE, GROUP BY, ORDER BY, JOIN) (0) | 2024.09.11 |
[Learning Spark] Chapter 4 : 스파크 SQL과 데이터 프레임 : 내장 데이터 소스 소개 (1) | 2024.09.01 |
[Learning Spark] Databricks 을 통해 notebook 및 cluster 생성 방법 (2) | 2024.09.01 |