# Python'da sözlükler (dict): oluşturma, metotlar, dolaşma, sıralama ve frozendict

URL: https://skillaria.top/tr/guides/python/python-sozlukler

Python'da sözlük (dict), anahtar-değer çiftlerinden oluşan değiştirilebilir bir koleksiyondur ve değeri anahtarla neredeyse anında bulur; {"kahve": 250} biçiminde süslü parantezlerle ya da dict() fonksiyonuyla oluşturulur. Anahtarlar benzersiz ve özetlenebilir olmalıdır, Python 3.7'den beri ekleme sırası korunur, Python 3.15'te ise yerleşik değiştirilemez bir tür olan frozendict gelmiştir.

Python'da sözlük (`dict`), anahtar-değer çiftlerinden oluşan bir koleksiyondur; kaç kayıt olursa olsun, değer anahtarla neredeyse anında bulunur. Harcamaları kategorilere göre saymak, ayarları tutmak ya da bir kullanıcıyı kimliğiyle hızlıca aramak istediğinizde sözlük kullanırsınız. Aşağıda python dict ile çalışmanın her yönü var: oluşturma, metotlar, dolaşma, sıralama, birleştirme ve 3.15'in yeni tipi `frozendict`.

## Python'da sözlük nedir

Sözlük çiftleri saklar ve anahtar benzersizdir: var olan bir anahtara değer yazarsanız eski değer üzerine yazılır. İç yapısı bir hash tablosudur; bu yüzden anahtara göre arama, ekleme ve silme işlemleri ortalama olarak sabit sürede çalışır, tüm kayıtlar taranmaz.

Anahtar olarak yalnızca özetlenebilir (hashable) bir nesne kullanılabilir: metin, sayı, değiştirilemeyen değerlerden oluşan demet. Liste anahtar olamaz; `TypeError: unhashable type: 'list'` hatası alırsınız. Değerler ise her şey olabilir, başka sözlükler ve listeler dahil.

Python 3.7'den itibaren sözlük ekleme sırasını garanti eder: dolaşırken anahtarlar eklendikleri sırayla gelir.

## Sözlük nasıl oluşturulur

Sözlük oluşturmanın birkaç yolu vardır ve hepsi gerçek kodda karşınıza çıkar.

```
spent = {"Yiyecek": 1200, "Taksi": 450}    # değişmez değer (literal)
empty = {}                                 # boş sözlük
also_empty = dict()                        # dict fonksiyonuyla aynısı
user = dict(name="Ayşe", age=30)           # adlandırılmış argümanlarla
pairs = dict([("a", 1), ("b", 2)])         # çiftlerden oluşan listeyle
keys = dict.fromkeys(["x", "y"], 0)        # {'x': 0, 'y': 0}
```

Dikkat: boş süslü parantez `{}` boş bir kümeyi değil, boş bir sözlüğü oluşturur. Boş küme yalnızca `set()` ile yapılır.

İki listeden sözlük kurmanın kullanışlı yolu `zip`'tir:

```
names = ["Yiyecek", "Taksi", "Sinema"]
sums = [1200, 450, 600]
spent = dict(zip(names, sums))
print(spent)   # {'Yiyecek': 1200, 'Taksi': 450, 'Sinema': 600}
```

## Anahtarla erişim: d[k] ve get

Değer köşeli parantezle okunur. Anahtar yoksa Python `KeyError` fırlatır. Hata almamak için `get` metodunu kullanın: anahtar yoksa `None` ya da verdiğiniz varsayılan değeri döndürür.

```
spent = {"Yiyecek": 1200}
print(spent["Yiyecek"])            # 1200
print(spent.get("Sinema"))         # None
print(spent.get("Sinema", 0))      # 0
spent["Sinema"]                    # KeyError: 'Sinema'
```

Bir anahtarın var olup olmadığını `in` operatörüyle sorarsınız: `"Yiyecek" in spent` değeri `True`'dur. Operatör yalnızca anahtarlara bakar, değerlere bakmaz. Değerler için `1200 in spent.values()` yazın.

## Ekleme, değiştirme ve silme

Kayıt eklemek ya da güncellemek tek satırlık bir atamadır. Sayım yaparken `get` ile birlikte kullanmak çok pratiktir:

```
spent = {}
for category, amount in [("Yiyecek", 250), ("Taksi", 300), ("Yiyecek", 400)]:
    spent[category] = spent.get(category, 0) + amount
print(spent)   # {'Yiyecek': 650, 'Taksi': 300}
```

Bir anahtarı `del d[k]` ile silebilirsiniz (anahtar yoksa `KeyError` verir) ya da değeri de döndüren `d.pop(k, varsayılan)` ile. Sözlüğün tamamını temizlemek için `d.clear()`. Kayıt sayısı, yani çift sayısı, `len(d)` ile alınır.

## Sözlük metotları: kısa liste

| Metot | Ne yapar |
| --- | --- |

| `get(k, varsayılan)` | anahtarın değerini ya da varsayılanı hata vermeden döndürür |

| `setdefault(k, varsayılan)` | değeri döndürür; anahtar yoksa önce varsayılanı yazar |

| `update(diğer)` | diğer sözlükteki çiftleri ekler ve üzerine yazar |

| `pop(k, varsayılan)` | anahtarı siler ve değerini döndürür |

| `popitem()` | en son eklenen çifti siler ve döndürür |

| `keys()`, `values()`, `items()` | anahtarların, değerlerin ve çiftlerin görünümleri |

| `copy()` | yüzeysel kopya |

| `clear()` | sözlüğü temizler |

| `fromkeys(anahtarlar, değer)` | aynı değerli yeni bir sözlük |

### setdefault: değerleri listelerle doldurmak

Değerler liste olduğunda ve veriyi gruplamanız gerektiğinde `setdefault` işinizi görür:

```
groups = {}
for item, cat in [("kahve", "Yiyecek"), ("metro", "Ulaşım"), ("pizza", "Yiyecek")]:
    groups.setdefault(cat, []).append(item)
print(groups)   # {'Yiyecek': ['kahve', 'pizza'], 'Ulaşım': ['metro']}
```

### update: sözlüğü güncellemek

`update` sözlüğü yerinde değiştirir: yeni anahtarlar eklenir, aynı olanların değerleri yeniden yazılır.

```
cfg = {"debug": False, "lang": "tr"}
cfg.update({"debug": True, "theme": "dark"})
print(cfg)   # {'debug': True, 'lang': 'tr', 'theme': 'dark'}
```

## defaultdict: varsayılan değeri olan sözlük

`collections.defaultdict`, dict'in bir alt sınıfıdır: var olmayan bir anahtara erişildiğinde değeri kendi verdiğiniz fabrika fonksiyonuyla kendisi oluşturur. Sayım ve gruplama kodu böylece kısalır.

```
from collections import defaultdict

spent = defaultdict(int)
for cat, amount in [("Yiyecek", 250), ("Taksi", 300), ("Yiyecek", 400)]:
    spent[cat] += amount
print(dict(spent))   # {'Yiyecek': 650, 'Taksi': 300}

groups = defaultdict(list)
groups["Yiyecek"].append("kahve")
```

Yalnızca sayım yapacaksanız `collections.Counter` da var: `Counter(["a", "b", "a"])` sonucu `Counter({'a': 2, 'b': 1})` olur.

## Sözlükte dolaşmak: for döngüsü

Bir sözlük `for` döngüsünde varsayılan olarak anahtarları verir. Anahtar ve değeri birlikte almak için en sık kullanılan yol `items()`'tır.

```
spent = {"Yiyecek": 650, "Taksi": 300}

for cat in spent:                    # anahtarlar
    print(cat)

for amount in spent.values():        # değerler
    print(amount)

for cat, amount in spent.items():    # çiftler
    print(f"{cat}: {amount} TL")
```

Dolaşırken sözlüğün boyutunu değiştiremezsiniz; `RuntimeError: dictionary changed size during iteration` hatası alırsınız. Bir kısım anahtarı silmeniz gerekiyorsa kopya üzerinde dolaşın: `for k in list(d):`.

## Sözlüğü ekrana yazdırmak

`print(d)` sözlüğü tek satırda yazdırır. Büyük ya da iç içe sözlükler için `pprint` modülü ya da `json.dumps(d, ensure_ascii=False, indent=2)` daha uygundur: veriyi girintili ve Türkçe karakterleri kaçırmadan gösterir.

## Sözlük sıralama

Sözlük kendi içinde sıralanmaz; `sort` metodu yoktur. Sözlüğü sıralamak, `sorted` ile sıralanmış çiftlerden yeni bir sözlük kurmak demektir.

```
spent = {"Taksi": 300, "Yiyecek": 650, "Sinema": 120}

by_key = dict(sorted(spent.items()))
print(by_key)    # {'Sinema': 120, 'Taksi': 300, 'Yiyecek': 650}

by_value = dict(sorted(spent.items(), key=lambda p: p[1], reverse=True))
print(by_value)  # {'Yiyecek': 650, 'Taksi': 300, 'Sinema': 120}
```

Yalnızca ilk N kategoriye ihtiyacınız varsa sonucu tekrar sözlüğe çevirmeyin: `sorted(spent.items(), key=lambda p: p[1], reverse=True)[:2]` çiftlerden oluşan bir liste döndürür.

Sözlüklerden oluşan bir listeyi bir alana göre sıralamak için: `sorted(users, key=lambda u: u["age"])`.

## Sözlükleri birleştirmek

Python 3.9'dan itibaren sözlükler `|` operatörüyle birleşir; `|=` ise sözlüğü yerinde günceller. Anahtarlar çakışırsa sağdaki operand kazanır.

```
a = {"x": 1, "y": 2}
b = {"y": 20, "z": 3}
print(a | b)          # {'x': 1, 'y': 20, 'z': 3}
print({**a, **b})     # aynısı açma (unpacking) ile
a |= b                # a.update(b) ile aynı
```

Dikkat: sözlüklerde `a + b` çalışmaz, `TypeError` verir. Aynı anahtarların değerlerini toplamak istiyorsanız `Counter` kullanın: `Counter(a) + Counter(b)`.

### Sözlük açma

Çift yıldız `**` bir sözlüğü fonksiyonun adlandırılmış argümanlarına ya da başka bir sözlüğe açar:

```
def greet(name, city):
    return f"{name}, {city}'dan"

data = {"name": "Ayşe", "city": "Ankara"}
print(greet(**data))   # Ayşe, Ankara'dan
```

## Sözlük üretimi (dict comprehension)

Sözlük üretimi, herhangi bir diziden tek satırda sözlük kurar:

```
squares = {n: n * n for n in range(5)}
print(squares)   # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

big = {k: v for k, v in spent.items() if v > 200}

inverted = {v: k for k, v in {"a": 1, "b": 2}.items()}
print(inverted)  # {1: 'a', 2: 'b'}
```

Son örnek sözlüğü ters çevirir: anahtarlar ve değerler yer değiştirir. Bu yöntem yalnızca değerler benzersiz ve özetlenebilir olduğunda çalışır; aksi halde bazı çiftler kaybolur.

## İç içe sözlükler

Bir değer başka bir sözlük olabilir. JSON yanıtlarını ya da kullanıcıların sözlüğünü tutan yapılar böyle kurulur.

```
users = {
    101: {"name": "Ayşe", "skills": ["python", "sql"]},
    102: {"name": "Ali", "skills": ["go"]},
}
print(users[101]["skills"][0])            # python
print(users.get(103, {}).get("name"))     # None, KeyError olmadan
```

## Sözlük kopyalamak: kopya mı, ikinci isim mi

`b = a` satırı sözlüğü kopyalamaz; aynı nesneye ikinci bir ad verir. `b` üzerinden yapılan değişiklikler `a`'da da görünür. Sözlüğü bir fonksiyona vermek de aynı şekilde çalışır: fonksiyon ortak nesneyi alır ve farkında olmadan bozabilir.

```
import copy

a = {"limits": [0, 500]}
b = a.copy()              # yüzeysel kopya
b["limits"].append(1000)  # iç liste ortak!
print(a)                  # {'limits': [0, 500, 1000]}

c = copy.deepcopy(a)      # tamamen bağımsız kopya
```

## Sözlükleri karşılaştırmak

`==` operatörü sözlükleri içeriğine göre karşılaştırır: tüm çiftler aynıysa eşittirler. Anahtarların sırası dikkate alınmaz: `{"a": 1, "b": 2} == {"b": 2, "a": 1}` ifadesi `True` verir. Ortak anahtarları bulmak için görünümler üzerinde küme işlemleri kullanın: `a.keys() & b.keys()`.

## Tipli sözlük: tür ipuçları

Sözlüğün tür ipucu `dict[str, int]` biçiminde yazılır. Alanları sabit ve türleri farklı olan bir sözlük için `typing` modülündeki `TypedDict` uygundur:

