[Python] Skill of coding - iterator를 병렬로 처리하려면 zip을 사용하자

Hyeseong·2020년 12월 9일
0

python skill of coding

목록 보기
3/18

iterator로 병렬로 처리하려면 zip을 사용하자

파이썬에서 관련 객체로 구성된 리스트를 많이 사용한다는 사실은 쉽게 알수 있어요. 리스트 컴프리헨션을 사용하면 source list에 표션식을 적용하여 파생리스트(derived list)를 쉽게 얻을 수 있어요

names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]
print(letters)
[7, 4, 5]

파생 리스트의 아이템과 소스 리스트의 아이템은 서로 인덱스로 연과되어 있어요. 따라서 두 리스트를 병렬로 순회하려면 소스 리스트인 names의 길이만큼 순회하면 되요.

longest_name = None
max_letters = 0

for i in range(len(names)):
    count = letters[i]
    if count > max_letters:
        longest_name = names[i]
        max_letters = count

print(longest_name)
Cecilia

문제는 루프문의 보기 좋지 않다는 것이다. names와 letters를 인덱스로 접근하면 코드를 읽기 어려워진다. 루프의 인덱스 i로 배열에 접근하는 동작이 두 번 일어난다. enumerate를 사용하면 이런 문제점을 약간 개선할 수 있지만, 여전히 완벽하지 않다.

longest_name = None
max_letters = 0
for i, name in enumerate(names):
    count = letters[i]
    if count > max_letters:
        longest_name = name
        max_letters = count
print(longest_name)
Cecilia

내장함수 zip을 이용하면 더 명료하게 코드를 사용할 수 있다.
zip은 지연 제너레이터로 이터레이터 2 개 이상을 감싼다. zip 제너레이터는 각 이터레이터로부터 다음 값을 담은 튜플을 얻어온다. zip 제너레이터를 사용한 코드는 다중 리스트에서 인덱스로 접근하는 코드보다 훨씬 명료하다.

names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]

longest_name = None
max_letters = 0
for name, count in zip(names, letters):
    if count > max_letters:
        longest_name = name
        max_letters = count
print(longest_name)
Cecilia

내장 함수 zip을 사용할 때 문제점!

입력 이터레이터들의 길이가 다르면 zip이 이상하게 동작한다는 점. names 리스트에 다른 이름을 추가했지만 letters의 카운터를 업데이트하는 것을 잊었다고 해보자. 두 입력 리스트에 zip을 실행하면 예상치 못한 결과가 나옴

names = ['Cecilia', 'Lise', 'Marie']
letters = [len(n) for n in names]

names.append('Rosalind')
for name, count in zip(names, letters):
    print(name)
Cecilia
Lise
Marie

'Rosalind' 가 결과에 없다.
zip은 감싼 이터레이터가 끝날 때까지 튜플을 계속 넘겨준다. 이 방식은 이터레이터가 == 때는 잘 동작함. zip으로 실행할 리스트의 길이가 같다고 확실 할 수 없다면 대신 내장 모듈 itertools의 zip_longest를 사용하자.

핵심 정리

  • 내장함수 zip은 여러 이터레이터를 병렬로 순횔할 때 사용할 수 있다.
  • zip은 튜플을 생성하는 지연 제너레이터다
  • 길이가 다른 이터레이터를 사용하면 zip은 그 결과를 잘라낸다
  • 내장 모듈 itertools의 zip_longest 함수를 쓰면 여러 이터레이터를 길이에 상관없이 병렬ㄹ로 순회할 수 있다.
profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글