안 웹개발/파이썬

파이썬 for문에서 인덱스를 쓰지 말아야 하는 이유

by 목도리 2021. 9. 29.

본문부터 읽을래

정통적인 i, arr[i] 방식. (왼쪽: C++ / 오른쪽: Python)

여러 언어에서는 배열 원소의 인덱스을 동시에 얻기 위해 for문과 인덱싱을 활용한다. python에서도 비슷하게 range(len(리스트)) 을 사용해 반복문에서 인덱스와 값을 얻는 경우가 많다. 문법적으로 틀리지는 않으나 파이-써닉한 코드가 아니다.

그렇다면 이런 상황에서는 무엇을 해야 할까? 더 나아가, 다른 비슷한 경우가 있을까? 애초에 그냥 위에처럼 쓰면 안 되는 걸까? for문이 다른 언어와 어떻게 다르길래 불편하게 익숙지 않은 식으로 쓰라는 걸까?

파이썬 for문은 다른 언어와 다르다

간접 vs 직접. (왼쪽: C / 오른쪽: Python)

대부분의 언어에서 배열은 일렬로 늘어선 호텔 방과 같이 생각할 수 있다. 가령 100호부터 105호까지 사과, 딸기, 배, 수박, 귤이 사고 있다. 인덱싱은 방번호로 방 안의 과일을 찾는 것이다. 수박을 찾고 싶다면 104호의 문을 두들기면 된다. 여기서 C++과 파이썬의 차이점은

  • C++: 100호부터 105호까지 차례대로 방문하였다.
  • 파이썬: 1층 투숙객에게 차례대로 방문을 열고 나와달라고 하였다.

파이썬의 경우에는 방 호수, 즉 인덱싱을 사용하지 않았다! 이는 파이썬의 for문은 반복 가능한 객체(이터러블)를 하나씩 꺼내오기 때문이다.

왼쪽: 기본형 / 오른쪽: 언패킹(unpacking)을 사용했다

거기에다 파이썬은 여러 변수에 여러 값을 언패킹(unpacking)해 넣을 수 있다. 요약하면 파이썬의 for문은

  • 배열(컨테이너)의 원소들을 차례대로 풀어낸다.
  • 여러 변수에 원소 값(배열)을 풀어 넣을 수 있다.

 

enumerate( ) : 반복 가능한 컨테이너(=이터러블)의 값과 인덱스가 모두 필요할 때

enumerate(컨테이너, 시작=숫자) 형식으로 0이 아닌 다른 수에서부터 시작할 수 있다.

reversed( ): 컨테이너를 뒤에서부터 반복하고 싶을 때

range(len(배열)) 형식을 사용했다면 이런 식으로 코드를 작성해야 한다. 보기에도 훨씬 알아보기 힘들고 범위 실수를 저지를 가능성도 더 높다.

 

zip( ) : 여러 컨테이너의 내용을 동시에 반복해야 할 때

반복할 컨테이너들의 길이가 다르면 가장 짧은 컨테이너의 길이만큼만 반복된다.

longest_zip( ) : zip( )할 컨테이너들의 길이가 다를 때

왼쪽: itertools는 random과 같은 파이썬 내장 모듈이다.
오른쪽: 초기화를 해 주지 않으면 fillvalue의 기본값은 None이다.

번외: 위 함수들을 쓸 또 다른 이유

  • 보기 편하다. 배열[i]보다는 원소가 알아보기 쉽고 혹시라도 생길지 모를 오류를 찾기도 쉬워진다.
  • 앞서 소개한 함수들은 모두 실행 결괏값으로 이터레이터(iterator)를 반환한다. 이터레이터는 상자 안에서 값을 하나씩 꺼내오는 형식의 구조를 뜻하는데, 메모리에 모든 값을 올릴 필요가 없이 하나하나씩 가져오기 때문에 속도가 느려질 걱정 없이 쓸 수 있다.

댓글