Sözlükler, kümeler ve koleksiyon seçimi
Listelerde bir değere erişmek için çoğunlukla indeks kullanırız. Oysa bir üründen söz ederken “0. eleman” ya da “2. eleman” demeyiz; adını, fiyatını, stok miktarını söyleriz. Öğrencide de öyle: adı, öğrenci numarası.
Bu hafta iki yeni koleksiyon öğreneceğiz. Sözlük (dictionary, dict) her değeri bir adla tutar; bu ada anahtar denir. "fiyat" anahtarının değeri 12.5 olabilir. Küme (set, set) ise her değeri yalnızca bir kez tutar. Bölümün sonunda da “bu iş için liste mi, sözlük mü, küme mi?” sorusunu cevaplamayı öğreneceğiz.
Bu sayfadaki kod hücreleri kendiliğinden çalışmaz. Her hücrede önce çıktıyı tahmin edin, sonra Run Code düğmesine basın. Kodu değiştirip yeniden çalıştırabilir, Start Over ile ilk hâline döndürebilirsiniz.
Bu bölümün kapsamı
- Anahtar–değer modeliyle okuma ve alan güncelleme
indenetiminin anahtarı aramasıget()ile varsayılan kullanmanın yararı ve bedeli.keys(),.values()ve.items()farkı- Sözlük anahtarının değişmez olma zorunluluğu
- Sözlükle frekans veya sayaç tablosu kurma
- Kümenin benzersizlik ve sıra davranışı, koleksiyon seçimi
collectionsmodülündeki hazır sayaç yapıları- Küme kesişim, birleşim ve fark işlemlerinin ayrıntısı
Bu başlıklar konunun devamıdır. İleride karşınıza çıkar, ama bu derste ezberlemeniz beklenmiyor.
Konsey seçiminin oylarını nasıl sayardınız?
Okulunuzda öğrenci konseyi başkanı seçiliyor. Dört aday var: Ayşe, Burak, Can ve Deniz. Her öğrenci bir kâğıda tek bir ad yazıp sandığa atıyor. Sandık açıldı. Kâğıtlar sırasıyla şöyle:
Ayşe, Burak, Ayşe, Elif, Ayşe, Can
Seçim kurulu sonuçları istiyor. Sayımı yapacak bir program yazılacak. Program yalnız ona yazdığınız adımları bilecek. Sayımın adımlarını 1. bölümdeki sözde kodla, Türkçe ve madde madde yazın. Sonra adımlarınızı dört soruyla deneyin:
- Ayşe üç kâğıtta geçiyor. Adımlarınız her adayın kaç oy aldığını nasıl buluyor? Ayşe ikinci kez gelince ne yapıyorsunuz?
- Bir kâğıtta Elif yazıyor, ama Elif aday değil. Oyu adayın sayısına ekleyen adımınız Elif’e gelince ne yapıyor?
- Kurul “Hiç oy almayan aday var mı, varsa kim?” diye soruyor. Adımlarınız bunu nereden buluyor?
- Kurul “Kaç farklı aday oy aldı?” diye soruyor. Kâğıtları sayarsanız
6bulursunuz. Adımlarınız kaç buluyor?
Python bilmeniz gerekmiyor: “Kâğıttaki adın yanına bir çizgi çekerim” de bir adım. Adımlarınızı bir kenara yazın. Bölümde her birinin Python’da nasıl yazıldığını göreceğiz. Alıştırmalardan önce listenize döneceğiz.
Sözlük: anahtardan değere erişim
Bir ürünün bilgilerini listede şöyle tutabiliriz:
urun = ["Kalem", 12.5, 40]Ama urun[1] yazınca bunun fiyat olduğunu anlamak için listenin hangi sırayla kurulduğunu bilmeniz gerekir.
Sözlükte ise her bilgiye bir ad veririz. Sözlük süslü parantezle yazılır, her alan anahtar: değer biçimindedir. Değere köşeli parantez içinde anahtarı yazarak erişiriz. Hücre ne yazar?
Burada "ad", "fiyat" ve "stok" anahtarlardır.
Anahtar–değer ilişkisi
Sözlükte her anahtar bir değeri gösterir:
"ad" → "Kalem"
"fiyat" → 12.5
"stok" → 40
Bir sözlükte aynı anahtar iki kez bulunamaz. Aşağıdaki hücrede önce var olan "stok" anahtarına, sonra sözlükte olmayan "kategori" anahtarına değer atanıyor. Sözlük en sonda kaç alan tutar, ne yazar?
Var olan bir anahtara yeniden değer atarsanız eski değerin yerine yenisi geçer. Olmayan bir anahtara değer atarsanız sözlüğe yeni bir alan eklenir.
Sözlükte in anahtarı kontrol eder
Sözlükte in kullandığınızda Python yalnızca anahtarlara bakar. Üç satır ne yazar?
"stok" sözlükte bir anahtar olduğu için ilk satır True yazar. "fiyat" diye bir anahtar yok, ikinci satır False yazar. "Kalem" sözlükte durur, ama anahtar olarak değil, "ad" anahtarının değeri olarak. in değerlere bakmadığı için üçüncü satır da False yazar.
Değerlerde aramak istiyorsanız bunu .values() ile açıkça belirtin:
print("Kalem" in urun.values())Anahtara bakan in, bir alanın eksik olup olmadığını denetlemek için kullanışlıdır:
if "stok" in urun:
print("Stok bilgisi var")
else:
print("Stok bilgisi eksik")Tahmin et: sözlük nasıl değişir?
Aşağıdaki kodu çalıştırmadan önce çıktıyı tahmin edin. Üçüncü print() hata verir mi?
ogrenci["puan"] = 82 satırını okuyan herkes puanın değiştiğini anlar. Listede ogrenci[1] = 82 yazsaydık bunu anlamak için listenin sırasını hatırlamak gerekirdi.
Alıştırma: stok değerini güncelleyin
Mağazada 3 defter satıldı. Stoktaki sayıyı 3 azaltın.
Beklenen sonuç 9’dur.
urun["stok"] = urun["stok"] - 3 yazabilirsiniz.
urun = {
"ad": "Defter",
"fiyat": 45,
"stok": 12
}
urun["stok"] = urun["stok"] - 3
print(urun["stok"])Eksik anahtar ve get()
Sözlükte olmayan bir anahtarı okumanın iki yolu var: köşeli parantez ve get() metodu. get() metoduna ikinci argüman olarak bir varsayılan değer de verebiliriz: anahtar yoksa bu değer döner. Aşağıdaki hücrede "stok" anahtarı yok. Hangi satır hata verir, öteki ikisi ne yazar?
İlk satır None yazar: get() anahtarı bulamayınca hata vermez, None döndürür. İkinci satır 0 yazar, çünkü varsayılan değer olarak 0 verdik. Üçüncü satır KeyError: 'stok' hatası verir: köşeli parantez anahtarın sözlükte olmasını bekler.
Alanın eksik olması beklenen bir durumsa get() kullanılabilir. Anahtar mutlaka olmalıysa köşeli parantez, eksik alanı hemen fark etmenizi sağlar.
get("stok", 0) her problemde doğru sonuç vermez. Stok bilgisi girilmemiş bir ürünün stoğu gerçekten 0 mıdır? Bunu problemin kuralı belirler. “Stok bilgisi girilmemiş” ile “stokta ürün kalmamış” farklı durumlardır.
Sözlük üzerinde gezinmek: keys(), values(), items()
Bir sözlükten anahtarları, değerleri ya da ikisini birlikte alabilirsiniz:
| Metot | Ne verir? |
|---|---|
.keys() |
Anahtarları |
.values() |
Değerleri |
.items() |
(anahtar, deger) çiftlerini |
Üç satır ne yazar?
Python sonuçları dict_keys([...]), dict_values([...]) ve dict_items([...]) biçiminde yazar. Köşeli parantezlerin içinde sırasıyla anahtarlar, değerler ve ('ad', 'Kalem') gibi çiftler görünür. Bu sonuçlar liste değildir, ama for ile dolaşılabilir ve list() ile listeye çevrilebilir.
Yalnızca anahtarlar üzerinde dolaşmak için şu iki yazım aynı işi görür:
for anahtar in urun:
print(anahtar)for anahtar in urun.keys():
print(anahtar)Yalnızca değerleri istiyorsak:
for deger in urun.values():
print(deger)Anahtar ve değeri birlikte almak için items() kullanırız. Döngü kaç tur döner, her turda ne yazar?
items() her turda (anahtar, deger) biçiminde iki elemanlı bir demet verir. for anahtar, deger in ... yazınca bu demeti iki değişkene açarız. 9. bölümdeki demet açma budur: demetin elemanları sırayla soldaki değişkenlere atanır.
Sözlükten alan silmek
Bir anahtarı değeriyle birlikte silmek için pop() kullanılır. pop() anahtarı siler ve silinen değeri döndürür. İki satır ne yazar?
Anahtarın olmaması beklenen bir durumsa get()teki gibi bir varsayılan değer verebilirsiniz:
silinen = urun.pop("indirim", None)del urun["stok"] yazarak da anahtar silinebilir, ama anahtar yoksa KeyError verir. Silinen değer de gerekiyorsa pop() daha uygundur.
Hangi değerler sözlük anahtarı olabilir?
Sözlük, anahtarı hızlı bulmak için anahtardan bir sayı (hash değeri) hesaplar. Bu yüzden anahtarın hashlenebilir (hashable), yani hash değeri hesaplanabilen bir değer olması gerekir. Başlangıç için pratik kural şu: anahtar olarak değiştirilemeyen (immutable) değerler kullanın.
Sık kullanılan geçerli anahtarlar:
kayit = {
"ad": "Deniz", # str
101: "aktif", # int
(41, 36): "nokta" # elemanları sayı olan demet
}Aşağıdaki hücre aynı iki sayıyı önce demet, sonra liste olarak anahtar yapmaya çalışıyor. Hangi satır hata verir?
Demetle yapılan atama sorunsuz çalışır. Üçüncü satır TypeError hatası verir, mesajda unhashable type: 'list' sözleri geçer. Liste değiştirilebilir olduğu için hashlenemez ve sözlük anahtarı olamaz. Hata çıktığı için print() satırına hiç gelinmez.
Bu kuralı 9. bölümdeki değiştirilebilir (mutable) ve değiştirilemez (immutable) ayrımıyla birlikte düşünün. Anahtar sonradan değişebilseydi sözlük onu bir daha bulamazdı.
Buradan “değiştirilemeyen her değer iyi bir anahtardır” sonucunu çıkarmayın. Anahtarı öğrenci numarası gibi bir kimlik olarak düşünün: sözlükte durduğu sürece değerini bulmaya yarar. Bu derste str, int ve elemanları sayı ya da metin olan basit demetler yeterlidir.
Sözlük ekleme sırasını korur, küme korumaz
Python 3.7 ve sonrasında sözlük, anahtarları eklendikleri sırayla tutar. Anahtarlar hangi sırayla yazılır?
Sözlük anahtarları alfabetik ya da sayısal olarak sıralamaz, yalnızca ekleme sırasını korur.
Kümelerde ise yazdırma ya da dolaşma sırasına güvenmeyin: aynı küme farklı çalıştırmalarda ya da ortamlarda farklı sırada görünebilir.
Alıştırmada kümenin elemanları beklediğinizden farklı sırada yazıldıysa cevabınız yanlış demek değildir. Kümede önemli olan, bir değerin kümede olup olmadığı ve her değerin bir kez bulunmasıdır. Çıktının belirli bir sırada olması gerekiyorsa sorted(kume) ile sıralayın.
Sayma tablosu oluşturmak
Sözlüğün en çok işe yaradığı yerlerden biri, her değerin kaç kez geçtiğini (frekansını) saymaktır. Sandıktaki oyları saymak da bu iştir.
Bir listedeki şehirlerin kaç kez geçtiğini bulalım. Sözlük en sonda ne yazar?
Bir şehir ilk kez geldiğinde sözlükte henüz yoktur ve get(sehir, 0) 0 verir. Aynı şehir yeniden geldiğinde o ana kadarki sayı alınır ve bir artırılır. Her değerin sayısını tutan bu sözlüğe frekans tablosu denir.
Alıştırma: durumları sayın
Aşağıdaki listede "tamam" ve "bekliyor" değerlerinin kaç kez geçtiğini sözlükte sayın.
Beklenen:
{'tamam': 3, 'bekliyor': 2}
get(durum, 0) o ana kadarki sayıyı, durum ilk kez geliyorsa 0 verir.
durumlar = ["tamam", "bekliyor", "tamam", "tamam", "bekliyor"]
sayilar = {}
for durum in durumlar:
sayilar[durum] = sayilar.get(durum, 0) + 1
print(sayilar)Küme (set): tekrarsız değerler
Bir küme her değeri bir kez tutar. Küme de süslü parantezle yazılır, ama içinde anahtar: değer çiftleri değil, yalnız değerler bulunur. "python" iki kez yazıldı. Hücre kaç eleman yazar?
İki kez yazdığımız "python" kümede bir kez bulunur. Sözlükten farklı olarak kümede elemanların hangi sırayla yazdırılacağı belli değildir.
Bir listeyi set() ile kümeye çevirebilirsiniz. Liste dört elemanlı. Küme kaç elemanlı olur?
Böylece listedeki tekrarlar atılır ve yalnızca benzersiz değerler, yani her biri bir kez geçen değerler kalır.
Kümenin indeksi yoktur; kume[0] yazamazsınız. Sıra sizin için önemliyse liste daha uygun olabilir. Boş küme set() ile oluşturulur, {} ise boş bir sözlüktür.
Kümede üyelik kontrolü
Kümeler, bir değerin içlerinde olup olmadığını sormak (üyelik kontrolü) için çok uygundur. Kümeye eleman add() ile eklenir. Hücre ne yazar?
"personel" kümede olduğu için Rol tanımlı yazılır. add("yonetici") yeni bir eleman ekler ve küme dört elemanlı olur. "ogrenci" zaten kümede olduğu için ikinci add() hiçbir şey değiştirmez. Son satır 4 yazar.
Tahmin et: kaç benzersiz değer var?
Liste altı elemanlı. İki uzunluk ne olur?
İlk uzunluk 6’dır, çünkü liste tekrarları da tutar. Küme her değerden bir tane tutar: A, B, C ve D. İkinci uzunluk 4’tür. Tekrar eden değerler kümeden tamamen silinmez, bir kez kalır.
Alıştırma: tekrar eden ders kodlarını ayıklayın
Aşağıdaki listedeki ders kodlarını, her biri bir kez geçecek biçimde bir kümede toplayın.
Kümede 3 ders kodu kalmalı. Kodların hangi sırayla yazdırıldığı önemli değildir.
set(dersler) listedeki tekrarları atıp bir küme döndürür.
dersler = ["BLP101", "BLP102", "BLP101", "BLP103", "BLP102"]
benzersiz_dersler = set(dersler)
print(benzersiz_dersler)
print(len(benzersiz_dersler))Hangi koleksiyonu seçmeliyim?
Tek bir “en iyi” koleksiyon yoktur. Seçimi, veriyle ne yapmak istediğimiz belirler.
| İhtiyaç | Genellikle uygun yapı |
|---|---|
| Sıralı bir değer dizisi | list |
| Küçük ve değişmemesi beklenen sıralı grup | tuple |
| Anlamlı anahtardan değere erişim | dict |
| Tekrarsız değerler ve üyelik kontrolü | set |
Örnekler:
- Bir öğrencinin haftalık puanları → liste
- Bir koordinat çifti → demet
- Bir ürünün
ad,fiyat,stokalanları → sözlük - Sistemde görülen benzersiz hata kodları → küme
Koleksiyonu verinin “nasıl göründüğüne” göre değil, programın veriye nasıl erişeceğine ve ne yapacağına göre seçin.
Liste ve sözlüğü birlikte kullanmak
Birden fazla ürünü saklamak için her ürünü bir sözlüğe, bütün sözlükleri de bir listeye koyabiliriz. Döngü kaç satır yazar?
Her ürünün sözlüğüne bir kayıt diyebiliriz. Gelecek hafta bu yapıyla çalışacağız: kayıtları filtreleyecek, gruplayacak ve özetleyeceğiz.
Soruya dönelim: oy sayımı Python’da
Bölümün başında konsey seçiminin oy sayımını sözde kodla yazıp dört soruyla denemiştiniz. Kâğıtlar bir liste, sonuç tablosu da her adayın 0 oyla başladığı bir sözlük olsun:
kagitlar = ["Ayşe", "Burak", "Ayşe", "Elif", "Ayşe", "Can"]
oylar = {"Ayşe": 0, "Burak": 0, "Can": 0, "Deniz": 0}Dört sorunun Python’daki karşılıkları şöyle:
| Soru | Sözde kodda | Python’da | Dikkat |
|---|---|---|---|
| Her aday kaç oy aldı? | “Kâğıttaki adın yanına bir çizgi çek” | oylar[oy] = oylar[oy] + 1 |
oylar[oy] = 1 yazılırsa Ayşe her kâğıtta yeniden 1 olur. Sözlük boş başlasaydı oylar.get(oy, 0) + 1 kalıbı gerekirdi, ama o zaman Deniz sözlüğe hiç girmezdi |
| Aday olmayan Elif | “Ad aday listesindeyse say, değilse geçersiz say” | if oy in oylar: ile sına, değilse geçersiz oy sayacını artır |
oylar["Elif"] + 1 KeyError verir. oylar.get("Elif", 0) + 1 hata vermez, ama Elif’i aday gibi sözlüğe ekler |
| Hiç oy almayan aday | “Oy sütununda 0 ara, yanındaki adı yaz” | 0 in oylar.values(), adı için for aday, sayi in oylar.items(): |
0 in oylar aday adlarına, yani anahtarlara bakar ve False verir |
| Kaç farklı aday oy aldı? | “Oy alan her adayı bir kez yaz, sonra say” | Geçerli oyları add() ile bir kümeye ekle, sonra len() |
len(kagitlar) kâğıt sayısını, yani 6’yı verir. len(set(kagitlar)) Elif’i de sayar ve 4 verir. Doğru cevap 3 |
Listenizi tabloyla karşılaştırın. Her soru için ayrı bir koleksiyon seçtik: kâğıtlar sıra ve tekrar önemli olduğu için liste, sonuç tablosu aday adıyla erişildiği için sözlük, oy alan adaylar her biri bir kez sayılacağı için küme. Elif için “onu da sayarım” dediyseniz get() kalıbını kurmuşsunuz: sayım hata vermeden sürer, ama aday olmayan biri sonuç tablosuna girer.
Üret: basit oy özeti
Seçim kurulunun sonuç tablosunda aday adları anahtar, oy sayıları değer olsun. oy_ozeti(oylar) adlı bir fonksiyon yazın. Fonksiyon şu iki sayıyı hesaplayıp (toplam_oy, oy_almayan_aday_sayisi) demeti olarak döndürsün:
- Toplam oy sayısı
- Hiç oy almamış aday sayısı
Beklenen:
(20, 2)
for sayi in oylar.values(): biçiminde değerler üzerinde gezinebilirsiniz.
def oy_ozeti(oylar):
toplam_oy = 0
oy_almayan_aday_sayisi = 0
for sayi in oylar.values():
toplam_oy = toplam_oy + sayi
if sayi == 0:
oy_almayan_aday_sayisi = oy_almayan_aday_sayisi + 1
return toplam_oy, oy_almayan_aday_sayisi
oylar = {
"Ayşe": 12,
"Burak": 0,
"Can": 8,
"Deniz": 0
}
print(oy_ozeti(oylar))Sıra sizde: oyları sayın
Sayımın tamamını yazın. Program kâğıtları tek tek okusun ve şu işleri yapsın:
- Ad aday listesindeyse o adayın oyunu bir artırsın ve adı
oy_alanlarkümesine eklesin. - Ad aday listesinde yoksa
gecersizsayacını bir artırsın. - En sonda kaç farklı adayın oy aldığını ve hiç oy almayan adayları yazdırsın.
Beklenen sonuçlar: Ayşe 3, Burak 1, Can 1, Deniz 0 oy. Geçersiz oy sayısı 1. Oy alan farklı aday sayısı 3. Hiç oy almayan aday Deniz.
Döngüde önce if oy in oylar: ile adın aday listesinde olup olmadığına bakın. Hiç oy almayan adayları bulmak için döngüden sonra oylar.items() üzerinde dolaşın ve değeri 0 olanları yazdırın.
kagitlar = ["Ayşe", "Burak", "Ayşe", "Elif", "Ayşe", "Can"]
oylar = {"Ayşe": 0, "Burak": 0, "Can": 0, "Deniz": 0}
gecersiz = 0
oy_alanlar = set()
for oy in kagitlar:
if oy in oylar:
oylar[oy] = oylar[oy] + 1
oy_alanlar.add(oy)
else:
gecersiz = gecersiz + 1
print(oylar)
print(gecersiz)
print("Oy alan farklı aday:", len(oy_alanlar))
for aday, sayi in oylar.items():
if sayi == 0:
print("Oy almayan:", aday)Tek sayfa özet
Bu hafta listelerin yanına sözlükleri ve kümeleri de ekledik. Konsey seçiminin oy sayımında olduğu gibi, her iş için koleksiyonu programın veriye nasıl erişeceğine göre seçtik.
- Sözlük her değeri bir anahtarla birlikte tutar.
sozluk["anahtar"]o anahtarın değerini verir. Anahtar yoksaKeyErrorçıkar."anahtar" in sozlukyalnız anahtarlara bakar. Değerlerde aramak içinin sozluk.values()yazılır.- Bir anahtara yeniden atama yapmak değeri günceller;
pop()veyadelile alan silinebilir. get()anahtar yoksa hata vermez;Noneya da verdiğiniz varsayılan değeri döndürür. Varsayılan0, “bilgi yok” ile “gerçekten sıfır” ayrımını siler..keys(),.values()ve.items()ile sırasıyla anahtarlarda, değerlerde ve anahtar–değer çiftlerinde dolaşılır.- Sözlük anahtarları hashlenebilir olmalıdır; değiştirilebilir
listanahtar olamaz. - Python 3.7 ve sonrasında sözlük ekleme sırasını korur ama anahtarları alfabetik olarak sıralamaz.
- Her değerin kaç kez geçtiğini saymak (frekans tablosu) için sözlük uygundur:
sayilar[x] = sayilar.get(x, 0) + 1. - Küme her değeri bir kez tutar ve indeksi yoktur; yazdırma ve dolaşma sırasına güvenilmez.
set(liste)listedeki benzersiz değerleri verir.- Kümede üyelik kontrolü
inile yapılır. - Liste, demet, sözlük ve küme farklı erişim ihtiyaçlarına göre seçilir.
Bir sonraki bölümde liste ve sözlüğü birlikte kullanarak küçük kayıt listelerini işleyeceğiz.
Bu bölümün kazanımları
Bu bölümü bitiren öğrenci:
- Anahtar–değer modeliyle sözlükten değer okur ve alan günceller.
indenetiminin sözlükte değeri değil anahtarı aradığını açıklar.get()ile eksik anahtarda varsayılan kullanır ve bunun bedelini açıklar..keys(),.values()ve.items()arasındaki farkı açıklar.- Sözlük anahtarının hashlenebilir olması gerektiğini açıklar.
- Sözlükle frekans veya sayaç tablosu kurar.
- Kümenin benzersizlik ve sıra davranışını açıklar ve probleme uygun koleksiyonu seçer.