Liste kurma

Python’un liste kurma (“list comprehensions”) notasyonu ile, elemanları belli bir formüle göre oluşturulmuş listeler yaratabiliriz. Bu usül Python’da çok yaygın kullanılır ve alternatiflerine göre daha “Pythonca” sayılır.

Basit liste kurma

Sözgelişi, verilen bir listedeki sayıların karelerini barındıran bir liste oluşturalım.  Sonuç listesini başta boş bırakalım, birinci listenin elemanları üzerinden bir döngü yapalım ve her iterasyonda ikinci listeye yeni sayıyı ekleyelim.

>>> liste1 = [3,-1,4,9]
>>> liste2 = []
>>> for x in liste1:
    liste2.append(x*x)

>>> liste2
[9, 1, 16, 81]

Aynı işi daha kısa yoldan, ve daha hızlı yapmanın yolu liste comprehensions‘dır.

>>> [ x*x for x in liste1 ]
[9, 1, 16, 81]

Genel olarak liste kurma işleminde

[ <ifade> for <şey> in <sıralı nesne> ]

notasyonunu kullanırız. Genellikle <ifade> , <şey>e bağlı bir formüldür; iterasyon değişkeni olan <şey>i liste, çokuz, dize gibi bir <sıralı nesne>den tek tek alırız ve <ifade>ye <şey>e bağlı olarak değer veririz. Aynı sırayla oluşturulmuş bir liste döndürülür.

Birtakım örneklerle daha açık olacaktır.

İkinin ilk on kuvvetinin listesi:

>>> [ 2**x for x in range(11)]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

Dizenin harflerini tek tek alarak değiştirmek:

>>> [ x+"-" for x in "abcdef" ]
['a-', 'b-', 'c-', 'd-', 'e-', 'f-']

Sıralı nesne olarak bir çokuzlar listesi verildiğinde çoklu atama yapılabilir. Sözgelişi, ikizlerin elemanlarının toplamını veren bir liste kuralım:

>>> [ x+y for (x,y) in [(1,2), (8,-2), (5,-7)] ]
[3, 6, -2]

Aynısını, iterasyon değişkenini tek tek ikizlere atayarak yapmak istersek şöyle yazarız:

>>> [ x[0]+x[1] for x in [(1,2), (8,-2), (5,-7)] ]
[3, 6, -2]

Bir fonksiyon çağrısı da kullanılabilir elbet.

>>> def kare(x):
    return x*x

>>> [ kare(x) for x in range(10) ]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

>>> def topla(x,y):
    return x+y

>>> [ topla(x,y) for x,y in [(1,2), (6,3), (9,-5)] ]
[3, 9, 4]

Hız farkı

Liste kurma yöntemi, bir döngü içinde listeye eleman eklemekten daha hızlıdır. Döngü yapıları, Python gibi yorumlanan dillerde genellikle C gibi derlenen dillere göre daha yavaş çalışırlar. Üstelik her iterasyonda listenin append metodunun bulunup işletilmesi gerekir. Bir liste kurma ifadesi yine bir döngü içerse de, bu döngü alt seviyededir ve Python yorumlayıcısı tarafından daha yüksek hızda işletilir.

Python kod parçalarının hızını belirlemek için timeit modulünü kullanabiliriz. Aşağıdaki komut 0-100 arası sayıların karelerinin listesini, bir milyon kez liste kurma ile oluşturur ve kaç saniye sürdüğünü bildirir.

>>> import timeit
>>> timeit.timeit("[x*x for x in range(100)]")
6.498114109039307

Python komutunun timeit fonksiyonuna bir dize olarak verildiğine dikkat edin.

Aynısını bir for döngüsü içinde listeye tekrar tekrar eleman ekleyerek yaparsak, neredeyse iki kat vakit aldığını görüyoruz.

>>> timeit.timeit("""
liste=[]
for x in range(100):
    liste.append(x*x)
""")
10.481191158294678

Burada dize içinde satırbaşı ve kaydırma kullanabilmek için üçlü tırnak kullandık.

Şartlı liste kurma

Liste kuruluşunda belli şartlara göre listeye eleman ekleyebiliriz. Sözgelişi, kaynak listedeki elemanlardan sadece beşten büyük olanlarının karelerini alalım.

>>> [ x*x for x in [3,1,8,9,3,7,6] if x > 5 ]
[64, 81, 49, 36]

Görüldüğü gibi burada sonuç listesi kaynak listesinden daha az elemana sahip.

Çeşitli şartlar “ve”, “veya” gibi işlemlerle birleştirilebilir. Mesela, 1900 ile 2100 arasındaki artık yılların listesini oluşturalım:

>>> [ y for y in range(1900, 2101) if (y%4 == 0 and y%100 != 0) or y%400 == 0 ]
[1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936, 1940, 1944, 1948, 1952, 
1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, 2000, 2004, 
2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, 2044, 2048, 2052, 2056, 
2060, 2064, 2068, 2072, 2076, 2080, 2084, 2088, 2092, 2096]

Kural gereği 1900 ve 2100 artık yıl değildir, ama 2000 artık yıldır.

Şart kullanırken genel ifade şöyledir:

[ <ifade> for <şey> in <sıralı nesne> if <şart> ]

Bazı durumlarda, şart yanlış olduğunda da listeye belli bir eleman eklenmesini isteyebiliriz. Sözgelişi, kaynak listede negatif sayılar yerine sıfır koymak, pozitif sayıların ise karesini almak istiyoruz diyelim. Bunu, yukarıdaki usulde yapamayız, ama daha önce gördüğümüz üçlü if-else ifadesi burada işimize yarar.

>>> [ x*x if x>0 else 0 for x in range(-5,6) ]
[0, 0, 0, 0, 0, 0, 1, 4, 9, 16, 25]

Bu durumda, if-else, listede kullanılan formüle aittir, liste kurma notasyonunun parçası değildir.

İçiçe döngüler

Diyelim, iki sıralı nesneden birer eleman alarak kurulabilecek bütün ikizlerin listesini (Kartezyen çarpımı) elde etmek istiyorsunuz. Bunu içiçe iki döngü kullanarak şöyle yapabilirsiniz:

>>> liste = []
>>> for a in "abcd":
    for b in [1,2,3]:
        liste.append((a,b))

>>> liste
[('a', 1), ('a', 2), ('a', 3),
('b', 1), ('b', 2), ('b', 3), 
('c', 1), ('c', 2), ('c', 3), 
('d', 1), ('d', 2), ('d', 3)]

Liste kurma işlemiyle aynı iş şöyle yapılır:

>>> [ (a,b) for a in "abcd" for b in [1,2,3] ]
[('a', 1), ('a', 2), ('a', 3),
('b', 1), ('b', 2), ('b', 3), 
('c', 1), ('c', 2), ('c', 3), 
('d', 1), ('d', 2), ('d', 3)]

Aynı şekilde, bir işlemdeki işlenenleri ayrı listelerden alabiliriz.

>>> [ a+b for a in (3,2,6) for b in (1,9,4) ]
[4, 12, 7, 3, 11, 6, 7, 15, 10]

İstediğimiz kadar for döngüsü ekleyebiliriz.

>>> [ a+b+c for a in range(5) for b in range(3) for c in [2,3] ]
[2, 3, 3, 4, 4, 5, 3, 4, 4, 5, 5, 6, 4, 5, 5, 6, 6, 7, 5, 6, 6, 7, 7, 8, 6, 7, 7, 8, 8, 9]

Her for ile beraber bir şart da belirleyebiliriz.

>>> [ a+b for a in (3,2,6) if a > 5 for b in (1,9,4) ]
[7, 15, 10]
>>> [ a+b for a in (3,2,6) if a > 5 for b in (1,9,4) if b < 5 ]
[7, 10]

Sağ taraftaki döngüler içindeki şartları ifade ederken soldaki değişkenleri kullanabiliriz. Sözgelişi, a+b+c = 10 şartını sağlayan bütün doğal sayı üçlülerinin listesini çıkaralım.

>>> [ (a,b,c) for a in range(1,10) for b in range(1,10) for c in range(1,10) if a+b+c==10 ]
[(1, 1, 8), (1, 2, 7), (1, 3, 6), (1, 4, 5), (1, 5, 4), (1, 6, 3), (1, 7, 2),
(1, 8, 1), (2, 1, 7), (2, 2, 6), (2, 3, 5), (2, 4, 4), (2, 5, 3), (2, 6, 2), 
(2, 7, 1), (3, 1, 6), (3, 2, 5), (3, 3, 4), (3, 4, 3), (3, 5, 2), (3, 6, 1), 
(4, 1, 5), (4, 2, 4), (4, 3, 3), (4, 4, 2), (4, 5, 1), (5, 1, 4), (5, 2, 3), 
(5, 3, 2), (5, 4, 1), (6, 1, 3), (6, 2, 2), (6, 3, 1), (7, 1, 2), (7, 2, 1), 
(8, 1, 1)]

İçiçe listeler ve matrisler

Bir liste kurma işlemini bir başkasının içine yerleştirerek bir listeler listesi oluşturmak mümkün.

>>> [ [a+b for a in "abc"] for b in "xyz"]
[['ax', 'bx', 'cx'], ['ay', 'by', 'cy'], ['az', 'bz', 'cz']]

