질문 역사:
enumerate() 함수는 Python 2.3에서 추가되었으며, 현재는 컬렉션을 반복하면서 요소와 요소의 인덱스에 동시에 접근할 수 있는 표준 방법입니다. enumerate()가 나오기 전에는 프로그래머들이 자주 사용자 정의 카운터를 만들거나 range(len(sequence)) 함수를 사용했지만, 이는 불편하고 가독성이 떨어졌습니다.
문제:
일반적인 for 루프는 값만 반복합니다. 인덱스에 접근하기 위해 종종 range(len(...))를 사용하는데, 이는 모든 반복 가능한 객체(예: 제너레이터, 문자열 및 가변 길이의 튜플, 필터링 시)에서 작동하지 않습니다. 이로 인해 오류가 발생하고 코드가 복잡해집니다.
해결책:
enumerate()는 (인덱스, 요소) 쌍을 반환하여 비표준 컬렉션이나 필터링된 제너레이터의 현재 요소 인덱스를 얻을 수 있게 해줍니다. 이 함수는 선택적 두 번째 인수로 카운터의 시작 값을 취할 수 있습니다.
코드 예:
words = ['apple', 'banana', 'cherry'] for idx, word in enumerate(words, 1): print(f"{idx}: {word}") # 출력: # 1: apple # 2: banana # 3: cherry
주요 특징:
왜 함수에서 range(len(seq)) 대신 enumerate를 자주 사용하는가?
답: range(len(seq))는 인덱스에 접근할 수 있는 시퀀스에서만 작동하며 반복 중 길이 변경을 고려하지 않습니다. 또한 가독성이 떨어지고 제너레이터에서는 느리거나 전혀 작동하지 않습니다. enumerate()는 모든 반복 가능한 컬렉션에 대해 안전하게 인덱스-값 쌍에 접근할 수 있게 합니다.
코드 예:
# 제너레이터와 함께 작동하지 않음: gen = (x for x in range(5)) for i in range(len(gen)): print(i) # 오류: 제너레이터는 길이가 없음
반복하면서 리스트의 요소를 수정하는 데 enumerate를 사용할 수 있을까요?
답: 네, 인덱스를 반복해야 값을 기록할 수 있습니다. 그렇지 않으면 값만 반복하면 객체의 복사본이 수정되고 원본은 수정되지 않습니다.
코드 예:
nums = [1, 2, 3] for idx, val in enumerate(nums): nums[idx] = val * 2 # nums = [2, 4, 6]
enumerate에 변하는 객체를 전달하면 무엇이 반환되나요?
답: 컬렉션이 반복 중에 변경되면(예: 요소가 삭제됨) 기대하지 못한 동작이 발생할 수 있습니다. 왜냐하면 enumerate는 내부 이터레이터를 따르기 때문입니다. 그러므로 반복하는 동안 컬렉션을 변경하는 것은 권장되지 않습니다.
range(len(...))를 사용하는 것.부정 사례
프로그래머가 range(len(list))를 사용하여 리스트를 반복하며 요소를 삭제합니다. 결과적으로 인덱스가 엉망이 되어 일부 요소가 건너뛰어집니다.
장점:
단점:
긍정 사례
enumerate()를 사용하여 필요한 요소의 새 리스트를 형성하거나 인덱스를 통해 값을 변경하지만 반복 중 목록 크기는 변하지 않습니다.
장점:
단점: