프로그래밍백엔드 개발자

Python에서 enumerate() 함수의 작동 메커니즘을 설명하세요. 이를 통해 시퀀스의 요소와 인덱스를 올바르게 반복하는 방법과 사용 시 유의해야 할 특성은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변

질문 역사: 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

주요 특징:

  • 리스트나 인덱스가 있는 구조 뿐만 아니라 모든 반복 가능한 객체와 작동합니다.
  • 시작 인덱스를 설정할 수 있습니다(예: 1에서의 번호 매기기).
  • 리스트가 아닌 이터레이터를 반환합니다(즉, 불필요한 메모리를 사용하지 않음).

속임수 질문.

왜 함수에서 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(...))를 사용하는 것.
  • 시작 인덱스를 잘못 처리하여 중요할 때(예: 21세기를 위해서는 0이 아닌 1부터 시작) 발생하는 오류.
  • enumerate를 통해 반복하는 동안 컬렉션의 크기를 변경하려고 하는 것.

실생활 예

부정 사례

프로그래머가 range(len(list))를 사용하여 리스트를 반복하며 요소를 삭제합니다. 결과적으로 인덱스가 엉망이 되어 일부 요소가 건너뛰어집니다.

장점:

  • 인덱스에 직접 접근할 수 있습니다.

단점:

  • 인덱스 오류, 가독성이 떨어지는 코드, out of range 또는 요소 손실의 가능성.

긍정 사례

enumerate()를 사용하여 필요한 요소의 새 리스트를 형성하거나 인덱스를 통해 값을 변경하지만 반복 중 목록 크기는 변하지 않습니다.

장점:

  • 깔끔한 코드, 모든 컬렉션에 대해 안정적인 작업, 버그가 적음.

단점:

  • 리스트 복사가 필요한 경우 추가 메모리가 요구될 수 있음.