Bir matris bir listeler listesi olarak görülebilir. Listenin her elemanı (satır) başka bir listedir. Sözgelişi, \left[\begin{array}{ccc}1&2&3\\ 4&5&6\\7&8&9\end{array}\right] matrisini bu şekilde temsil etmek için

>>> [ [3*sutun + satir for satir in [1,2,3] ] for sutun in [0,1,2] ]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ifadesi kullanılabilir.

Kronecker matrisi (diyagonal elemanları 1, diğer elemanları 0 olan matris, \delta_{ij} ) şöyle kurulabilir.

>>> [ [ 1 if satir==sutun else 0 for sutun in range(5)] for satir in range(5)]
[[1, 0, 0, 0, 0],
 [0, 1, 0, 0, 0],
 [0, 0, 1, 0, 0],
 [0, 0, 0, 1, 0],
 [0, 0, 0, 0, 1]]

Diyagonal üstü bir matris (\delta_{i,j-1}) ise

>>> [ [ 1 if satir==sutun-1 else 0 for sutun in range(5) ] for satir in range(5) ]
[[0, 1, 0, 0, 0],
 [0, 0, 1, 0, 0],
 [0, 0, 0, 1, 0],
 [0, 0, 0, 0, 1],
 [0, 0, 0, 0, 0]]

Genel liste kurma ve denk döngüler

Liste kurma ifadesinin en genel hali şöyledir:

[ <ifade> for <şey1> in <sıralı1> if <şart1>
for <şey2> in <sıralı2> if <şart2>
...
for <şeyN> in <sıralıN> if <şartN> ]

Burada if kısımları mecburi değil. Bu yapı kafa karıştırıcı olabilir. Döngülerle çalışmaya alışıksanız, bu ifadenin döngü karşılığını göz önünde tutmak faydalı olabilir.

liste = []
for <şey1> in <sıralı1>:
    if <şart1>:
        for <şey2> in <sıralı2>:
            if <şart2>:
            ....
                      for <şeyN> in <sıralıN>:
                          if <şartN>:
                              liste.append(<ifade>)

Sözgelişi,

liste = [ a+b for a in range(10) if a%2==0 for b in range(8) if a+b>8 ]

listesi, döngülerle şöyle hazırlanır:

liste = []
for a in range(10):
    if a%2==0:
        for b in range(8):
            if a+b>8:
                liste.append(a+b)

Liste kurma” üzerine 6 yorum

  1. Geri bildirim: Tablo veri dosyalarını işlemek | PythonBilim

  2. Geri bildirim: Fonksiyonel programlama: map, filter, reduce | PythonBilim

  3. Hocam merhaba, yazdığınız bu post gerçekten çok işime yaradı. Alıştırma olsun diye, sizin list comprehension halinde yazdığınız kodların bir kısmını for döngüsü ile yazmaya çalışıyordum, ancak bir türlü [ [3*sutun + satir for satir in [1,2,3] ] for sutun in [0,1,2] ] için aynı sonuçları verecek for döngüsünü bulamadım. Acaba yardımcı olur musunuz ?

    Cevapla
  4. Hocam Merhaba,
    Yazdığınız bu yazılar gerçekten çok faydalı oldu,emek harcadığınız için teşekkür ediyorum.Listelerle ilgli kafama takılan bir soru var onu sorayım istedim yol gösterebilirseniz sevinirim.

    Elimde “az” listesi var ve bunun her ögesine tek tek aşağıdaki gibi ulaşabiliyorum.

    az = [[12, 56, 38],[34, 27,12],[92, 77, 66],[2, 7,15,17]]
    az_yedek=az[:]
    yedek=[]
    deger=int(input(“Sayı girin:…”))

    for x, i in enumerate(az):
    print(‘az({0}] = {1}’.format(x, i))
    if type(i) == list:
    a = x
    for y, j in enumerate(i):
    print(‘az({0}]({1}] = {2}’.format(a, y, j))
    if type(j) == list:
    b = y
    for z, k in enumerate(j):
    print(‘az({0}]({1}]({2}] = {3}’.format(a, b, z, k))

    1-kullanıcıdan her seferinde sayı girmesini istiyoruz.
    2-diyelim ki kullanıcı 12 sayısını girdi.
    3-“az”listesi içindeki ilk öğenin az[0] degeri 12 olarak bulundu yazılır.(Listenin ilk öğesi az[0] liste içinden kaldırılır,ancak az[1][2] öğesindeki 12 değeri için işlem yapılmaz.)
    4-“az”listesi içindeki tüm sayılar, girilen sayılara göre çıkarıldıktan sonra az[0] tüm öğeler tamamlanmıştır çıktısı alınır.
    5-Tamamlanan ilk liste değeri sırasıyla bir sayıya atanır ve yedek liste içinde tutulur.

    Teşekkürler ,

    Cevapla

Yorum bırakın