Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

วิธีประมวลผล Iterator แบบขนานด้วย ZIP ใน Python

บทนำ

List comprehension ทำให้สร้าง derived list จาก source list ได้ง่าย เช่น คูณทุกค่าด้วย 5

ปัญหา: รวมสองลิสต์ด้วยลูป


list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]
list3 = []
for i in range(len(list1)):
    list3.append(list1[i] + list2[i])
# [600, 800, 1000, 1200]

ใช้ zip() รวม iterator แบบขนาน


list4 = [(a + b) for a, b in zip(list1, list2)]
# [600, 800, 1000, 1200]

zip จับคู่ element ตาม index: (100,500), (200,600), ... unpack เป็น a, b แล้วคำนวณ

ข้อควรระวังสำคัญ: zip หยุดเมื่อ iterator ใด iterator หนึ่งหมด


list1.append(1000)  # list1 ยาว 5, list2 ยาว 4
list5 = [(a + b) for a, b in zip(list1, list2)]
# [600, 800, 1000, 1200] - ค่า 1000 หายไป! ไม่มี error แจ้งเตือน

อันตรายใน production เพราะข้อมูลหายเงียบๆ

โซลูชัน: ใช้ itertools.zip_longest


from itertools import zip_longest

list6 = []
for a, b in zip_longest(list1, list2):
    if b is None:
        print("<< handle missing in list2 >>")
    elif a is None:
        print("<< handle missing in list1 >>")
    else:
        list6.append(a + b)
# list6 = [600, 800, 1000, 1200] (ยังคงคำนวณเฉพาะคู่ที่ครบ)
# แต่เรารู้ว่ามีค่า missing 4 ค่า จาก print

zip_longest ยืด iterator สั้นด้วย None (default) จนกว่า iterator ยาวจะหมด สามารถกำหนด fillvalue ได้

สรุป

  • zip สะดวกสำหรับ iterate หลาย iterator พร้อมกัน
  • zip หยุดเมื่อ iterator ใด iterator หนึ่งหมด (อาจทำให้ข้อมูลหายโดยไม่รู้)
  • ถ้า iterator ความยาวต่างกัน ต้องใช้ itertools.zip_longest และจัดการ fillvalue เอง