Sözlükler, kümeler ve koleksiyon seçimi

Listelerde bir değere erişmek için çoğunlukla indeks kullanırız. Fakat gerçek veriler çoğu zaman “0. eleman” veya “2. eleman” diye değil, ad, fiyat, stok, öğrenci numarası gibi anlamlı alanlarla düşünülür.

Bu hafta Python’ın sözlük (dict) yapısını anahtar–değer ilişkileri için, küme (set) yapısını ise tekrarsız değerleri tutmak için kullanacağız. Ayrıca “bu problem için liste mi, sözlük mü, küme mi?” sorusunu bilinçli biçimde sormaya başlayacağız.

Bu hafta neleri yapabilmelisiniz?

Bölümün sonunda:

  • Sözlük oluşturabilmeli,
  • Anahtar kullanarak değere erişebilmeli,
  • in ile sözlükte anahtar bulunup bulunmadığını kontrol edebilmeli,
  • Yeni anahtar–değer çifti ekleyebilmeli, mevcut değeri güncelleyebilmeli ve gerektiğinde kayıt silebilmeli,
  • get() ile eksik anahtarı daha güvenli biçimde sorgulayabilmeli,
  • .keys(), .values() ve .items() kullanımlarını ayırt edebilmeli,
  • Sözlük anahtarlarının neden hashlenebilir/değiştirilemez türlerden seçilmesi gerektiğini başlangıç düzeyinde açıklayabilmeli,
  • Sözlüklerin ekleme sırasını koruması ile kümelerin sırasız davranışı arasındaki farkı açıklayabilmeli,
  • Basit bir sayma/frekans tablosu oluşturabilmeli,
  • Küme oluşturabilmeli ve tekrarlı değerlerin nasıl elendiğini açıklayabilmeli,
  • in ile kümede üyelik kontrolü yapabilmeli,
  • add() ile kümeye eleman ekleyebilmeli,
  • Liste, sözlük ve küme arasında probleme uygun olanı seçebilmelisiniz.

Sözlük: anahtardan değere erişim

Sözlükte köşeli parantez ile anahtar erişimi ve get() metodunun eksik anahtardaki farklı davranışı.

Sözlükte anahtar erişimi ve get

Bir ürün bilgisini listeyle şöyle tutmak mümkün olabilir:

urun = ["Kalem", 12.5, 40]

Fakat urun[1] ifadesinin ne olduğunu anlamak için listenin düzenini bilmek gerekir.

Sözlükte alanlara 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

Anahtarlar benzersiz olmalıdır. Aynı anahtar yeniden atanırsa eski değer güncellenir.

urun = {"stok": 40}
urun["stok"] = 35

print(urun)

Sonuç:

{'stok': 35}

Yeni alan da eklenebilir:

urun["kategori"] = "Kırtasiye"

Sözlükte in anahtarı kontrol eder

Sözlük üzerinde in kullandığınızda varsayılan olarak anahtarların varlığı kontrol edilir:

urun = {"ad": "Kalem", "stok": 40}

print("stok" in urun)       # True
print("fiyat" in urun)      # False
print("Kalem" in urun)      # False

Son satırda "Kalem" bir değerdir, anahtar değildir. Değerler içinde arama yapılacaksa bunu ayrıca .values() ile ifade etmek gerekir:

print("Kalem" in urun.values())

Bu ayrım özellikle eksik alan kontrolünde 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:

Sözlükte alanların adla erişilebilir olması, kodun niyetini listede sabit indeks kullanmaktan daha görünür kılar.

Alıştırma — stok değerini güncelleyin

Bir satış sonrasında stoktan 3 ürün eksilsin.

Beklenen sonuç 9dur.

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 üretir:

urun = {"ad": "Kalem"}
# print(urun["stok"])

Eğer alanın bulunmaması normal bir durumsa get() kullanılabilir:

urun = {"ad": "Kalem"}

stok = urun.get("stok")
print(stok)

Sonuç None olur.

Varsayılan değer de verebiliriz:

stok = urun.get("stok", 0)
print(stok)

Bu kez sonuç 0 olur.

Warning

get("stok", 0) kullanmak her problemde doğru değildir. Eksik stok bilgisinin gerçekten 0 anlamına gelip gelmediğini problem kuralı belirler. “Veri yok” ile “değer gerçekten sıfır” aynı bilgi değildir.

Sözlük üzerinde gezinmek: keys(), values(), items()

Bir sözlüğün üç yaygın görünümü vardır:

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

sunar.

Yalnızca anahtarlar üzerinde dolaşırken şu iki kullanım eşdeğer niyettedir:

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 iki elemanlı bir demet verir; 9. haftadaki demet açma bilgimizi burada yeniden kullanıyoruz.

Sözlükten kayıt silmek

Bir anahtar–değer çiftini silmek için pop() kullanışlıdı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 bulunmaması normal bir olasılıksa varsayılan verebilirsiniz:

silinen = urun.pop("indirim", None)

del urun["stok"] sözdizimi de anahtarı silebilir; ancak olmayan anahtarda KeyError üretir. Başlangıçta silinen değere de ihtiyaç duyduğumuz örneklerde pop() daha açıklayıcıdır.

Hangi değerler sözlük anahtarı olabilir?

Sözlük, anahtarı hızlı biçimde bulmak için anahtarın hashlenebilir (hashable) olmasını ister. Başlangıç düzeyinde pratik kural şudur: anahtar olarak çoğunlukla değiştirilemeyen değerler kullanın.

Yaygın 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 davranışı 9. haftadaki mutable / immutable ayrımıyla ilişkilendirebilirsiniz.

Note

“Her değiştirilemez değer mutlaka her durumda iyi anahtardır” gibi ezber bir sonuç çıkarmayın. Buradaki temel fikir, sözlük anahtarının sözlük içindeyken güvenilir biçimde bulunabilir bir kimlik sağlamasıdır. Bu ders için str, int ve basit uygun demetler yeterlidir.

Sözlük sırası ile küme sırası aynı değildir

Modern Python’da (3.7+) sözlükler anahtarların eklenme sırasını korur:

urun = {}
urun["ad"] = "Kalem"
urun["fiyat"] = 12.5
urun["stok"] = 40

print(list(urun.keys()))

Bu program anahtarları ekleme sırasıyla verir:

['ad', 'fiyat', 'stok']

Ancak bu, sözlüğün anahtarları alfabetik veya sayısal olarak sıraladığı anlamına gelmez. Yalnızca ekleme sırası korunur.

Kümelerde ise gösterim veya dolaşma sırasına güvenilmemelidir. Aynı küme farklı çalıştırma veya ortamlarda farklı sırada görünebilir.

Important

Bir alıştırmada kümenin elemanlarını farklı sırada görmeniz tek başına cevabınızın yanlış olduğu anlamına gelmez. Kümede önemli olan üyelik ve benzersizliktir. Belirli bir çıktı sırası gerekiyorsa sorted(kume) gibi açık bir sıralama adımı kullanın.

Sayma tablosu oluşturmak

Sözlüklerin güçlü kullanım alanlarından biri frekans sayımıdı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}

Her şehir ilk kez görüldüğünde get(sehir, 0) değeri 0 verir; sonraki karşılaşmalarda mevcut 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) mevcut sayıyı veya ilk karşılaşmada sıfırı 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)

Kümede "python" yalnızca bir kez bulunur. Fakat ekrana hangi sırada yazılacağı sözlükteki ekleme sırası davranışı gibi garanti edilmez.

Bir listeyi kümeye dönüştürmek de mümkündür:

sehirler = ["Samsun", "Ordu", "Samsun", "Amasya"]
benzersiz = set(sehirler)

print(benzersiz)

Küme, benzersiz değerleri bulmak istediğimizde kullanışlıdır.

Liste, sözlük ve küme arasında gereksinime göre seçim.

Koleksiyon seçimi
Note

Kümeyi indeksle sıralı bir yapı gibi kullanmayın. kume[0] biçiminde erişim yoktur. Eğer sıra problem için önemliyse liste daha uygun olabilir.

Kümede üyelik kontrolü

Kümeler üyelik kontrolü için doğal bir yapıdır:

