Computer >> 컴퓨터 >  >> 프로그램 작성 >> Python

ZIP을 사용하여 반복자를 병렬로 처리하는 방법

<시간/>

소개

목록 이해를 사용하면 소스 목록을 쉽게 가져오고 표현식을 적용하여 파생 목록을 얻을 수 있습니다. 예를 들어 목록의 각 요소에 5를 곱하고 싶다고 가정해 보겠습니다. 여기서는 간단한 for 루프를 사용하여 이 작업을 수행합니다.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
multiply_by_5 = []
for x in a:
multiply_by_5.append(x*5)
print(f"Output \n *** {multiply_by_5}")

출력

*** [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

목록 이해를 사용하면 반복할 표현식과 입력 시퀀스를 지정하여 동일한 결과를 얻을 수 있습니다.

# List comprehension
multiply_by_5 = [x*2 for x in a]
print(f"Output \n *** {multiply_by_5}")

출력

*** [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

이제 추가할 목록이 몇 개 있다고 가정해 보겠습니다.

# 1 . Create a List of Numbers
list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]

# 2. Add the two lists to create a new list
list3 = []

# Using a Loop.
for i in range(len(list1)):
added_value = list1[i] + list2[i]
list3.append(added_value)
print(f"Output \n*** {list3}")

출력

*** [600, 800, 1000, 1200]

이제 여기서 중요한 것은 추가된 값의 파생 목록(여기서는 list3)에 있는 항목이 인덱스를 통해 소스 목록에 있는 항목과 직접적으로 관련되어 있다는 것입니다.

이제 압축이 진행되는 한 동일한 목록 정수에 대한 압축 솔루션이 있습니다. 이 경우 두 개의 정수 목록이 있습니다. 하나는 100, 200, 300, 400을 포함하고 다른 하나는 500, 600, 700, 800을 포함합니다. 물론, 우리는 그것들을 정의하고 변수에 할당할 수 있습니다. 목록이 필요하지 않습니다.

튜플과 같은 다른 시퀀스일 수 있습니다.

그래서 우리가 할 일은 그것들의 요소 쌍을 함께 압축하는 것이므로 list1의 100개와 list2의 500개는 함께 압축되는 식입니다. 각 튜플에 대해 반복하면서 튜플을 변수 및 b로 압축을 풉니다.

list4 = []
list4 = [(a + b) for a, b in zip(list1, list2)]
print(f"Output \n*** {list4}")

출력

*** [600, 800, 1000, 1200]

이제 위의 솔루션이 정말 멋져 보이지만 코드에 적용하기 전에 알아야 할 심각한 문제가 있습니다.

zip 내장 함수는 입력 반복자의 길이가 다른 경우 이상하게 작동합니다. 시도해 보겠습니다.

# add a new number to the list
list1.append(1000)
print(f"Output \n*** Length of List1 is {len(list1)} , Length of List2 is {len(list2)}")

# run the zip against the list for addition.
list5 = [(a + b) for a, b in zip(list1, list2)]
print(f"*** {list5}")

출력

*** Length of List1 is 9 , Length of List2 is 4
*** [600, 800, 1000, 1200]

이제 list3에서 추가된 각 번호를 인쇄할 때 list1에 추가된 번호가 누락되었음을 알 수 있습니다. 추가한 번호는 list1에 있고 zip의 출력에는 표시되지 않습니다.

그리고 이것이 바로 zip이 작동하는 방식입니다. 반복자 중 하나가 소진될 때까지 튜플을 유지합니다. 따라서 list1이 list2에 비해 더 가야 할 것이 있지만 먼저 소진되어 루프가 종료됩니다.

놀랍게도, 당신은 어떤 예외도 통지받지 않습니다. 따라서 프로덕션에서는 zip에 매우 주의해야 합니다.

이 문제에 대한 옵션은 zip long이라는 itertools의 python 함수에 있습니다.

이 zip이 가장 긴 것은 반복자 중 하나가 소진된 경우에도 계속 진행됩니다.

from itertools import zip_longest

list6 = []
for a, b in zip_longest(list1, list2):
if b is None:
print(f" << do your logic here >> ")
elif a is None:
print(f" << do your logic here >> ")
else:
list6.append(a + b)
print(f"Output \n*** {list6}")


<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>

출력

*** [600, 800, 1000, 1200]

결론:

  • 여러 반복자를 병렬로 반복하려는 경우 zip 함수가 매우 편리합니다.

  • zip 함수는 길이가 다른 반복자를 전달할 때 다르게 작동합니다.

  • 길이가 다른 반복자를 사용하려면 zip_longest를 사용하세요.