• Sonuç bulunamadı

Döngülenebilir Nesneleri Çözme

5.3.2 “index” metodu

5.5 Döngülenebilir Nesneleri Çözme

Bu bölümde demetlere özgü olmayan bir konuya de˘ginece˘giz. Bu konuyu buraya almamın ne-deni, konu demetlere özgü olmasa da demetlerle de ba˘glantısının bulunması, yapısı itibariyle demetleri de ilgilendirmesidir... Ayrıca bu bölüm bir bakıma bir önceki bölümün devamı olarak da dü¸sünülebilir. Çünkü burada da temel olarak aynı kavramlardan bahsedece˘giz.

Bölümümüzün konusu “Döngülenebilir nesneleri çözme”. ˙Ingilizce’de buna “Iterable Unpack-ing” diyorlar. Peki ne demek bu “döngülenebilir nesneleri çözme” denen ¸sey?

Öncelikle burada “döngülenebilir nesne” kavramından bahsetmemiz gerekiyor. ˙Ingilizce’de

“iterable” olarak adlandırılan döngülenebilir nesneler kabaca “üzerinde döngü kurulabilen her-hangi bir ¸sey” olarak tarif edilebilir. Mesela karakter dizileri döngülenebilen nesnelerdir. Ama sayılar döngülenebilen nesneler de˘gildir. Peki bir nesnenin döngülenebilip döngülenemeye-ce˘gini nasıl anlayaca˘gız? Çok basit. Bunun için kullanabilece˘gimiz ayrı bir fonksiyon bulunur Python’da... Bu fonksiyonun adıiter():

>>> iter("elma")

<str_iterator object at 0x00E4B8F0>

Bu komuttan elde etti˘gimiz çıktı “elma” karakter dizisinin bir “döngülenebilir nesne” oldu˘gunu söylüyor bize. Elde etti˘gimiz çıktıya göre, “elma” karakter dizisi, “bellekte bulundu˘gu adres 0x00E4B8F0 olan bir döngülenebilir nesne” imi¸s... Bir de ¸suna bakalım:

>>> iter(10)

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

TypeError: ’int’ object is not iterable

Burada en son satırda gördü˘gümüz “int object is not iterable” ifadesinden anlıyoruz ki sayılar döngülenebilir nesneler de˘gilmi¸s... Dolayısıyla buradan ¸su sonucu çıkarıyoruz: Python’da karakter dizileri döngülenebilirken, sayılar döngülenemez. Yani karakter dizileri üzerinde mesela birfor döngüsü kurabiliriz, ama sayıların üzerinde bir for döngüsü kuramayız...

Konumuz demetler oldu˘guna göre, bir de demetlerin durumuna bakalım:

>>> iter(())

<tuple_iterator object at 0x00E4B910>

Burada demetlerin ayırt edici özelli˘gi olan “()” i¸saretlerini kullandı˘gımıza dikkat edin. Listeler için ise ¸söyle bir ¸sey yapabiliriz:

>>> iter([])

<list_iterator object at 0x00E4B8F0>

Demek ki tıpkı demetler gibi, listeler de döngülenebilir nesnelermi¸s...

“Döngülenebilir Nesneleri Çözme” ifadesinin “Döngülenebilir Nesne” kısmını anladı˘gımıza göre, gelelim bu nesneyi “çözme” meselesine... Döngülenebilir nesneleri çözmeyi aslında biliy-oruz. Yukarıda dedi˘gimiz gibi, demetler bir döngülenebilir nesnedir. Geçen bölümde demet-lerin nasıl çözülece˘gini (tuple unpacking) gördük. Dolayısıyla döngülenebilir nesneleri nasıl çözece˘gimizi de tahmin edebiliriz... Zira demetler de bir döngülenebilir nesne oldu˘gu için,

“demet çözme” i¸sleminin kendisi de aslında bir “döngülenebilir nesne çözme” i¸slemidir...

Hatırlarsanız demet çözme i¸slemini ¸su ¸sekilde yapıyorduk:

>>> demet = (0, 1, 2)

>>> a, b, c = demet

Elbette konumuz demetler oldu˘gu için örne˘gimizi önce bir demet tanımlayarak yaptık. Ama tabii ki illa demet tanımlamak zorunda de˘giliz. Yukarıdaki kodları ¸söyle de yazabiliriz:

>>> aralık = range(3)

>>> a, b, c = aralık

Öncelikle burada tanımladı˘gımız ¸seyin bir demet olmadı˘gına dikkatinizi çekmek isterim. “ar-alık” de˘gi¸skeninetype() fonksiyonunu uygularsanız bu verinin tipinin “tuple” olmadı˘gını göre-ceksiniz...

Ayrıca burada tek tek “0, 1, 2” yazmak yerine,range() fonksiyonunun bize sundu˘gu kolaylık-tan yararlandı˘gımıza da dikkat edin...

Demetimizi veya aralı˘gımızı tanımladıktan sonra a, b ve c de˘gi¸skenlerini kullanarak demetin veya aralı˘gın ö˘gelerini tek tek yazdırabiliriz. Burada önemli nokta, e¸sitli˘gin sol tarafındaki nesne sayısı ile sa˘g tarafındaki nesne sayısının aynı olmasıdır. Yani sol tarafta “a”, “b” ve “c”

gibi üç adet nesneye kar¸sılık, sa˘g tarafta da “0”, “1” ve “2” gibi üç adet ö˘ge var. Bu arada yukarıdaki kodları istersek ¸söyle de yazabiliriz elbette:

>>> a, b, c = range(3)

Bunu böyle yazdıktan sonra normal bir ¸sekilde “a”, “b” ve “c” de˘gi¸skenlerini kullanarak 0’dan 3’e kadar olan sayıları ekrana dökebiliriz.

Tanımı gere˘gi, döngülenebilir nesneleri çözebilmek için, e¸sitli˘gin sa˘g tarafında takdir edersiniz ki döngülenebilir bir nesne olması gerekiyor... Mesela bu bölümün ba¸sında sayıların döngülen-emedi˘gini ö˘grenmi¸stik. Dolayısıyla ¸söyle bir ¸sey yazamayız:

>>> a, b, c = 5

TypeError: ’int’ object is not iterable

Bu hata bize “int” nesnesinin döngülenemeyece˘gini söylüyor. Buradaki sorun e¸sitli˘gin sol ve sa˘g tarafındaki ö˘ge sayısının aynı olmamasından kaynaklanmıyor. Sebep “int”, yani sayı veri tipinin döngülenemez bir nesne olması... Bu durumu daha net olarak ¸su örnekte görebiliriz:

>>> a, b, c = "su"

ValueError: need more than 2 values to unpack

Gördü˘günüz gibi burada aldı˘gımız hata farklı. Buradaki sorun e¸sitli˘gin sol ve sa˘g tarafında aynı sayıda ö˘ge olmamasından kaynaklanıyor. Yoksa “su” karakter dizisi döngülenebilir bir nesne oldu˘gu için ö˘ge sayısını tutturmamız yeterli olacaktır. Zaten aldı˘gımız hata, çözme i¸slemi için 2’den fazla de˘ger gerekti˘gini söylüyor bize...

>>> a, b, c = "Can"

“Peki ben “a”, “b” ve “c” de˘gi¸skenlerinin üçüne birden tek de˘ger vermek istiyorsam ne ya-paca˘gım?” diye soruyor olabilirsiniz... Yani mesela hem a, hem b, hem de c de˘gi¸skeninin de˘gerinin “Can” olmasını istersek bunu nasıl yapaca˘gız? ¸Söyle yapaca˘gız:

>>> a = b = c = "Can"

Ancak ¸söyle bir deneme sizi hüsrana u˘gratabilir:

>>> a = b = c = 1, 2, 3

Burada her bir de˘gi¸sken 1, 2 ve 3 sayılarının üçünü birden içine alacaktır. Yani mesela “a”

komutunu verdi˘gimizde ¸söyle bir çıktı elde edece˘giz:

>>> a (1, 2, 3)

Aldı˘gımız bu çıktı, neden istedi˘gimiz gibi bir çıktı elde edemedi˘gimizi aslında açıklıyor.

Dikkat ederseniz aldı˘gımız çıktının veri tipi bir demettir. ˙Isterseniz a de˘gi¸skenine type() fonksiyonunu uygulayarak bunu kendiniz de do˘grulayabilirsiniz. Zira yukarıda yaptı˘gımız ¸sey aslında bir önceki bölümde ö˘grendi˘gimiz “demetleme” (tuple packing) i¸sleminin ta kendisidir...

Demetleme i¸slemini yaptıktan sonra isterseniz bu demeti çözebilirsiniz de...

>>> bir, iki, üç = a

>>> bir 1

>>> iki 2

>>> üç 3

¸

Simdiye kadar verdi˘gimiz örneklerde e¸sitli˘gin sol ve sa˘g tarafının aynı sayıda ö˘ge içermesi gerekiyordu. Peki ya diyelim ki elimizde ¸söyle bir demet var:

>>> fedailer = ("Ahmet", "Mehmet", "Özcan", "Kezban", "Süreyya", "Cevat")

Yapmak istedi˘gimiz ¸sey bu demeti “ilk”, “orta” ve “son” olarak gruplandırmak olsun... Bu i¸slemi acaba nasıl yapmalıyız?

˙Iste˘gimizi gerçekle¸stirmek için iki yöntem var önümüzde. Birinci yöntemde Python’daki “dil-imleme” (slicing) özelli˘ginden yararlanabiliriz:

>>> ilk, orta, son = fedailer[:1], fedailer[1:-1], fedailer[-1]

Ö˘geleri bu ¸sekilde tanımladıktan sonra “ilk”, “orta” ve “son” de˘gi¸skenlerini kullanarak her bir grubu ayrı ayrı yazdırabiliriz.

Gelelim ikinci yönteme... Bu ikinci yöntem Python 3.0 ile birlikte gelen bir özelliktir. Python’un 3.0’dan önceki sürümlerinde bu özellik bulunmaz:

>>> ilk, *orta, son = fedailer

>>> ilk

’Ahmet’

>>> orta

[’Mehmet’, ’Özcan’, ’Kezban’, ’Süreyya’]

>>> son

’Cevat’

Gördü˘günüz gibi, Python 3.0 ile birlikte yukarıdaki i¸slevi çok daha basit ve temiz bir ¸sekilde yerine getirebiliyoruz. Burada “*” i¸saretinden yararlandı˘gımıza dikkat edin. Bu tür ifadelere Python’da “starred expressions” (yıldızlı ifadeler) adı verilir. Python 3.0 ile birlikte bu yıldızlı ifadeler daha geni¸s bir kullanım alanına kavu¸stu. Hatta print() fonksiyonu içinde bile bu yıldızlı ifadelerden yararlanabiliriz. Yıldızlı ifadelerinprint() fonksiyonunda kullanımı ile ilgili örnekleri birkaç bölüm sonra görece˘giz...

Yukarıdaki örnekte kullandı˘gımız yıldızlı ifade, “ilk” ve “son” adlı de˘gi¸skenler ile belirlenen ö˘gelerin dı¸sında kalan öteki bütün ö˘geleri tanımlayabilmemizi sa˘gladı. Ayrıca burada yıldızlı ifade ile elde etti˘gimiz kısmın bir liste oldu˘guna da dikkat edin. Burada normal olarak liste yerine demet verilmesi beklenebilirdi, ama çıktı üzerinde daha kolay i¸slem yapılabilmesi için Python geli¸stiricileri buradaki yıldızlı ifadenin çıktısının liste veri tipinde olmasını uygun gör-mü¸slerdir... Gerçekten de de˘gi¸stirilebilir (mutable) bir veri tipi olan listeler üzerinde i¸slem yapmak, de˘gi¸stirilemeyen (immutable) bir veri tipi olan demetler üzerinde i¸slem yapmaktan çok daha kolaydır.

Döngülenebilir nesneleri çözme i¸sleminin bu geni¸sletilmi¸s haline ili¸skin bütün özellikler ve bu yeni i¸slevin gerekçeleri, http://www.python.org/dev/peps/pep-3132/ adresinde bulunan PEP 3132‘de açıklanmı¸stır... E˘ger bu konuyla ilgili olarak ˙Ingilizce kaynaklarda arama yapmak isterseniz, kullanmanız gereken ifade “Extended Iterable Unpacking” olacaktır...

Böylelikle Python’da “demetler” konusunu da bitirmi¸s olduk. Bu bölümde pek çok ¸sey ö˘grendik. Bu ö˘grendiklerimizi birkaç kez gözden geçirerek bilgilerimizi peki¸stirme yoluna git-memiz, ilerde görece˘gimiz konuları daha iyi kavrayabilmek bakımından oldukça faydalı olacak-tır.

BÖLÜM

6

Sözlükler

Bu bölümde Python’daki en verimli ve en kullanı¸slı veri tiplerinden birini inceleyece˘giz.

Bölümümüzün konusu sözlükler. Sözlükler Python’un bir hayli güçlü araçlarından bir tanesidir.

O kadar ki, istersek sözlükleri basit bir veritabanı niyetine bile kullanabiliriz.

¸

Simdiye kadar ¸su veri tiplerini görmü¸stük:

1. Karakter Dizileri 2. Sayılar

3. Listeler 4. Demetler

¸

Simdi ise bunlara bir de sözlükleri ekleyece˘giz. Sözlükler ¸sekil olarak öteki veri tiplerinden bi-razcık farklı bir görünüme sahiptir. Ayrıca mesela listeler “sıralı diziler” (ordered sequence) ¸ sek-linde tanımlanan bir gruba girerken, sözlükler “sırasız diziler” (unordered sequence) grubuna dahildir. Burada sıralı-sırasız kavramlarıyla kastetti˘gimiz ¸seyin ne oldu˘gunu asıl konumuza geçti˘gimizde ö˘grenece˘giz.

˙Isterseniz lafı daha fazla dolandırmadan asıl mevzuya geçelim. Ben sizin, sözlükleri ö˘ grendik-ten sonra bu veri tipini çok sevece˘ginize eminim...