İki yinelebilen objemiz olsun. Bunları çiftler halinde döngüden nasıl geçiririz?
foo = (1, 2, 3)
bar = (4, 5, 6)
for (f, b) in some_iterator(foo, bar):
print("f: ", f, "; b: ", b)
Sonuç olarak elde etmek istediğimiz aşağıdaki gibi bir sonuç.
f: 1; b: 4
f: 2; b: 5
f: 3; b: 6
Bunu yapmanın bir yolu indeksler üzerinde yineleme yapmak:
for i in range(len(foo)):
print("f: ", foo[i], "; b: ", bar[i])
Ama bu biraz pitonik değil gibi. Peki bunu yapmanın daha iyi bir yolu var mı?
Python 3
for f, b in zip(foo, bar):
print(f, b)
zip
daha kısa bir yol sunar ve listelerden daha kısa olan durduğunda sonlanır.
Python 3’te zip
, Python2’deki itertools.izip
gibi bir demet yinelemesi döndürür. Demetlerin listesini almak için ise ziplist(zip(foo, bar))
kullanılır. Her iki öğe de bitene kadar yinelemeye devam etmek için ise itertools.zip_long
kullanılabilir.
Python 2
Python 2’de zip
, yine bir demet listesi döndürür. Bu durum öğelerimiz büyük değilken iyi olabilir. Her iki öğe de çok fazla içeriğe sahipse, zip(foo,bar)
oluşturmak gereksiz yere bir geçici değişken oluşturmaya sebep olur. Ve bu değişken oldukça büyük olacaktır. Bunun yerine itertools.izip
veya itertools.izip_longest
ile bir yineleyici oluşturmak daha iyi olacaktır.
import itertools
for f,b in itertools.izip(foo,bar):
print(f,b)
for f,b in itertools.izip_longest(foo,bar):
print(f,b)
izip
herhangi bir liste tükendiğinde durur. izip_longest
ise her iki liste de tükendiğinde durur. Daha kısa liste tükendiğinde, izip_longest
bu yinelemeye karşılık gelen konumda None değeri içeren bir tuple verir. Bunun yerine isterseniz farklı bir şey de ayarlayabiliriz.
Bu kod parçaları üzerinde biraz daha duralım. Python 3.6’nın zip()
işlevini, Python’un enumerate()
işlevini, el ile bir sayaç (bkz. count()
işlevi) oluşturmayı, bir index-listesi kullanmayı ve özel bir durum olarak bir listenin öğelerini diğer listenin indexi için kullanmayı performans açısından değerlendirelim. Performansları yazdırma ve yeni bir liste oluşturma türünden incelemek için timeit()
kullanalım. (Bu incelemeleri gerçekleştirmek için oluşturduğumuz Python komut dosyalarından biri aşağıda verilmiştir.) Gerçekçi bir karşılaştırma için listelerinin boyutlarını 10 ila 1.000.000 öğe arasında tutalım.
Sonuçlar:
- Yazdırma: Düşünülen tüm yaklaşımların performanslarının, +/-%5 doğruluk toleransını hesaba katarsak, tüm işlevler yaklaşık olarak
zip()
‘e benzer sonuç veriyor. Liste boyutu 100 öğeden küçük olduğunda iseenumerate()
işlevi ~%9 daha hızlıyken index yöntemizip()
işlevinden biraz daha yavaş kalıyor. Diğer yöntemlerzip()
işlevine benzer performans gösteriyor.

- Liste oluşturma: İki tür liste oluşturma yaklaşımına baktık : (a)
list.append()
yöntemi ve (b) liste üreteci. +/-5% doğruluk toleransını hesaba kattıktan sonra, bu yaklaşımların her ikisi için dezip()
işlevinin, bir liste indexi kullanmaktanenumerate()
işlevinden ya da sayaç kullanmaktan daha hızlı performans gösterdiği görülüyor. Bu karşılaştırmalardakizip()
işlevinin performans kazancı% 5 ila % 60 daha hızlı olabiliyor. İlginçtir ki, bir dizeyi diğeri için index olarak kullanmakzip()
işlevineeşdeğer veya daha hızlı performanslar (%5 ila% 20) sağlayabilir.

Sonuç değerlendirmesi
Bir programcı, anlamlı veya önemli olan işlemler için geçen işlem süresi miktarını belirleyebilmeli.
Örneğin, yazdırma için 144 öğeden fazla olan boyutlarda listelerin programcı için önemli bir işlem maliyetine neden olacağını görüyoruz. Yani, bu değerlendirmede daha küçük liste boyutları için belirtilen yaklaşımlarla elde edilen herhangi bir performans programcı için önemsiz olacaktır. Programcı için yazdırma eyleminde zip()
işlevinin performansının diğer yaklaşımlara benzer olduğu sonucu çıkacak.
Sonuç
Liste oluşturma için iki liste arasında yinelemede zip()
işlevinin kullanılmasında önemli performans elde edilebilir. İki listenin öğelerini yazdırmak için iki liste arasında yineleme yaparken ise zip()
işlevi, diğer yöntemlere göre benzer performans verir.
Liste oluşturmayı incelerken kullanılan Python3.6 Komut Dosyası.
import timeit
import matplotlib.pyplot as plt
import numpy as np
def test_zip( foo, bar ):
store = []
for f, b in zip(foo, bar):
#print(f, b)
store.append( (f, b) )
def test_enumerate( foo, bar ):
store = []
for n, f in enumerate( foo ):
#print(f, bar[n])
store.append( (f, bar[n]) )
def test_count( foo, bar ):
store = []
count = 0
for f in foo:
#print(f, bar[count])
store.append( (f, bar[count]) )
count += 1
def test_indices( foo, bar, indices ):
store = []
for i in indices:
#print(foo[i], bar[i])
store.append( (foo[i], bar[i]) )
def test_existing_list_indices( foo, bar ):
store = []
for f in foo: