본문 바로가기

카테고리 없음

[Python] for문에서 range 대신 enumerate 사용하기

For문에서 iterator를 pythonic하게 돌리는 방법입니다. 각 경우에 대해 아래와 같은 방법으로 돌릴 때 가장 효율적이고 가독성이 높습니다. 우선 pythonic하지 않은 방법을 살펴보겠습니다. 다른 언어에 익숙한 분들은 처음에 아래와 같이 for문을 잘 사용합니다.

# Non-pythonic for i in range(len(some_list)): emlement = some_list[i] # do something on element

위와 동일하게 작동하는 pythonic way는 아래와 같습니다.

# Pythonic
    for element in some_list:
        # do something on element

그런데 가끔 index(element의 위치)를 동시에 써야 할 때도 있습니다. 그럴 때는 앞서 보여드린 non-pythonic을 써야만 할 것 같은데요.

# Non-pythonic
    for i in range(len(some_list)):
        element = some_list[i]
        # do something on element
        # do something on index 'i'

그럴 때 pythonic 방법은 아래와 같이 enumerate를 쓰는 것입니다.

# Pythonic
    for i, element in enumerate(some_list):
        # do something on element
        # do something on index 'i'

훨씬 간단하죠? 그럼 index만 필요하지 element는 필요 없을 때는 어떨까요?

# Pythonic
    for i, _ in enumerate(some_list):
        # do something on index 'i'

_ 는 python에서 무시할 때 쓰는 관용적인 표현입니다. enumerate가 index와 element를 뱉어내지만, 그 중 element는 무시하겠다는 뜻입니다. element만 필요할 때도 아래와 같이 쓸 수 있습니다.

# Pythonic
    for _, element in enumerate(some_list):
        # do something on element

그럼 길이가 같은 두 list에서 가져올 땐 어떻게 해야할까요. 이번에야말로 non-pythonic 방법으로 index만 가져와야 할 것 같은데요. 이때 pythonic 방법은 zip을 쓰는 것입니다.

# Non-pythonic
    for i in range(len(first_list)):
        element_in_first = first_list[i]
        element_in_second = second_list[i]
        # do something on element_in_first and element_in_second
# Pythonic
    for element_in_first, element_in_second in zip(first_list, second_list):
        # do something on element_in_first and element_in_second

여기서 zip은 두 list(혹은 tuple)를 element-by-element로 묶어주는 역할을 합니다. 세 개나 네 개일 때도 zip으로 세 개나 네 개를 묶어주면 됩니다. 만약 index까지 필요하다면 아래와 같이 하면 됩니다.

# Pythonic
    for i, (element_in_first, element_in_second) in enumerate(zip(first_list, second_list)):
        # do something on element_in_first and element_in_second
        # do somethin on index 'i'

zip을 쓸 때 주의할 점은 묶어주는 list-like objects의 길이가 다를 때 짧은 것 기준으로 생성된다는 점입니다.

enumeratezip에 익숙해지면 for문을 쓸 때 상당히 편합니다. 정말 어쩔 수 없이 range(len(some_list))와 같은 방법을 써야하는 경우도 더러 있지만 그렇지 않을 때는 pythonic한 방법을 쓰는 것이 가독성도 좋고 편합니다.