여러 이터레이터에 대해 나란히 루프를 수행하려면 zip을 사용하라

Minsang Yu·2023년 6월 6일

파이썬에서는 관련된 객체가 들어 있는 리스트를 다수 다루는 경우가 자주 있다. 리스트 컴프리헨션을 사용하면 소스 list에서 새로운 list를 파생시키기 쉽다.

names = ['Cecilia', '남궁민수', 'John']
counts = [len(n) for n in names]

# 만들어진 name중 가장 긴 이름을 리턴하라

longest_name = None
max_count = 0

for i in range(len(names)):
    count = counts[i]
	  if count > max_count:
        longes_name = name[i]
        max_count = count

print(longest_name)

>>>
Cecilia

문제는 이루프가 시각적으로 잡음이 많다는 것이다. 인덱스를 사용해 names와 counts의 원소를 찾는 과정이 코드를 읽기 어렵게 만든다. 배열 인덱스 i를 사용해 배열 원소를 가져오는 연산이 두번 일어난다.


  • 이런 코드를 더 깔끔하게 만들 수 있도록 파이썬은 zip이라는 내장함수를 제공한다.
  • zip은 둘 이상의 이터레이터를 지연 계산 제네레이터를 사용해 묶어준다.
  • zip 제네레이터는 각 이터레이터의 다음 값이 들어 있는 튜플을 반환한다.
  • 이 튜플을 for 문에서 바로 언패킹 할 수 있다.
names = ['Cecilia', '남궁민수', 'John']
counts = [len(n) for n in names]

# 만들어진 name중 가장 긴 이름을 리턴하라

longest_name = None
max_count = 0

for name, count in zip(names, countes):
    if count > max_count:
        longest_name = name
				max_count = count 

이렇게 만든 코드는 인덱스를 사용해 여러 리스트의 원소에 접근하는 코드보다 훨씬 깔끔하다.

zip은 자신이 감싼 이터레이터 원소를 하나씩 소비한다. 따라서 메모리를 다 소모해서 프로그램이 중단되는 위험 없이 아주 긴 입력도 처리할 수 있다.

zip의 주의사항

zip은 인자로 받은 이터레이터중 가장 짧은 이터레이터 길이에 맞춰서 반환한다.

names.append('Rosalind')

for name, count in zip(names, countes):
    print(name)

>>>
Cecilia
남궁민수
John

새로 추가한 원소인 Rosalind 에 대한 출력이 없다. zip은 자신이 감싼 이터레이터중 어느 하나가 끝날 때까지 튜플을 내놓기 때문이다.

긴 이터레이터를 버릴떄가 바람직하지 않을 경우 itertoos.zip_longest

를 사용한다.

import itertoos

for name, count in itertools.zip(names, countes):
				print(f"{name}: {count}")

>>>
Cecilia: 7
남궁민수: 4
John: 4
Rosalind: None # 존재하지 않는 이터레이터 원소는 null처리한다.

zip_longest는 존재하지 않는값을 자신에게 전달된 fillvalue로 대신한다. fillvalu의 기본값은 None이다.

정리

  • zip 내장 함수를 사용해 여러 이터레이터를 나란히 이터레이션할 수 있다.
  • zip은 튜플을 지연 계산하는 제네레이터를 만든다. 따라서 무한히 긴 입력에도 zip을 쓸 수 있다.
  • 입력 이테레이터의 길이가 서로 다르면 zip은 아무런 경고도 없이 가장 짧은 이터레이터 길이까지만 튜플을 내놓고 더 긴 이터레이터의 나머지 원소는 무시한다.
  • 가장 짧은 이터레이터에 맞춰 길이를 제한하지 않고 길이가 서로 다른 이터레이터에 대해 루프를 수행하려면 itertools 내장 모듈인 zip_longest 함수를 사용하라.

Reference. Effective Python

profile
Jr. DataEngineer

0개의 댓글