koddla

Yazılımcıları bilgi ile güçlendirir.

Python’da iki liste aynı anda nasıl döndürülür?

İ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:

  1. 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 ise enumerate() işlevi ~%9 daha hızlıyken index yöntemi zip() işlevinden biraz daha yavaş kalıyor. Diğer yöntemler zip() işlevine benzer performans gösteriyor.
  1. 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 de zip() işlevinin, bir liste indexi kullanmaktan enumerate() işlevinden ya da sayaç kullanmaktan daha hızlı performans gösterdiği görülüyor. Bu karşılaştırmalardaki zip() işlevinin performans kazancı% 5 ila % 60 daha hızlı olabiliyor. İlginçtir ki, bir dizeyi diğeri için index olarak kullanmak zip() 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:

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Back to top