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 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; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.
"Kalem" in urun neden False döndürüyor?
Kısa cevap: sözlükte in değerlere değil anahtarlara bakar ve "Kalem" bir anahtar değil, değerdir. Bu farkı görmek için önce sözlüğün nasıl yazıldığına bakalım.
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:
urun = {
"ad": "Kalem",
"fiyat": 12.5,
"stok": 40
}Değerlere anahtar ile erişiriz:
print(urun["ad"])
print(urun["fiyat"])
print(urun["stok"])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. Var olan bir anahtara yeniden değer atarsanız eski değerin yerine yenisi geçer.
urun = {"stok": 40}
urun["stok"] = 35
print(urun)Sonuç:
{'stok': 35}
Olmayan bir anahtara değer atarsanız sözlüğe yeni bir alan eklenir:
urun["kategori"] = "Kırtasiye"Sözlükte in anahtarı kontrol eder
Sözlükte in kullandığınızda Python yalnızca anahtarlara bakar:
urun = {"ad": "Kalem", "stok": 40}
print("stok" in urun) # True
print("fiyat" in urun) # False
print("Kalem" in urun) # FalseSon satırda "Kalem" bir değerdir, anahtar değildir. 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:
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 anahtara köşeli parantezle erişmek KeyError hatası verir:
urun = {"ad": "Kalem"}
# print(urun["stok"])Alanın eksik olması beklenen bir durumsa get() kullanılabilir:
urun = {"ad": "Kalem"}
stok = urun.get("stok")
print(stok)Sonuç None olur.
get()e ikinci argüman olarak bir varsayılan değer de verebiliriz. Anahtar yoksa bu değer döner:
stok = urun.get("stok", 0)
print(stok)Bu kez sonuç 0 olur.
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:
urun = {"ad": "Kalem", "fiyat": 12.5, "stok": 40}
print(urun.keys())
print(urun.values())
print(urun.items()).keys()→ anahtarları,.values()→ değerleri,.items()→(anahtar, deger)çiftlerini
verir.
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:
for anahtar, deger in urun.items():
print(anahtar, deger)items() her adımda (anahtar, deger) biçiminde iki elemanlı bir demet verir. for anahtar, deger in ... yazınca bu demeti, 9. haftada gördüğümüz gibi iki değişkene açmış oluruz.
Sözlükten alan silmek
Bir anahtarı değeriyle birlikte silmek için pop() kullanılır:
urun = {"ad": "Kalem", "stok": 40, "gecici_not": "kontrol"}
silinen = urun.pop("gecici_not")
print(silinen)
print(urun)pop() anahtarı siler ve silinen değeri döndürür. 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" # tuple içindeki elemanlar da hashlenebilirse
}Liste değiştirilebilir olduğu için sözlük anahtarı olamaz:
sozluk = {}
# sozluk[[1, 2]] = "x"
# TypeError: unhashable type: 'list'Bu kuralı 9. haftadaki değiştirilebilir (mutable) ve değiştirilemez (immutable) ayrımıyla birlikte düşünün.
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:
urun = {}
urun["ad"] = "Kalem"
urun["fiyat"] = 12.5
urun["stok"] = 40
print(list(urun.keys()))Çıktı:
['ad', 'fiyat', 'stok']
Sözlük anahtarları alfabetik ya da sayısal olarak sıralamaz; yalnızca ekleme sırasını korur.
Kümelerde ise yazdırma veya dolaşma sırasına güvenmeyin: aynı küme farklı çalıştırmalarda veya 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.
Bir listedeki şehirlerin kaç kez geçtiğini bulalım:
sehirler = ["Samsun", "Ordu", "Samsun", "Amasya", "Ordu", "Samsun"]
sayilar = {}
for sehir in sehirler:
sayilar[sehir] = sayilar.get(sehir, 0) + 1
print(sayilar)Sonuç:
{'Samsun': 3, 'Ordu': 2, 'Amasya': 1}
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.
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:
etiketler = {"python", "web", "python", "veri"}
print(etiketler)İ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:
sehirler = ["Samsun", "Ordu", "Samsun", "Amasya"]
benzersiz = set(sehirler)
print(benzersiz)Böylece listedeki tekrarlar atılır ve yalnızca benzersiz değerler kalır.
Kümenin indeksi yoktur; kume[0] yazamazsınız. Sıra sizin için önemliyse liste daha uygun olabilir.
Kümede üyelik kontrolü
Kümeler, bir değerin içlerinde olup olmadığını sormak (üyelik kontrolü) için çok uygundur:
izinli_roller = {"ogrenci", "personel", "misafir"}
rol = "personel"
if rol in izinli_roller:
print("Rol tanımlı")Kümeye eleman add() ile eklenir:
izinli_roller.add("yonetici")Tahmin et: kaç benzersiz değer var?
İlk uzunluk 6, benzersiz değer sayısı 4 olur.
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çim, veriyle ne yapmak istediğimize bağlıdır.
| İ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:
urunler = [
{"ad": "Kalem", "fiyat": 12.5},
{"ad": "Defter", "fiyat": 45},
{"ad": "Silgi", "fiyat": 8}
]
for urun in urunler:
print(urun["ad"], urun["fiyat"])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.
Üret: basit stok özeti
Bir stok sözlüğünde ürün kodları anahtar, stok miktarları değer olsun:
stoklar = {
"KLM": 12,
"DFT": 0,
"SLG": 8,
"CTN": 0
}stok_ozeti(stoklar) adlı bir fonksiyon yazın. Fonksiyon şu iki sayıyı hesaplayıp (toplam_stok, tukenen_urun_sayisi) demeti olarak döndürsün:
- Toplam stok miktarı
- Stoğu
0olan ürün sayısı
Başlangıç:
Beklenen:
(20, 2)
for miktar in stoklar.values(): biçiminde değerler üzerinde gezinebilirsiniz.
def stok_ozeti(stoklar):
toplam_stok = 0
tukenen_urun_sayisi = 0
for miktar in stoklar.values():
toplam_stok = toplam_stok + miktar
if miktar == 0:
tukenen_urun_sayisi = tukenen_urun_sayisi + 1
return toplam_stok, tukenen_urun_sayisi
stoklar = {
"KLM": 12,
"DFT": 0,
"SLG": 8,
"CTN": 0
}
print(stok_ozeti(stoklar))Tek sayfa özet
Bu hafta listelerin yanına sözlükleri ve kümeleri de ekledik; koleksiyonu problemin ihtiyacına göre seçmeye başladık.
- Sözlük her değeri bir anahtarla birlikte tutar.
sozluk["anahtar"]o anahtarın değerini verir;"anahtar" in sozlukanahtarın bulunup bulunmadığını kontrol eder.- 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..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.
- 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ı bilir.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ı tanır ve probleme uygun koleksiyonu seçer.