ProgramlamaBackend geliştirici

Python'da zip() yerleşik işlevi nasıl çalışır, ne için kullanılır ve farklı uzunluktaki dizilerin işlenmesinde hangi ince noktalar vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Sorunun Tarihi

zip() işlevi Python 2'de ortaya çıkmıştır (o zaman liste döndürüyordu), Python 3 ile birlikte tembel bir iteratör döndürmeye başladı. Birkaç diziyi eleman bazında tuple'lara "birleştirir", bu da paralel olarak yineleyen koleksiyonların işlenmesini kolay ve verimli hale getirdi.

Problem

Genellikle birkaç listeyi (veya başka tür dizileri) aynı anda işlemek gerekir; örneğin, anahtar-değer çiftleri üzerinden geçmek veya nokta-pair koordinatlarını işlemek. Gösterge senkronizasyonu yapmak, özellikle farklı uzunluktaki koleksiyonlar için hataların ve okunabilirliğin kaynağıdır.

Çözüm

zip() işlevi herhangi bir sayıda yineleyici nesneyi kabul eder ve her bir yineleyici nesneden karşılık gelen elemanları içeren tuple'lar döndüren bir iteratör sunar. Eğer diziler farklı uzunluktaysa, sonuç en kısa olanla sona erer.

Kod Örneği:

names = ['Alice', 'Bob', 'Charlie'] ages = [24, 27, 30] for name, age in zip(names, ages): print(f'{name} {age} yaşında')

zip'i * ile açmak mümkündür:

pairs = [(1, 'a'), (2, 'b'), (3, 'c')] nums, chars = zip(*pairs) print(nums) # (1, 2, 3) print(chars) # ('a', 'b', 'c')

Anahtar Özellikler:

  • zip() (Python 3'te) bir iteratör döndürür, liste değil.
  • zip() işlemi en kısa yineleyici üzerinde durur.
  • Açık indeks kontrollü olmaksızın koleksiyonların paralel işlenmesine olanak tanır.

Tuzak Soruları.

Farklı uzunluktaki koleksiyonları zip()'e verirsek ne olur?

zip() en kısa koleksiyonun sonuna ulaştığında durur — uzun koleksiyonların diğer elemanları göz ardı edilir.

print(list(zip([1,2,3], ['a','b']))) # [(1, 'a'), (2, 'b')]

Daha kısa dizileri varsayılan bir değer ile tamamlayarak tuple'lar almak mümkün mü?

Standart zip() bunu yapamaz, ancak bu tür bir davranış için itertools.zip_longest mevcuttur:

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() sonucunu "açarak" orijinal listeleri tekrar elde etmek mümkün mü?

Evet, eğer tüm orijinal koleksiyonlar aynı uzunluktaysa ve sonuç değiştirilmemişse, * operatörü ile zip'i açmak mümkündür.

pairs = [(1,2), (3,4)] a, b = zip(*pairs) print(a) # (1, 3) print(b) # (2, 4)

Tipik Hatalar ve Antipatternler

  • zip()'in her zaman en uzun koleksiyonun sonuna kadar "gideceğini" beklemek.
  • Python 3'te zip()'in liste döndürdüğünü varsaymak (bu bir iteratördür, bazen list() ile sarmak gerekir).
  • Her bir yinelemede tüketilen değişken kaynaklarla zip üzerinde çalışmak.

Gerçek Hayat Örneği

Olumsuz Durum

Farklı uzunluktaki ilişkili koleksiyonları zip'in özelliklerini göz önünde bulundurmadan işlemek:

lst1 = [1,2,3,4] lst2 = ['a','b'] for x, y in zip(lst1, lst2): print(x, y) # 1 a # 2 b # (3,4) ve lst1'den 'c', 'd' işlenmedi

Artılar:

  • Dizilerin aynı uzunlukta olması garanti olduğunda basit ve anlaşılır.

Eksiler:

  • Koleksiyonların gerçek uzunluklarına farklılık gösterirse değer kaybı.

Olumlu Durum

Bütün elemanların işlenmesini garanti altına almak için zip_longest'i fillvalue ile kullanmak:

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 ?

Artılar:

  • Tüm elemanların işlenmesi garanti edilmiştir.
  • "Boş" bir değer kesin olarak belirtilmiştir.

Eksiler:

  • Harici bir modül import etmek gerekir.
  • fillvalue'yi unutmamak önemlidir, aksi takdirde varsayılan olarak None olur.