izinli_roller = {"ogrenci", "personel", "misafir"}

rol = "personel"

if rol in izinli_roller:
    print("Rol tanımlı")

Eleman eklemek için add():

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 kayıtları azaltın

Aşağıdaki ders kodlarından benzersiz olanları küme olarak elde edin.

Beklenen benzersiz değer sayısı 3tür. Kümenin ekrana hangi sırada yazıldığı değerlendirme ölçütü değildir.

set(dersler) listedeki tekrarları kaldırarak küme üretir.

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. Veriyle ne yapmak istediğimiz önemlidir.

İ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, stok alanları → sözlük
  • Sistemde görülen benzersiz hata kodları → küme
Tip

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 kaydı tutmak için her ürünü sözlük, kayıtların tamamını liste yapabiliriz:

urunler = [
    {"ad": "Kalem", "fiyat": 12.5},
    {"ad": "Defter", "fiyat": 45},
    {"ad": "Silgi", "fiyat": 8}
]

for urun in urunler:
    print(urun["ad"], urun["fiyat"])

Bu yapı gelecek haftanın ana konusudur: birden fazla kayıt üzerinde filtreleme, gruplama ve özetleme.

Ü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ı fonksiyon:

  • Toplam stok miktarını,
  • Stoku 0 olan ürün sayısını

hesaplayıp (toplam_stok, tukenen_urun_sayisi) demeti olarak döndürsün.

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))

Bölüm özeti

Bu hafta koleksiyon seçimimizi problem ihtiyacına göre genişlettik.

  • Sözlük anahtar–değer ilişkileri tutar.
  • sozluk["anahtar"] değere doğrudan erişir; "anahtar" in sozluk anahtarın bulunup bulunmadığını kontrol eder.
  • Bir anahtara yeniden atama yapmak değeri günceller; pop() veya del ile alan silinebilir.
  • get() eksik anahtarda varsayılan değer kullanmaya izin verir.
  • .keys(), .values() ve .items() sırasıyla anahtar, değer ve anahtar–değer çiftlerini dolaşmayı sağlar.
  • Sözlük anahtarları hashlenebilir olmalıdır; değiştirilebilir list anahtar olamaz.
  • Python 3.7+ sözlükler ekleme sırasını korur; bu alfabetik sıralama anlamına gelmez.
  • Sözlük, frekans veya sayaç tablosu oluşturmak için uygundur.
  • Küme tekrarsız değerler tutar ve sıralı indeks yapısı değildir; yazdırma/dolaşma sırasına güvenilmez.
  • set(liste) benzersiz değerleri elde etmek için kullanılabilir.
  • in, kümede üyelik kontrolü için doğal bir işlemdir.
  • Liste, demet, sözlük ve küme farklı erişim ihtiyaçlarına hizmet eder.

Kendinizi kontrol edin

  1. urun["fiyat"] ifadesindeki "fiyat" nedir?
  2. "stok" in urun neyi kontrol eder? "Kalem" in urun neden değeri aramaz?
  3. Olmayan bir anahtara sozluk["x"] ile erişmenin sonucu ne olabilir?
  4. get("x", 0) ne yapar ve “eksik” ile “0” aynı anlamda değilse neden sakıncalı olabilir?
  5. .keys(), .values() ve .items() arasındaki fark nedir?
  6. pop() ne yapar?
  7. Neden [1, 2] listesi sözlük anahtarı olamaz?
  8. Sözlüklerin ekleme sırasını koruması ile kümelerin sıra davranışı arasındaki fark nedir?
  9. sayilar[deger] = sayilar.get(deger, 0) + 1 kalıbı ne amaçla kullanılır?
  10. Küme neden tekrar eden değerleri tutmaz ve bir alıştırmada farklı yazdırma sırası neden hata değildir?
  11. Hangi durumda liste yerine küme seçmek daha anlamlıdır?
  12. Bir ürün kaydı için neden sözlük, yalnızca ürün adlarının sıralı listesi için neden liste daha doğal olabilir?

Bir sonraki bölümde liste ve sözlükleri birlikte kullanarak küçük kayıt kümelerini işleyeceğiz.

Back to top