파이썬으로 문제를 풀다가, 다른 분들의 코드를 보면 생각보다 간결하게 짠 코드들도 많았는데요. 파이썬의 enumerate 또한 그 중 하나입니다. 이것이 어떤 함수인지 간단하게 알아보겠습니다.

 


 먼저, 이 함수는 iterable한 것을 받고, 옵션으로 start를 받습니다. iterable 한 것 중, 대표적인 것은 list가 있는데요. 예제 프로그램을 보겠습니다.

 

 

 'cho', 'ga', 'hui' 순서로 저장되어 있는 리스트가 있습니다. 뭔가 순회하는 것 처럼 보이는데요. 결과를 보겠습니다.

 

 

 어? 순회해서 값을 가져올 때 마다 앞에 index가 붙음을 알 수 있어요. (0, 'cho'), (1, 'ga'), (2, 'hui')가 순서대로 나왔네요. start 값을 주면 어떻게 될까요?

 

 

 start에 3을 입력해 보았습니다.

 

 

 그랬더니, 'cho' 앞에 3, 'ga' 앞에 4, 'hui' 앞에 5가 붙었음을 확인할 수 있어요. 어찌 되었던, index 값과 원소를 둘 다 동시에 가져오고 싶다면, 이런 식으로 쓰면 되긴 하겠네요.

 

 

 enumerate가 내부적으로 n과 element 쌍을 yield 하게 됩니다. 따라서, start가 없다면 인덱스와 iterable한 무언가에 있는 원소를 가져올 겁니다. 위 프로그램은, list에 있는 아이템과, 인덱스를 가지고 옵니다.

 

 

 실행 결과를 보면, index와 아이템을 가져옴을 알 수 있어요.

 

 


 이렇게만 보면 좋은 친구 같긴 합니다만, 주의해야 할 점이 있습니다. 파이썬의 enumerate는 본질적으로는 이터러블한 객체를 계속 순회하는 함수입니다. c++에서 iteration과 유사한 속성을 가지는데요. 그러면 주의해야 할 점이 무엇인지도 쉽게 떠오를 수 있습니다. 순회하는 도중에 자료 구조에 변형이 일어나는 경우를 극단적으로 조심해야 합니다. 예를 들어, 이런 경우를 생각해 봅시다.

 

 

 저는 list에서 'a'를 모두 제거하고 싶습니다. 그래서, enumerate로 싹 다 돌면서 item이 'a'인 경우 li[i]를 제거합니다. 잘 동작할 거 같지만, 결과를 보면 그렇지 않음을 알 수 있습니다.

 

 

 왜 잘못된 결과가 나왔을까요? 이유는 간단합니다. 순회가 되고 있는데 변형이 일어났기 때문입니다. 제 목적은 list에 있는 'a'를 모두 삭제하는 것이였는데요. 사실 리스트에 있는 특정한 조건을 만족하는 원소를 삭제해야 하는 요구 사항을 달성하기 위한, 적합한 방법 중 하나는 필터링을 하는 것입니다.

 

 

 예를 들어, 'a'가 여러 개 있는 리스트가 있습니다. 이 중, 'a'를 삭제하려고 한다면, 리스트 컴프리헨션을 이용하면 됩니다.

 

 

 결과는 'b', 'b', 'c' 순서대로 있는 리스트가 나옵니다.

 

 

 다른 문제 상황. 0 based에서 1번째, 3번째, 4번째 원소를 리스트에서 삭제해야 한다고 해 봅시다. 원래 의도라면 'b', 'd', 'e'가 제거되어야 합니다. 실행 결과는 어떻게 나올까요?

 

 

 'b', 'e', 'g'가 제거되었어요. 어? 그러면, 어떻게 해야 제대로 제거가 될까요? 가능한 방법 중 하나는, 거꾸로 돌려버리는 것입니다.

 

 

 뒤에서부터 제거해 버리면, 제거할 원소 앞에 원소들이 제거 되지 않았으므로, 우리가 원하는 인덱스에 있는 것들을 제거할 수 있어요.

 

 

 의도와 일치한 결과가 나왔습니다.