Sözlükler

Giriş

Webster's Dictionary

Önceki bölümde listelerle epeyce haşır neşir olduk. Online Python eğitimimizin bu bölümünde, sözlüklere ve sözlüklerin operatörleri ile yöntemlerine göz atacağız. Listeler ve sözlükler içermeyen Python programları veya betikleri hayal etmek neredeyse imkansızdır. Sözlükler ve onların yarattığı uygulamalar Python’u bu kadar etkili ve üstün yapan kısımlardır. Listeler gibi sözlükler de çalışma zamanı içinde istenildiği gibi kolayca değiştirilebilir, kesilebilir ve geliştirilebilir. Kopya üretmeye gerek olmaksızın, büyüyüp küçülürler. Sözlükler listeler içine alınabilir veya bunun tam tersi de olabilir.

Peki listeler ile sözlükler arasındaki fark nedir? Bir liste sıralı nesnelerden oluşur, ancak sözlükler sıralı değildir. Temel fark şudur ki, sözlüklere erişim anahtar değerlerle olur ve konuma dayalı erişim yoktur.

Daha teorik olmak gerekirse, sözlükler soyut bir veri türünün Python’daki karşılığıdır, bilgisayar biliminde bunlara ilişkisel diziler diyoruz. İlişkisel diziler sözlüklerde olduğu gibi anahtar-değer çiftleri olarak yer alır, her olası anahtar değer koleksiyonda en fazla bir kere bulunur. Sözlükteki herhangi bir anahtar bir değerle ilişkilendirilir (veya bir değere işaret eder). Bir sözlüğün değerleri herhangi bir Python veri türü olabilir. Dolayısıyla sözlüklerin sıralanmamış anahtar-değer çiftleri olduğunu söyleyebiliriz. Sözlükler anahtarlı tablo olarak Python’da yer alır ve bu yüzden Perl programlama dilinde bunlar “sağlama” olarak bilinir.

Sözlükler karakter dizileri, demetler ve listeler gibi sıralı veri türlerinin sıra işlemlerini desteklemez. Sözlükler gömülü eşleme türüne aittir, ancak şu ana kadar bu türden yalnızca tek bir örnek olduğunu söylemeliyiz!

Bu bölümün sonunda, bir sözlüğün nasıl listeye çevrileceğini anlatacağız, listeler (anahtar,değer) demetleri veya iki liste olabilir, bu listenin birinde anahtarlar, diğerinde değerler yer alır. Bu dönüşüm diğer tarafa da yapılabilir.

Sözlüklere Örnekler

İlk örneğimiz ABD ve Kanada’da yer alan şehirlerin adları ve nüfuslarını içeren bir sözlük olacak. Bu değerleri “Kuzey Amerikan şehirlerinin nüfuslarını içeren liste” başlığı altında Wikipedia’dan aldık (https://en.wikipedia.org/wiki/List_of_North_American_cities_by_population) Bu şehirlerden birinin nüfusunu öğrenmek istersek, yapmamız gereken şehrin adını isim (indeks) olarak kullanmak olacak:

In [1]:
şehir_nüfusu = {"New York City":8550405, "Los Angeles":3971883, "Toronto":2731571, "Chicago":2720546, "Houston":2296224, "Montreal":1704694, "Calgary":1239220, "Vancouver":631486, "Boston":667137}
şehir_nüfusu["New York City"]
Out[1]:
8550405
In [2]:
şehir_nüfusu ["Toronto"]
Out[2]:
2731571
In [3]:
şehir_nüfusu ["Boston"]
Out[3]:
667137

Sözlükte olmayan bir şehri yani bir anahtarı kullanırsak ne olur? Bir KeyError meydana gelir:

In [4]:
şehir_nüfusu ["Detroit"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-b762123aaae9> in <module>
----> 1 şehir_nüfusu ["Detroit"]

KeyError: 'Detroit'

Sözlüğümüzü tanımlarken bir sıralama olduğu hissine kapılabilirsiniz, örneğin birincisi “New York City”, ikincisi “Los Angeles” vs gibi düşünebilirsiniz. Ancak sözlüklerde sıralama yoktur ve buna karşı dikkatli olmalısınız. Bu yüzden şehir sözlüğünün çıktısı “orijinal sırayı” yansıtmaz:

In [7]:
şehir_nüfusu 
Out[7]:
{'New York City': 8550405,
 'Los Angeles': 3971883,
 'Toronto': 2731571,
 'Chicago': 2720546,
 'Houston': 2296224,
 'Montreal': 1704694,
 'Calgary': 1239220,
 'Vancouver': 631486,
 'Boston': 667137}

Dolayısıyla sözlüğe bir listede olduğu gibi numara verip bir öğeye ulaşmak mümkün değildir:

In [6]:
city_population[0]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-6-a4816f909f86> in <module>
----> 1 city_population[0]

KeyError: 0

Var olan bir sözlüğe başka bir veri eklemek çok kolaydır:

In [8]:
city_population["Halifax"] = 390096
city_population
Out[8]:
{'New York City': 8550405,
 'Los Angeles': 3971883,
 'Toronto': 2731571,
 'Chicago': 2720546,
 'Houston': 2296224,
 'Montreal': 1704694,
 'Calgary': 1239220,
 'Vancouver': 631486,
 'Boston': 667137,
 'Halifax': 390096}

Bu sebeple boş bir sözlük oluşturup arttıra arttıra gitmek mümkündür. Şimdiye dek boş bir sözlüğü nasıl oluşturacağınıza değinmedik. Bunu boş bir süslü tırnak çifti ile yapabilirsiniz. Aşağıdaki kod ile şehir isimli boş bir sözlük oluşturabilirsiniz:

In [9]:
şehir = {}
şehir
Out[9]:
{}

İlk örneğimiz olan şehir ve nüfus sözlüğüne bakınca, sözlüklerdeki değerlerin farklı olması gerektiği izlenimine kapılabilirsiniz ki bu yanlıştır. Değerler aynı da olabilir, aşağıdaki örneği inceleyiniz: Python’un 'babası' “Monty Python”un hürmetine, şimdi bazı özel yiyecek sözlükleri oluşturacağız. Python “jambon”, “yumurta” ve “spam” olmadan olur mu?

Not: SPAM 2. Dünya Savaşı'ndan sonra birçok ülkede oldukça popüler olmuş bir konserve et markasıdır. SPAM aslında Spiced - Ham'in (baharatlı jambon) kısaltmasıdır. Monthy Python's Flying Circus isimli komedi dizisinde 25. bölümdeki SPAM isimli skeç, SPAM'in müşteriler istese de istemese de neredeyse her yemeğin içinde olduğu bir restoranda Vikinglerin rahatsız edici bir şekilde tekrar tekrar "Spam" kelimesini tekrarlayarak şarkı haline getirişini konu alır. Spam'in bugünkü anlamının kesinlikle bu skeçle bir ilgisi vardır. Şimdi yiyecek sözlüğümüze geri dönelim:

In [10]:
yiyecek = {"jambon" : "evet", "yumurta" : "evet", "spam" : "hayır" }
yiyecek
Out[10]:
{'jambon': 'evet', 'yumurta': 'evet', 'spam': 'hayır'}
In [11]:
yiyecek["spam"] = "evet"
yiyecek
Out[11]:
{'jambon': 'evet', 'yumurta': 'evet', 'spam': 'evet'}

Bir sonraki örneğimiz İngilizce – Almanca sözlük olacak:

In [13]:
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
print(en_de)
print(en_de["red"])
{'red': 'rot', 'green': 'grün', 'blue': 'blau', 'yellow': 'gelb'}
rot

Başka bir dil sözlüğü oluşturmak istesek nasıl olur? Örneğin Almanca-Fransızca gibi?

In [14]:
de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}

İngilizceden Fransızcaya bir kelimeyi tercüme etmek istesek bu mümkündür, elimizde İngilizce-Fransızca sözlüğü olmasa bile bunu yapabiliriz. de_fr[en_de[“red”]] yazarak “kırmızı” kelimesini “rouge” kelimesine dönüştürebiliriz.

In [5]:
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
print(en_de)
{'red': 'rot', 'green': 'grün', 'blue': 'blau', 'yellow': 'gelb'}
In [6]:
print(en_de["red"])
rot
In [7]:
de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}
print("The French word for red is: " + de_fr[en_de["red"]])
The French word for red is: rouge

Bir sözlükte değer olarak keyfi türler kullanabiliriz, ancak anahtarlar için bir sınırlama vardır. Sadece değişebilir olmayan veri türleri anahtar olarak kullanılabilir, yani listeler veya sözlükler kullanılamaz: Değiştirilebilir bir veri türünü anahtar olarak kullanırsanız bir hata mesajı alırsınız:

In [17]:
dic = { [1,2,3]:"abc"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-af2a40fe8efa> in <module>
----> 1 dic = { [1,2,3]:"abc"}

TypeError: unhashable type: 'list'

Anahtar olarak demet kullanımına izin verilir, aşağıdaki örnekleri inceleyiniz:

In [18]:
dic = { (1,2,3):"abc", 3.1415:"abc"}
dic
Out[18]:
{(1, 2, 3): 'abc', 3.1415: 'abc'}

Dil sözlükleri ile olan örneklerimizi biraz genişletelim. Sözlüğün sözlüğünü yapacağız:

In [19]:
en_de = {"red" : "rot", "green" : "grün", "blue" : "blau", "yellow":"gelb"}
de_fr = {"rot" : "rouge", "grün" : "vert", "blau" : "bleu", "gelb":"jaune"}

dictionaries = {"en_de" : en_de, "de_fr" : de_fr }
print(dictionaries["de_fr"]["blau"])
bleu

Sözlüklerde Operatörler

Operatör Açıklama
len(d) Saklanan girdilerin sayısını döndürür, yani (anahtar, değer) çiftlerinin sayısını verir.
del d[k] k anahtarını değeri ile beraber siler
k in d k anahtarı d sözlüğünde var ise True döndürür
k not in d k anahtarı d sözlüğünde yok ise True döndürür.

Örnekler: Aşağıdaki sözlük latin karakterleri morse koduna çeviren eşleştirmeleri içeriyor.

In [ ]:
morse = {
"A" : ".-", 
"B" : "-...", 
"C" : "-.-.", 
"D" : "-..", 
"E" : ".", 
"F" : "..-.", 
"G" : "--.", 
"H" : "....", 
"I" : "..", 
"J" : ".---", 
"K" : "-.-", 
"L" : ".-..", 
"M" : "--", 
"N" : "-.", 
"O" : "---", 
"P" : ".--.", 
"Q" : "--.-", 
"R" : ".-.", 
"S" : "...", 
"T" : "-", 
"U" : "..-", 
"V" : "...-", 
"W" : ".--", 
"X" : "-..-", 
"Y" : "-.--", 
"Z" : "--..", 
"0" : "-----", 
"1" : ".----", 
"2" : "..---", 
"3" : "...--", 
"4" : "....-", 
"5" : ".....", 
"6" : "-....", 
"7" : "--...", 
"8" : "---..", 
"9" : "----.", 
"." : ".-.-.-", 
"," : "--..--"
}

Bu sözlüğü morsecode.py olarak kaydedersiniz, aşağıdaki örnekleri kolayca takip edebilirsiniz. Öncelikle bu sözlüğü içeri aktarmanız gerekiyor:

In [21]:
from morsecode import morse

len fonksiyonunu çağırarak bu sözlükte kaç karakter saklı olduğunu öğrenebilirsiniz:

In [22]:
len(morse)
Out[22]:
38

Sözlükte yalnızca büyük harfler var, dolayısıyla “a” False döndürür, örneğin:

In [23]:
"a" in morse
Out[23]:
False
In [24]:
"A" in morse
Out[24]:
True
In [25]:
"a" not in morse
Out[25]:
True

pop() ve popitem()

pop

Listeler yığın olarak kullanılabilir ve pop() operatörü yığından bir element çıkarmak için kullanılır. Ancak sözlükler için bir pop() yönteminin var olması akla yakın gelmiyor.Nihayetinde bir sözlük (dict) sıralı bir veri türü değil, yani sıralama ve indeksleme yok. Bu sebeple sözlüklerde pop() farklı tanımlanıyor. Anahtarlar ve değerler keyfi bir sırada tutuluyor, bu sıra rasgele değil, ancak tutma biçimine bağlı. D bir sözlük ise, D.pop(k) D sözlüğünden k anahtarını değeri ile beraber siler ve karşılık gelen değeri D[k] dönüş değeri olarak döndürür. Bir anahtar bulunamazsa KeyError hatası oluşur:

In [27]:
en_de = {"Austria":"Vienna", "Switzerland":"Bern", "Germany":"Berlin", "Netherlands":"Amsterdam"}
başkentler = {"Austria":"Vienna", "Germany":"Berlin", "Netherlands":"Amsterdam"}
başkent = başkentler.pop("Austria")
print(başkent)
Vienna
In [28]:
print(başkentler)
{'Germany': 'Berlin', 'Netherlands': 'Amsterdam'}
In [29]:
başkent = başkentler.pop("Switzerland")
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-29-3dbca80ef718> in <module>
----> 1 başkent = başkentler.pop("Switzerland")

KeyError: 'Switzerland'

Önceki örnekte İsviçre’nin başkentini bulmaya çalışırsak bir KeyError hatası ortaya çıkıyor. Bu hataları önlemek için, zekice bir yol var. pop() yönteminin isteğe bağlı ikinci bir parametresi var, bu da varsayılan bir değer olarak kullanılabiliyor:

In [30]:
başkent = başkentler.pop("Switzerland", "Bern")
print(başkent)
Bern
In [31]:
başkent = başkentler.pop("France", "Paris")
print(başkent)
Paris
In [32]:
başkent = başkentler.pop("Germany", "München")
print(başkent)
Berlin

popitem

Popitem() dict’in bir yöntemidir ve hiçbir parametre almaz, keyfi olarak bir (anahtar, değer) çiftini ikili bir demet olarak çıkararak döndürür. Boş bir sözlükte popitem() uygulanırsa bir KeyError hatası oluşur.

In [33]:
başkentler = {"Springfield":"Illinois", "Augusta":"Maine", "Boston": "Massachusetts", "Lansing":"Michigan", "Albany":"New York", "Olympia":"Washington", "Toronto":"Ontario"}
(şehir, eyalet) = başkentler.popitem()
(şehir, eyalet)
Out[33]:
('Toronto', 'Ontario')
In [34]:
print(başkentler.popitem())
('Olympia', 'Washington')
In [35]:
print(başkentler.popitem())
('Albany', 'New York')
In [36]:
print(başkentler.popitem())
('Lansing', 'Michigan')
In [37]:
print(başkentler.popitem())
('Boston', 'Massachusetts')

Var Olmayan Anahtarlara Erişim

Eğer var olmayan bir anahtara erişmeye çalışırsanız, bir hata mesajı alırsınız:

In [38]:
konumlar = {"Toronto" : "Ontario", "Vancouver":"British Columbia"}
konumlar["Ottawa"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-38-6df41131bb79> in <module>
      1 konumlar = {"Toronto" : "Ontario", "Vancouver":"British Columbia"}
----> 2 konumlar["Ottawa"]

KeyError: 'Ottawa'

Bu hatayı önlemek için “in” operatörünü kullanabilirsiniz:

In [40]:
konum = "Ottawa"

if konum in konumlar: 
    print(konumlar[konum])
else:
    print(konum + " konumlarda değil")
Ottawa konumlarda değil

Anahtar yoluyla değerlere erişmenin bir başka yolu da get() yöntemidir: Get() indeks yoksa bir hata oluşturmaz. Bu durumda None döndürür. Bir indeks mevcut değilse, döndürülecek varsayılan bir değer belirtmek de mümkündür:

In [41]:
proj_dil = {"proj1":"Python", "proj2":"Perl", "proj3":"Java"}
proj_dil["proj1"]
Out[41]:
'Python'
In [42]:
proj_dil["proj4"]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-42-4079afb9df54> in <module>
----> 1 proj_dil["proj4"]

KeyError: 'proj4'
In [43]:
proj_dil.get("proj2")
Out[43]:
'Perl'
In [44]:
proj_dil.get("proj4")
print(proj_dil.get("proj4"))
None
In [45]:
# varsayılan bir değer atama:
proj_dil.get("proj4", "Python")
Out[45]:
'Python'

Önemli Yöntemler

Bir sözlük, copy() yöntemi ile kopyalanabilir:

Copy()

In [8]:
kelimeler = {'house': 'Haus', 'cat': 'Katze'}
w = kelimeler.copy()
kelimeler["cat"]="chat"
print(w)
{'house': 'Haus', 'cat': 'Katze'}
In [9]:
print(kelimeler)
{'house': 'Haus', 'cat': 'chat'}

Bu kopya yüzeysel olup derin bir kopya değildir. Bir değer liste gibi karmaşık bir veri türüyse, bu nesne üzerinde yapılacak yerinde değişiklikler kopyada da etkisini gösterecektir:

In [49]:
# -*- coding: utf-8 -*-

eğitimler = { "ders1":{"başlık":"Yeni Başlayanlar için Python Eğitimi", 
                         "yer":"Frankfurt", 
                         "eğitmen":"Steve G. Snake"},
              "ders2":{"başlık":"Orta Düzey Python Eğitimi",
                         "yer":"Berlin",
                         "eğitmen":"Ella M. Charming"},
              "ders3":{"başlık":"Python Metin İşleme Dersi",
                         "yer":"Münih",
                         "eğitmen":"Monica A. Snowdon"}
              }

eğitimler2 = eğitimler.copy()

eğitimler["ders2"]["başlık"] = "Yeni Başlayanlar için Perl Eğitimi"
print(eğitimler2)
{'ders1': {'başlık': 'Yeni Başlayanlar için Python Eğitimi', 'yer': 'Frankfurt', 'eğitmen': 'Steve G. Snake'}, 'ders2': {'başlık': 'Yeni Başlayanlar için Perl Eğitimi', 'yer': 'Berlin', 'eğitmen': 'Ella M. Charming'}, 'ders3': {'başlık': 'Python Metin İşleme Dersi', 'yer': 'Münih', 'eğitmen': 'Monica A. Snowdon'}}

Çıktıyı kontrol ettiğimizde ders2’nin yalnızca ders sözlüğünde değil, dersler2’de de değiştiğini göreceksiniz.

Bir anahtara yeni bir değer yani yeni bir nesne atarsanız, herşey beklediğiniz gibi gider:

In [55]:
eğitimler = { "ders1":{"konu":"Yeni Başlayanlar için Python Eğitimi", 
                         "yer":"Frankfurt", 
                         "eğitmen":"Steve G. Snake"},
              "ders2":{"konu":"Orta Düzey Python Eğitimi",
                         "yer":"Berlin",
                         "eğitmen":"Ella M. Charming"},
              "ders3":{"konu":"Python Metin İşleme Dersi",
                         "yer":"Münih",
                         "eğitmen":"Monica A. Snowdon"}
              }

eğitimler2 = eğitimler.copy()

eğitimler["ders2"] = {"başlık":"Yeni Başlayanlar için Perl Semineri",
                         "yer":"Ulm",
                         "eğitmen":"James D. Morgan"}
print(eğitimler2["ders2"])
{'konu': 'Orta Düzey Python Eğitimi', 'yer': 'Berlin', 'eğitmen': 'Ella M. Charming'}

Bu davranışın nedenini anlamak isterseniz, “Yüzeysel ve Derin Kopyalama” bölümümüzü okumanızı öneririz.

Clear()

Clear() yöntemi ile bir sözlüğün içi temizlenebilir. Sözlük silinmez, ama boş bir sözlüğe döner:

In [56]:
w.clear()
print(w)
{}

Update(): Sözlüklerin Birleştirilmesi

Listelerle yaptığımız gibi, sözlükleri birleştirmeye ne dersiniz? Sözlüklerde de benzer şekilde update yöntemi var. update() bir sözlüğün anahtar ve değerlerini diğeriyle birleştirir:

In [57]:
bilgi = {"Frank": {"Perl"}, "Monica":{"C","C++"}}
bilgi2 = {"Guido":{"Python"}, "Frank":{"Perl", "Python"}}
bilgi.update(bilgi2)
bilgi
Out[57]:
{'Frank': {'Perl', 'Python'}, 'Monica': {'C', 'C++'}, 'Guido': {'Python'}}

Sözlüklerde Yineleme

Bir sözlüğün anahtarlarında yineleme yapmak için hiçbir yönteme ihtiyaç yoktur:

In [58]:
d = {"a":123, "b":34, "c":304, "d":99}
for key in d:
     print(key) 
a
b
c
d

Ancak keys() yöntemini de kullanmak mümkündür, yine de elde edilecek sonuç aynıdır:

In [59]:
for key in d.keys():
     print(key) 
a
b
c
d

Values() yöntemi değerler üzerinden doğrudan tekrarlama yapmak için rahat bir yoldur:

In [60]:
for value in d.values():
    print(value)
123
34
304
99

Yukarıdaki döngü aşağıdaki ile mantıksal olarak eşdeğerdir:

In [61]:
for key in d:
        print(d[key])
123
34
304
99

Dikkat ettiyseniz “mantıksal” dedik, çünkü ikinci yöntem daha az etkindir! İki alternatif için kullanılan zamanı ipython’daki timeit ile ölçmeyi biliyorsanız neden böyle dediğimizi anlayacaksınız:

In [62]:
%%timeit  d = {"a":123, "b":34, "c":304, "d":99}
for key in d.keys():
    x = d[key]
539 ns ± 46.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [63]:
%%timeit  d = {"a":123, "b":34, "c":304, "d":99}
for value in d.values():
    x = value
396 ns ± 25 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Listeler ve Sözlükler Arasındaki Bağlantılar

Zipper on a Ball

Python ile bir süre uğraştıysanız, listeleri sözlüklere dönüştürmek veya tam tersini yapmak için neredeyse kaçınılmaz bir durum. Bunu yapacak bir fonksiyon yazmak çok zor değil. Python size bu imkânları sağlamasaydı Python olmazdı.

Şöyle bir sözlüğümüz olsun:

In [64]:
D = {"list":"Liste", "dictionary":"Wörterbuch", "function":"Funktion"} 

Bunu ikili demetler içeren bir listeye çevirebiliriz:

In [65]:
L = [("list","Liste"), ("dictionary","Wörterbuch"), ("function","Funktion")] 

L listesi ve D sözlüğü aynı içeriğe sahip, yani bilgi içeriği açısından aynı, ya da kısa ve öz bir şekilde belirtmek gerekirse “L ve D’nin entropisi aynıdır”. Elbette, L listesinden bilgiyi çekmek D sözlüğüne göre daha zordur. L’deki belli bir anahtarı bulmak için, listenin içindeki demetlere bakmanız ve aradığınız anahtar ile demetlerin ilk bileşenlerini karşılaştırmanız gerekir. Bu arama kesin olarak ve son derece etkili bir şekilde, sözlükler için uygulanmaktadır.

Sözlüklerden Listelere

Items(), keys() ve values() yöntemlerini kullanarak sözlüklerden liste oluşturmak mümkündür. Adından da anlayacağımız gibi keys() yöntemi ile sadece sözlüğün anahtarlarını içeren bir liste oluşur. Values() ile sözlüğün değerlerini içeren bir liste oluşur. Items() ile (anahtar, değer) içeren ikili demetleri içeren bir liste elde edilir:

In [11]:
w = {"house": "Haus", "cat": "", "red": "rot"}
items_view = w.items()
items = list(items_view)
items
Out[11]:
[('house', 'Haus'), ('cat', ''), ('red', 'rot')]
In [67]:
keys_view = w.keys()
keys = list(keys_view)
keys
Out[67]:
['house', 'cat', 'red']
In [68]:
values_view = w.values()
values = list(values_view)
values
Out[68]:
['Haus', '', 'rot']
In [69]:
values_view
Out[69]:
dict_values(['Haus', '', 'rot'])
In [70]:
items_view 
Out[70]:
dict_items([('house', 'Haus'), ('cat', ''), ('red', 'rot')])
In [71]:
keys_view
Out[71]:
dict_keys(['house', 'cat', 'red'])

Items() yöntemini bir sözlüğe uyguladığımız zaman, bir liste almayız, Python 2’de durum böyleydi, ancak eleman görünümü diye bilinen bir şey alırız. List fonksiyonunu uygulayarak eleman görünümünü bir listeye dönüştürebiliriz. Bir sözlüğü eleman görünümü veya eleman listesine dönüştürmekle bilgi kaybımız olmaz, yani items() ile oluşturulan görünümden orijinal sözlüğe geçmek mümkündür. İki demetli listede aynı entropi varsa da, yani bilgi içeriği aynıysa da, her iki yaklaşımın etkinliği tamamen farklıdır. Sözlük veri türü bir sözlükteki elemanlara erişmek, onları silmek veya değiştirmek için son derece etkili yöntemler sunar, listelerde ise bu fonksiyonların programcı tarafından oluşturulması gerekir.

Listelerin Sözlüklere Dönüştürülmesi

Şimdi dikkatimizi yemek pişirme sanatına çevirelim. Korkmayın, bu bir Python dersi olmaya devam edecek, bir yemek pişirme dersi olmayacak. Elimizdeki listeler belli şartları sağlıyorsa bu listeleri nasıl sözlüklere çevireceğimizi göstermek istiyoruz. İki listemiz var, birinde yiyecek isimleri, diğerinde de karşılık gelen ülkeler mevcut:

In [13]:
yiyecekler = ["pizza", "sauerkraut", "paella", "hamburger"]
ülkeler = ["Italya", "Almanya", "İspanya", "ABD"]
ülkeye_özel_yineleyici = zip(ülkeler, yiyecekler)
ülkeye_özel_yineleyici
Out[13]:
<zip at 0x168fd0409c8>
In [16]:
ülkeye_özel_spesyaller = list(ülkeye_özel_yineleyici)
print(ülkeye_özel_spesyaller)
[('Italya', 'pizza'), ('Almanya', 'sauerkraut'), ('İspanya', 'paella'), ('ABD', 'hamburger')]

Alternatif olarak iteras, for döngüsü içindeki zip nesnesi kullanabilirsiniz. Bu şekilde, yalnızca değerler üzerinde yineleme yapmak istiyorsak ve bir listeye ihtiyacımız yoksa,daha verimli olabiliriz

In [14]:
for ülke, yiyecekler in zip(ülkeler, yiyecekler):
    print(ülke, yiyecekler)
Italya pizza
Almanya sauerkraut
İspanya paella
ABD hamburger

Şimdi bir sözlük oluşturacağız, burada bir ülkeye özel yiyecek türü ile ülkeyi eşleştireceğiz; lütfen önyargılara başvurduğumuz için bizi bağışlayın. Bu amaçla zip() fonksiyonunu kullanacağız. Zip ismi doğru bir seçimdir, çünkü iki liste bir fermuarın çekilmesi gibi birleşir. Sonuç bir liste yineleyicisidir.

In [17]:
ülkeye_özel_spesyaller_sözlüğüm = dict(ülkeye_özel_spesyaller)
print(ülkeye_özel_spesyaller_sözlüğüm)
{'Italya': 'pizza', 'Almanya': 'sauerkraut', 'İspanya': 'paella', 'ABD': 'hamburger'}

Şimdi ülkeye özel yiyecek çeşitlerimiz bir liste haline geldi – iki üyeli demetlere sahip bir listemiz var, ilk bileşenler anahtar ve ikinci bileşenler de değer olarak görülecek ve dict() ile çalıştırınca otomatik olarak bir sözlüğe çevrilecek.

In [19]:
yiyecekler = ["pizza", "sauerkraut", "paella", "hamburger"]
ülkeler = ["İtalya", "Almanya", "İspanya", "ABD"]
dict(zip(ülkeler, yiyecekler))
Out[19]:
{'İtalya': 'pizza',
 'Almanya': 'sauerkraut',
 'İspanya': 'paella',
 'ABD': 'hamburger'}

Ancak bu çok etkisiz bir yol, çünkü bu listeyi sözlüğe çevirmek için iki öğeli bir demet dizisi oluşturduk. Bunu doğrudan dict(zip()) kullanarak yapmak daha kolaydır:

Zip() fonksiyonu ile ilgili hâlâ bir soru var. İki argüman listesinin birinde diğerine göre daha fazla öğe varsa ne olacak? Bunun cevabı zor değil: Eşleştirilemeyen fazlalık öğeler gözardı edilecektir:

In [78]:
yiyecekler = ["pizza", "sauerkraut", "paella", "hamburger"]
ülkeler = ["İtalya", "Almanya", "İspanya", "ABD"," İsviçre"]
ülkeye_özel_spesyaller = list(zip(ülkeler, yiyecekler))
ülkeye_özel_spesyaller_sözlüğüm = dict(ülkeye_özel_spesyaller)
print(ülkeye_özel_spesyaller_sözlüğüm)
{'İtalya': 'pizza', 'Almanya': 'sauerkraut', 'İspanya': 'paella', 'ABD': 'hamburger'}

Bu yüzden İsviçre’nin ulusal yiyeceğinin ne olduğu sorusunu cevaplayamayacağız.

Herşey Bir Adımda

Normal olarak, bir programlama ifadesi içinde çok fazla adım bulundurmamak tavsiye edilir, gerçi böyle yapınca kod daha etkileyici ve sıkı gibi görünür. Ara adımlarda “konuşan” değişken isimleri kullanmak okunurluğu artırabilir. Yine de önceki sözlük çalışmamızda tek satırda sonuca gitmemiz cazip olabilir:

In [88]:
ülkeye_özel_spesyaller_sözlüğüm = dict(list(zip(["pizza", "sauerkraut", "paella", "hamburger"], ["İtalya", "Almanya", "İspanya", "ABD"," İsviçre"])))
print(ülkeye_özel_spesyaller_sözlüğüm )
{'pizza': 'İtalya', 'sauerkraut': 'Almanya', 'paella': 'İspanya', 'hamburger': 'ABD'}

Diğer taraftan önceki betikteki kod daha okunabilir hale getiriliyor:

In [89]:
yiyecekler = ["pizza", "sauerkraut", "paella", "hamburger"]
ülkeler = ["Italy", "Germany", "Spain", "USA"]
ülkeye_özel_spesyaller_zip = zip(yiyecekler,ülkeler)
print(list(ülkeye_özel_spesyaller_zip))
[('pizza', 'Italy'), ('sauerkraut', 'Germany'), ('paella', 'Spain'), ('hamburger', 'USA')]
In [90]:
ülkeye_özel_spesyaller_liste = list(ülkeye_özel_spesyaller_zip)
ülkeye_özel_spesyaller_sözlük = dict(ülkeye_özel_spesyaller_liste)
print(ülkeye_özel_spesyaller_sözlük)
{}

Tıpkı tek bir adımda yapmış gibi aynı sonucu alıyoruz.

Pusuda Bekleyen Tehlike

Özellikle Python 2.x’ten Python 3.x’e geçenler için şunu söylemeliyiz: zip() bir liste döndürüyordu, şimdi ise bir yineleyici döndürüyor. Yineleyicilerin kullanılmaları ile birlikte tükendiklerini hatırınızda tutmanız gerekir. Aşağıdaki etkileşimli örneği inceleyiniz:

In [83]:
l1 = ["a","b","c"]
l2 = [1,2,3]
c = zip(l1, l2)
for i in c:
     print(i)
('a', 1)
('b', 2)
('c', 3)

Bu etkiyi görmek için liste operatörünü devreye sokacağız:

In [86]:
l1 = ["a","b","c"]
l2 = [1,2,3]
c = zip(l1,l2)
z1 = list(c)
z2 = list(c)
print(z1)
[('a', 1), ('b', 2), ('c', 3)]
In [87]:
print(z2)
[]

Bir alıştırma olarak şu betik üzerinde derin derin düşünün. Sonuç neden boş bir sözlük?

In [91]:
yiyecekler = ["pizza", "sauerkraut", "paella", "hamburger"]
ülkeler = ["İtalya", "Almanya", "İspanya", "ABD"]
ülkeye_özel_spesyaller_zip = zip(yiyecekler,ülkeler)
print(list(ülkeye_özel_spesyaller_zip))
ülkeye_özel_spesyaller_liste = list(ülkeye_özel_spesyaller_zip)
ülkeye_özel_spesyaller_sözlük = dict(ülkeye_özel_spesyaller_liste)
print(ülkeye_özel_spesyaller_sözlük)
[('pizza', 'İtalya'), ('sauerkraut', 'Almanya'), ('paella', 'İspanya'), ('hamburger', 'ABD')]
{}

Dipnot

1 Eğer yineliyecilerin nasıl çalıştığını daha detaylı öğrenmek isterseniz Iterators and Generators chapter bölümümüzü okumanızı tavsiye ederiz.