```
from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

u: User = {"name": "Ayşe", "age": 30}
```

Tür ipuçları çalışma zamanında denetlenmez; bunları IDE'ler ve mypy gibi analiz araçları okur.

## Değiştirilemeyen sözlük: Python 3.15'te frozendict

Python 3.15 ile yerleşik `frozendict` tipi geldi (PEP 814): içe aktarmaya gerek yoktur ve değiştirmeye çalışmak doğrudan `TypeError` ile sonuçlanır. Daha önce değiştirilemeyen sözlük, `types` modülündeki bir sarmalayıcıyla ya da üçüncü taraf bir paketle taklit edilirdi. Bu, hiçbir fonksiyonun sessizce değiştiremeyeceği ortak ayarlar için tam aradığınız şeydir.

```
config = frozendict(min_amount=0, max_amount=500)
config["max_amount"] = 1000
# TypeError: 'frozendict' object does not support item assignment

strict = config | {"max_amount": 300}   # yeni bir frozendict, orijinal duruyor
cache = {config: "mayıs raporu"}        # özetlenebilir — anahtar olabilir
```

Kurs materyallerine göre bilmeniz gerekenler:

- `frozendict`, `dict`'ten değil `object`'ten türer; bu yüzden `isinstance(cfg, dict)` `False` döndürür. "Herhangi bir sözlük" kontrolü için `collections.abc.Mapping` ya da `isinstance(x, (dict, frozendict))` kullanın.
- Özetlenebilir yalnızca anahtarları ve değerleri özetlenebilirse: `frozendict(a=[1])` oluşturulur, ama `hash()` çağrısı hata verir. Değiştirilemezlik sığdır, tıpkı demetlerde olduğu gibi.
- Sıra korunur, ama `==` karşılaştırması sırayı dikkate almaz.
- `json.dumps`, `pickle` ve `copy` frozendict'i tanır.

## Tipik hatalar

- **Okurken KeyError** — `get` ya da `in` ile kontrol edin.
- **Anahtar olarak liste** — listeyi demete çevirin: `d[tuple(lst)]`.
- **Döngü sırasında değiştirmek** — `list(d)` üzerinde dolaşın.
- **Atamanın kopya yaptığını sanmak** — `copy()` ya da `deepcopy` kullanın.
- **Boş küme yerine `{}`** — bu boş bir sözlüktür.

## Özet

Python dict, dilin temel veri yapısıdır: anahtarla hızlı arama, ekleme sırasının korunması, `get`, `setdefault`, `update` gibi kullanışlı metotlar, `items()` ile dolaşma, `sorted` ile sıralama ve `|` ile birleştirme. Kopyalamayı ve özetlenebilir anahtarları akılda tutun; Python 3.15'te değiştirilemeyen ayarlar için `frozendict` kullanın. Sözlükler, listeler, demetler ve kümeler "Python 3.15: sıfırdan uzmanlığa" kursunda harcama takipçisi örneğiyle uygulamalı olarak işlenir.

## FAQ

**Bir sözlükte farklı türde değerler tutabilir miyim?**

Evet, değerler aynı sözlükte bile farklı türde olabilir: sayılar, metinler, listeler, başka sözlükler. Kısıtlama yalnızca anahtarlar için geçerlidir; özetlenebilir olmak zorundadırlar.

**Bir sözlükte kaç eleman olduğunu nasıl öğrenirim?**

len(d) çift sayısını verir. Boş bir sözlük için 0 döner ve boş sözlük if koşulunda yanlış sayılır.

**dict ile defaultdict arasındaki fark nedir?**

defaultdict, dict'in bir alt sınıfıdır; var olmayan bir anahtara erişildiğinde KeyError vermek yerine int ya da list gibi bir fabrikayla değer üretir. Diğer davranışları aynıdır.

**Değere göre anahtarı nasıl bulurum?**

Doğrudan bir metot yoktur; döngü gerekir: next((k for k, v in d.items() if v == value), None). Bu sık yapılıyorsa ters bir sözlük kurun: {v: k for k, v in d.items()}.

**Bir sözlüğü dosyaya nasıl kaydederim?**

Genellikle json modülüyle: yazma modunda açılmış dosyaya json.dump(d, f, ensure_ascii=False, indent=2), okumak için json.load(f). Anahtarlar bu durumda metne dönüşür.


---
Source: Skillaria.Top (https://skillaria.top)
