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의 길이가 다를 때 짧은 것 기준으로 생성된다는 점입니다.
enumerate
와 zip
에 익숙해지면 for문을 쓸 때 상당히 편합니다.
정말 어쩔 수 없이 range(len(some_list))
와 같은 방법을 써야하는 경우도 더러 있지만 그렇지 않을 때는 pythonic한 방법을 쓰는 것이 가독성도 좋고 편합니다.