zip() 함수는 Python 2에서 등장했으며 (그때는 리스트를 반환함), Python 3부터는 지연 반복기를 반환합니다. 이 함수는 여러 시퀀스를 요소별로 튜플로 "엮어" 주기 때문에, 병렬 반복 가능한 컬렉션을 처리하는 데 편리하고 효율적입니다.
종종 여러 리스트(또는 다른 종류의 시퀀스)를 동시에 처리해야 할 때가 있습니다. 예를 들어, 키-값 쌍을 순회하거나 점-쌍의 좌표를 처리하는 경우입니다. 인덱스를 수동으로 동기화하는 것은 오류와 코드의 가독성을 떨어뜨리는 원인이 됩니다, 특히 길이가 다른 컬렉션에서요.
zip() 함수는 임의의 수의 반복 가능한 객체를 받아들이고, 각 반복 가능한 객체에서 해당 요소들이 포함된 튜플의 반복기를 반환합니다. 길이가 다른 시퀀스의 경우, 결과는 가장 짧은 시퀀스에서 중단됩니다.
names = ['Alice', 'Bob', 'Charlie'] ages = [24, 27, 30] for name, age in zip(names, ages): print(f'{name}은 {age}세입니다.')
zip을 *을 사용하여 펼칠 수 있습니다:
pairs = [(1, 'a'), (2, 'b'), (3, 'c')] nums, chars = zip(*pairs) print(nums) # (1, 2, 3) print(chars) # ('a', 'b', 'c')
길이가 다른 컬렉션을 zip()에 전달하면 어떻게 되나요?
zip()는 가장 짧은 컬렉션의 끝에 도달하면 중단되며, 긴 컬렉션의 나머지 요소는 무시됩니다.
print(list(zip([1,2,3], ['a','b']))) # [(1, 'a'), (2, 'b')]
더 짧은 시퀀스를 기본값으로 보충하여 튜플을 얻으려면 어떻게 해야 하나요?
표준 zip()은 그렇게 할 수 없지만, 이를 위해 itertools.zip_longest가 있습니다:
from itertools import zip_longest for a, b in zip_longest([1,2], ['x','y','z'], fillvalue=None): print(a, b) # 1 x # 2 y # None z
zip()의 결과를 "언팩"하여 원래 리스트를 다시 얻을 수 있나요?
네, 모든 원본 컬렉션이 같은 길이를 가지며 결과가 변경되지 않았다면, * 연산자를 사용하여 zip을 펼칠 수 있습니다.
pairs = [(1,2), (3,4)] a, b = zip(*pairs) print(a) # (1, 3) print(b) # (2, 4)
길이가 다른 관련 컬렉션을 zip의 특성을 고려하지 않고 처리:
lst1 = [1,2,3,4] lst2 = ['a','b'] for x, y in zip(lst1, lst2): print(x, y) # 1 a # 2 b # (3,4)와 'c', 'd'는 lst1에서 처리되지 않았습니다.
장점:
단점:
fillvalue를 사용하여 zip_longest로 모든 요소를 보존:
from itertools import zip_longest lst1 = [1,2,3,4] lst2 = ['a','b'] for x, y in zip_longest(lst1, lst2, fillvalue='?'): print(x, y) # 1 a # 2 b # 3 ? # 4 ?
장점:
단점: