Python Programlama Dili

Bölüm 3

Veri Tipleri

Top Navigasyon

Ders 21

3.3 - Sözlük (Dictionary) Tipi Veriler

Koleksiyon tipi veriler, bilgisayar bilimlerinde "Veri Yapıları" (Data Structures) olarak adlandırılır. Liste ve topluluk (tuple) veri yapılarından sonra, bu seksiyonda sözlük (dictionary) veri tipini inceleyeceğiz.

Sözlük tipi veriler, belirli bir düzeni olmayan,  sayıları istendiği kadar olabilen, anahtar:değer çiftleridir. Sözlükler süslü parantez {} içinde gösterilirler.

Sözlük anahtar değerleri benzersiz (unique) ve hashable değerler olmalıdır. Bunlar tek değer olabildikleri gibi df = {('Bölge', 1):16} tanımında olduğu gibi bileşik (kompozit) anahtar değerleri de olabilirler. Bileşik anahtar değerleri, sadece hashable tipte topluluklar veya frozensetler olabilir. Listeler kompozit anahtar değerleri olarak kullanılamaz, çünkü değişmez tipte değillerdir. Bundan başka her durumda, her geçerli Python tanıtıcısı sözlük anahtarı olarak kullanılabilir. Anahtar değeri olarak önceden belirtilmiş bir değer verilmek istenirse, eski anahtar: değer çifti silinir, yerine yeni tanımlanan anahtar:değer çifti yerleştirilir. Değerler ise, her geçerli Python veri tipinden olabilir. Sözlük tipi verilerde, indis tanımı yoktur. Bu yüzden dilimleme ile alt sözlüklere ayrılamaz. Ayrıca, indis tanımı olmadığından, sözlüklerde eleman dizilişi tamamen, gelişigüzel (random) niteliktedir. Belirli bir düzene göre yapılandırılmış sözlük verilerinin oluşturulması için özel sıralama yöntemlerinin uygulanması gerekir.

Sözlükler, değişebilir (mutable) veri tiplerindendir. Bir kez tanımlandıktan sonra kısmen değiştirilip güncellenebilirler.

3.3.1 - Sözlük Tipi Verilerin Oluşturulması

Sözlük tipi veriler, boş bir çift  süslü parantez kullanılarak yaratılabilir. Örnek.

İstenirse, süslü parantez içeriğinde anahtar:değer çiftleri ile yaratılabilir. Örnek:

Eğer var olan bir anahtar ile yeni bir anahtar:değer çifti yaratılmak istenirse, eski anahtar:değer çifti silinir ve yerine yeni anahtar:çifti konulur. Örnek

Görüldüğü gibi, anahtar değerleri mutlaka benzersiz olmalıdır. Aksi halde veri temelinde değer karmaşası yaşanır. Bunun için anahtar değerlerinin saptanmasında olağanüstü dikkat gerekir. Oluşturulan sözlükler de sıralama olmadığı ve yaratılan elemanların belirli bir sıra düzenine uymadan, gelişigüzel olarak oluşturulduğuna dikkat edilmelidir.

Sözlükler, öntanımlı dict() fonksiyonu kullanılarak başka koleksiyon veri tiplerinden, sözlük veri tipine dönüştürerek de yaratılabilir. Örnek:

Zaten tanımlanmış bir sözlüğü, yeniden sözlük tipine dönüştürmek çok akıllıca görünmemesine karşın, dict () öntanımlı fonksiyonunun sözlüklerin yüzeysel kopyalanmaları için bir yöntem oluşturduğu, bu program ile görülmektedir. Bu işlem, istenirse, aşağıda görüldüğü gibi, bir ara atama yolu ile de gerçekleştirilebilir.

Doğal olarak, bir liste veya topluluk gibi başka koleksiyon tipinde olan verilerin öntanımlı dict() fonksiyonu yardımı ile sözlük tipine dönüştürmek çok daha anlamlı olacaktır. Örnekler aşağıda görülmektedir:

Yukarıdaki uygulama, kodların nasıl kompakt hale getirilebileceğinin görülmesi için iyi bir örnektir. Kodların bu şekilde kompakt hale getirilmesi, programın iyi anlaşılmasını, özellikle ilk geliştirme sürecinde çok zorlaştırır ve kesinlikle bu işlem programın ilk sürümlerinde değil, çok daha sonra, program iyice yerleşik ve fonksiyonel hale geldikten sonraki sürümlerinde, güncelleme işlemleri arasında yapılmalıdır.

Başlangıç sürümlerinde, programlar daha açık ve anlaşılır olmalıdır. Örnek :

Yukarıdaki programda görüldüğü gibi, bileşik olmayan anahtar değerleri için listeler kullanılabilir. Veri yapısı sözlük tipine dönüştürülecek bir koleksiyonun veri yapısı, bu dönüştürmeye uygun olmadır. Aksi halde hata oluşur. Buna şekil (shape) koşulunun uygunluğu adı verilir.

Aynı yöntemle, veri yapısı uygun olan koleksiyonlar da, dict() öntanımlı fonksiyonunun argümanı olarak tanımlandıklarında sözlük veri tiplerine dönüştürülebilirler. Örnek:

Bu uygulamanın

Bu uygulama, dict () fonksiyonun, uygun yapılı topluluklarını, sözlük veri tipine dönüştürülebileceklerini açıkça göstermektedir. Bu uygulamanın daha da ilginci zip () fonksiyonun da olaya dahil olmasıdır. Örnek:

Yukarıdaki program çok ilginç ve pratik bir sözlük yaratma metodunu belirtmektedir. Bu metotla, bileşik anahtar değerli sözlükler de yaratılabilir. Sadece, bileşik anahtar değerli sözlüklerin anahtar değeri olarak sadece değişemez ve hashable koleksiyonlar kullanılabilir.  Bu kriteryumu da sadece hashable toplukluklar ve frozensetler karşılayabilir. Listeler, bileşik anahtar değerli sözlüklerin anahtar değerleri olarak kullanılamaz. Listelerin, sözlük anahtar değerleri olarak kullanılamadıkları tek kısıtlama da budur.

Bu sözlük oluşturma yönteminin, sıradan ve ve oluşturuğu sözlüklerin diğer metotlarla da yapılabileceği düşünülebilir. Küçük çapta sözlükler için bu düşünce doğru da olabilir. Fakat, biraz düşününce, bu yöntemin inanılmaz bir olanak sağladığı anlaşılacaktır. Sözlük değerlerinin aynı zamanda nesne sınıf örneklerinden oluşabileceği gözönüne alınmalıdır. İstenilen bir veri yapısı sınıfı yaratarak, bunun binlerce sınıf örneğini bir disk dosyasına yerleştirip, bir koleksiyon tipi verinin elemanları olarak okutmak ve bir başka dosyadan okutulan anahtar değerleri ile akuple ederek, tüm bu anahtar:değer çiftlerini, zip () fonksiyonu ile, bir sözlükte birleştirmek büyük çapta bir veri temeli yaratmak anlamına gelmektedir. Böyle bir veri temelinde, çoklu anahtar değerlerinin her bir anahtarının, nesne örneği değerin bir başka özelliğine denk getirilmesi inanılmaz yetenekli bir dinamik veri temelinin geliştirilmesi anlamına gelir. Bu veri temeli dinamik olacaktır çünkü, disk dosyalarında veriler her an güncellenebilir niteliktedir. Veri temeli de statik olmayıp, her çağrıldığında değişik disk dosyaları okunup zip () fonksiyonu ile çalışma sürecinde (runtime) olarak birleştirildiğnden tam dinamik karakterde olacaktır. Yine de, bu bir amatör veri temelidir ve verilere erişim çok hızlı olmayabilir. Bu yüzden erişim hızı çok kritik ise, Python programlama dilinin, çok kullanışlı veri temeli bağlantılarından yararlanarak profesyonel bir veri temeli ile, örnek olarak MySql ile çalışmak çok daha iyi olabilir.

Sözlükler, değişebilir tipte veriler olduklarından, aynı zamanda dictionary comprehensions denilen yöntemle de yaratılabilirler. Bu yöntemi, topluluklar ile de incelemiştik. Burada da tekrar edelim. Topluluklardan farklı olarak, sözlüklerde, hem anahtar, hem değer vermek gerekir. Anahtarları bir listeye, değerleri bir başka listeye yerleştirirsek ister zip() fonksiyonu ile, istersek iki içiçe for in döngüleri ie bunları bir sözlükte birleştirebiliriz. Örnek:

Öntanımlı zip() fonksiyonu ile daha da pratik:

Sözlüklerin yapılanması sırasında belirli koşullar da belirleyebiliriz. Örnek:

Eleman değerleri belirli koşulları sağlayan sözlüklerin oluşturulması, zip() ile kolaydır. Örnek:

Burada sözlük iki terimli anahtar ve tek değerden oluşuyor. Önce zip() fonksiyonunu uygulayarak sözlük ve seri adlı iki bağımsız sözlük verisi oluşturuyoruz. Sonra seri sözlüğünün elemanlarını tarayarak değeri 40 dan büyük olan elemanın anahtar değerini saptayarak, bu anahtar:veri çiftini, sözlük sözlüğünden çıkartıyoruz. Eleman sayısı tamamlanınca, sözlük sözlüğünde istediğimiz özellikleri sağlayan elemanlar kalmış oluyor.

Dictionary comprehensions yöntemi yukarıdaki işlemleri daha kısaltmak için gerçekleştirilmiştir. Ne yazık ki bu basit yöntem, ratladığım hiçbir kaynakta açık ve adım adım anlatılamamış ve bu nedenle kullanıcılar çoğu kez bu kolay yöntemi kullanmaktan kaçınmaktadırlar. Oysa ilk kural ile başlayalım:

Bu durumda, dictionary comprehensions yöntemini uygulamak için, ilk önce sözlüğün yaratılması için yararlanılacak koleksiyonun (liste, topluluk, küme, donmuş küme) daha önce dikkatle hazırlanması gereklidir.

Sözlüklerin yaratılması için gerekli dosyanın yaratılması hiç zor değildir. Bu koleksiyon, oluşacak sözlüğün anahtar : veri çiftlerinin oluşturulabilmesi için gerekli değerleri sağlamalıdır. Yani, bu dosyanın her elemanı, sözlük oluşturulması için yeterli bilgiyi sağlamalıdır. Bu da çok basit olarak sağlanabilir. Bazı olasılıkları gözden geçirelim:

Bir anahtar listesi

Bu liste sadece anahtar bilgilerini içermektedir. Eğer böyle bir listenin elemanları ile bir sözlük oluşturulacaksa, bu liste sadece anahtar değerlerini sağlayabilecektir. Durum aşağıda görüldüğü gibi olacaktır:

Anahtarlar bulundu, ama bu anahtarlara karşı gelecek değerler bulunumazsa sözlük oluşturulamaz. Değerler önceden belirlenmişse, sözlük oluşturulabilir. Bu değerlerin nasıl belirlenebilecekleri belirli olasılıklarla belirlenebiir.

Bir olasılık, bu anahtar değerleri ile veriler arasında, matematik bir bağıntı olabileceği ve değerlerin, verilerin anahtar değerlerinden saptanabileceğidir. Örnek olarak veri = sin(anahtar) olabilir. Bu durumda, sözlük dosyası tamamlanmıştır. Görevin geri kalanını, dictionary comprehensions üstlenip sözlüğü oluşturacaktır.

Bir başka olasılık, her bir anahatar değerine karşı, bir gözlem yapılmış olduğu ve bu gözlem değerlerinin bir veri listesine kaydedilmiş olmasıdır. Bu da fizikte çok rastlanan ikili bir ilişki anlamına gelir. Örnek olarak, belirli sıcaklıklara karşı gelen su buharı basınçları okunup bir listeye kaydedilmiş olabilir. O zaman da, anahtar ve veri dosyalarını zipleyerek (anahtar, veri), (anahtar, veri) çiftlerini oluşturmuş oluruz. Ziplenmiş verileri bir listeye yerleştiririz ve bundan sonrasını dictionary comprehension halleder.

Dictionary comprehension yöntemi iki türlü uygulama prosedürünü destekler. Bunlar,

{anahtarifadesi : değerifadesi for anahtar, değer in iterable}
{anahtarifadesi : değerifadesi for anahtar, değer in iterable if koşul}

şeklindedir. Bu yöntemlerden ilkinin açıklanmasına tanımın sonundan başlayalım: for anahtar, değer in iterable... Burada iterable, oluşturulmuş olan, sözlük tanım koleksiyonudur. Bu koleksiyon, iki döngü değişkeni (anahtar, değer) ile tarandığına göre, en az iki boyutlu olması gerekir. koleksiyonun yapısı,

şeklindedir. Her iterasyonda, elemanlar hedeflenirse,

olacaktır. Eğer, elemanlarından anahtar:değer çiftleri oluşturulabiliyorsa, bu veri koleksiyonu, sözlük yapmaya uygundur. Sözlük yapabilmek için, en az bir anahtar ve bir  değere gereksinme duyululur. Oysa, veri koleksiyonunda bu yapılanma, açık bir şekilde kendini göstermektedir. Veri koleksiyonunun her elemanı, iki elemanlı topluluklardan oluşmaktadır.  Her bir elemanın ilk iç elemanı anahtar, ikinci iç elemanı da değer olarak tanımlanırsa, sözlük yapılanması gerçekleşmiş olacaktır. Veri koleksiyonun her bir elemanı, oluşacak sözlüğün anahtar:değer çiftlerininden birini tanımlayacaktır. Her bir veri koleksiyonu elemanı için, oluşacak sözlüğün değer çiftlerinden birisinin anahtar değerini eleman[0], değerini de eleman[1] şeklinde tanımlarsak olay çözümlenir. Sözlük yapılanması,

Topluluk verilerine erişimi incelerken, bir topluluk homojen ve elemanları iki elemanlı topluluklardan oluşuyorsa, i, j şeklinde iki döngü değişkenli iterasyonlarla, elemanların her iki iç elemanına erişmek olanağı olduğunu görmüştük bu yöntemi, yukarıdaki örnekteki xy topluluğuna uygularsak, x ve y birer iterasyon değişkeni olarak,

Görüldüğü gibi, çok kolay ve çok kısa bir tanımlama ile örnek olara iki elemanlı bir sözcüğü, iki elemanlı ve iki düzeyli bir koleksiyondan oluşturduk. Bu koleksiyon binlerce elemanlı olabilir ve binlerce elemanlı tek anahtarlı bir sözlük oluşturulabilirdi.

Çoklu anahtar değerli sözlüklerde, her anahtar kombinasyonu için bir değer atanabilir. Olayın çekici tarafı, anahatar kombinasyonlarının farklı olabilmesi ve bir anahtar sabit kalarak (pivot) diğer anahtarların değişebilmesidir. Örnek olaka üç anahtarlı bir sözcükle, her şehrin, her ilçesinin, her mahallesindeki nufus değerlerini kaydetmek isteyelim. Kayıtlar istenildiği kadar gelişigüzel olabilir. Okunurken pivot olarak şehir anahtarını alırsak, ikinci pivot olarak ilçe anahtarı olacaktır. Bu iki pivot sabit kalaraki beklirli bir şehrin (ilk pivot), belirli bir ilçesinin (kinci pivot) tüm mahallelerindeki nüfus sayısı (değişen üçüncü anahtar) saptamak olanğı bulunabilir. Tüm değişebilecek üçüncü anahtar değerleri sona erince, yani, belirli bir ilin, belirli bir ilçesinin tüm mahalleleri tükenince, ikinci pivota yeni bir değer verilebilir, yanı il aynı kalır ama ilçe değişir, bu kez değişen ikinci pivot için tüm mahallaer taranır. En sonunda, belirli bir il için tüm ilçeler (ikinci pivot değerleri) tükenince, başka bir ile geçilir (ilk pivot değiştirilir). Yeni il için de bir öncesinin işlemleri aynen tekrarlanır. Sonunda il seçenekleri de tamamlanınca tüm sözlük değerlerine erişim tamamlanmış olur. Burdan çoklu anahtarlı sözlüklerin ne kadar büyük potansiyelleri olduğu açıkça görülebilir.

Eğer iki anahtar, bir değer, yani (a, b) : c isteminde bir sözlük oluşturmak istenirse, uygun veri yapısından (data structure) yola çıkılmalıdır. Örnek,

Görüldüğü gibi, rapor sözlüğü başarı ile ve çok pratik bir yöntemle oluşturuldu. Şimdi yöntemi analiz edelim. Veri yapısı ile başlayalım. Burada veri yapısı iki düzeylidir. İlk düzey eleman düzeyidir ve buna aşağıdaki gibi erişilebilir.

Bu sonuçlar doğal olarak, sözlük oluşturmaya yönelik değil, veri yapısı üzerine bilgi edinmeye yöneliktir. Burada, veri yapısının elemanlarını görebiliyoruz. Herşeyden önce verilerin tekdüzey (monoton) olduğu ve eleman yapılarının birbirlerinin aynısı olduğu görülüyor. Sözlük oluşturmada bu olmazsa olmaz bir koşuldur. Böylece sözlük oluşturmaya esas veri yapısının uyması gereken ikinci koşulu açıklayabiliriz.

Dicitionary comprehensions yöntemi ile sözlük oluşturmaya yönelik bir koleksiyonda eleman yapıları birbirbirlerinin aynı olmalıdır (şekil koşulu).

Örneğimizdeki veri koleksiyonu bu kriteryumu sağlayabildiğine göre, şimdi her elemanın iç yapılarını inceleyelim. Her eleman, iki iç elemandan oluşuyor. Elemanlardan birisi iki elemanlı bir topluluk, ki bu anahtar oluyor, diğeri de tek bir sayısal değer ki bu da değer oluyor. Buradan, sözlük oluşturacak veri yapısı için, olmazsa olmaz ikinci kuralı algılıyoruz:

Dicitionary comprehensions yöntemi ile sözlük oluşturmaya yönelik bir koleksiyonda, koleksiyonun her elemanı, oluşturulacak sözlüğün anahtar:değer çiftini tanımlayacak bilgiye sahip olmalıdır.

Bu bilgi, yukarıdaki uygulamadaki veri yapısında olduğu gibi, veri yapısının içinde olabilir. Veya biraz sonra görülecek bir literatür uygulaması gibi, değer, anahtarın argümanı olduğu bir fonksiyonun geri dönüş değeri olabilir ama, her koşulda, veri yapısının her elemanının oluşacak sözlüğün bir anahtar : değer çiftini tanımlayacak bilgiyi içermesi gerekli olacaktır. Şimdi bu kriteryumu sağlayan, yukarıdaki veri yapısı ile bir dictionary comprehension organize edelim:

Örneklerde de görülebildiği gibi herşey veri yapısına bağlıdır. Şimdi farklı bir veri yapısı ile aynı sözlüğü oluşturmaya çalışalım :

Veri yapısı farklı olmasına karşın, bilinçli bir veri kullanımı ile kolaylıkla aynı sözlüğü oluşturabiliyoruz. Veri yapısı faklı olmasına karşın, tekdüze (monoton) ve veri yapısının her elementinin, bir sözlüğün anahtar: değer çiftlerinin tanımlanması için yeterli olduğu görülüyor.

Aşağıdaki literatür uygulamasında, veri yapısının her elementi, sözlüğün anahtar : değer çiftinin değer kısmının tanımı için, anahtar değerinin argüman olarak kullanıldığı bir fonksiyonun geri dönüş değerinden yararlanıyor.

Aşağıdaki program, koşullu bir dictionary comprehension uygulamasıdır. Bu program, bir klasördeki de bit sayısı 10000 nin altında olan dosyaların adlarını ve bit sayılarını bir sözlükte toplamaktadır.

Bu program, bir klasördeki bit sayısı 10000 den az olan dosyaların adlarını ve bit sayılarını bir sözlükte toplar. (Programming in Python 3 sec.Ed. Mark Summerfield)

Bu yöntemler, tek boyutlu sözlüklerde daha kolaylıkla uygulanabilir. Örnek:

Bir koşul olması durumunda,

3.3.2 - Sözlük Tipi Verilerin Elemanlarına Erişim

Sözlükler belirli bir sıra düzeni ile oluşturulmadıklarından ve indis tanımı olmadığından, elemanlarına sadece anahtar değerleri ile erişim sağlanabilir.

Anahtar değerleri tek ise,

Anahtar değerleri birden çok ise,

Sözlüklerin elemanlarına daha çok iteratif yolla erişilebilir. Bunları, sözlüklere uygulanan öntanımlı metotlar konusunda daha yakından inceleyeceğiz.

3.3.2 - Sözlük Tipi Verilere Uygulanabilen Metotlar

Sözlükler, belirli anahtar:değer topluluklarından, sıralanma olmadan oluşturulmuş koleksiyonlardır. Bu koleksiyonların anahtar değerleri, indis görevini yapar. Sözlüklerde, değer anahtarları veya başka türlü bir söylem ile değer indisleri, sözlük içinde gelişigüzel dağılmışlardır. Bir kez listelenen bir sözlüğün anahtar:değer çiftleri, bir kez daha bir daha listelendiğinde aynı sırada olmayabilir.

Sözlüklerin değer içeriklerine en basit olarak anahtarları aracılığı ile erişilir. Bu erişim, bir topluluk elemanlarına indisleri ile erişmek ile aynıdır. Örnek:

Görüldüğü gibi, sözlük elemanlarına aynı JavaScript ilişkisel dizileri gibi, anahtar değerleri ile erişim sağlanıyor. Tümsözlük içeriğini görüntülemek için, print( <sözlük adı>) yazılması yeterlidir. Örnek

Görüntülenen sözlük içeriğinin, anahtarlarına göre belirli bir sıra düzeni gözetilmediğine dikkat edelim.

Sözlük anahtarları sayısal olursa, elemanlarına erişim, herhangibir koleksiyonun elemanlarına erişimden farksız olur. Örnek :

3.3.3 - Sözlük Tipi Verilere Uygulanabilen Metotlar

Sözlükler, öntanımlı len() metodunu destekler. Örnek:

Sözlük tipi metotlara uygulanan item () metodu, sözlüğün tüm elemanlarını bir topluluk içinde toplar ve bu topluluğu görüntüler. Örnekler:

Sözlüklere uygulanan items() metodu, anahtar değeri tekli olsun, çoklu olsun, sözlükteki tüm elemanları bir topluluk içinde bir liste olarak geri döndürüyor. Bu topluluğun tek elemanı, sözlüğün tüm anahtar: değer verilerini eleman olarak içeren bir listedir. Bu listenin elemanlarına erişim olanağı yoktur. Örnek:

Sözlüklere uygulanan items() metodunun geri döndürdüğü koleksiyonun elemanlarına indisleri ile erişim sağlanamasının nedeni, bu koleksiyonun,"görüntü (view)" olarak adlandırılan bir tipte olmasıdır. Görüntü tipleri sadece sonucun görüntülenmesi için oluşturulurlar. Bu tipi kolaeksiyonlar küme (set) tipindedir ve kümelere uyulanan metotlar ugulanarak elemanlarına erişilebilirler. BU yöntemler belirli değerlerin belirli bir sözlükte olup olmadığı sorgulanabilir. Bu metotları, kümeleri incelediğimizde, görüntü kümelerine de uygulayarak sonuçları alabileceğiz.

Buna rağmen,  items() metodunun geri döndürdüğü koleksiyonfor in döngüleri ile iterasyon yapılmasına uygundur ve bu yöntemle sözlük elemanlarına erişilebilir. Örnekler:

Sözlük anahtarlarının görüntülenmesi için keys() metodu uygulanabilir. Örnek:

Sonuç, sözlüğün tüm anahtarlarının görüntüsünü içeren bir görüntü kümesidir. Bu kümenin erişim metotlarını, kümeler ile birlikte inceleyeceğiz. Buna rağmen bu koleksiyonfor in döngüleri ile taranmaya uygundur. Örnek:

Öntanımlı del metodu, bellekteki bir veriyi bellekten kaldırır. Örnekler:

Sözlüklere uygulanan len () metodu, sözcük uzunluğunu döndürür. Örnek:

Öntanımlı fromkeys() metodu, hash edilebilen bir koleksiyondan yani float, frozenset, int, str, and hash edilebilen toplulukların elemanlarını anahtar olarak kullanarak, sözlükler oluşturan, son derece yararlı bir metottur. Kullanılışı,

sözlük.fromkeys(s ,v)
    

şeklindedir. Burada,