# 8 mistakes almost every beginner makes with dicts.
# Wrong way, error, right way — all in one file.
# redhorndev.com

# ─────────────────────────────────────────────
# 1. KeyError — key doesn't exist
# ─────────────────────────────────────────────

soldier = {"name": "Raven", "score": 85}
# print(soldier["rank"])            # KeyError: 'rank'

print(soldier.get("rank", "unassigned"))    # CORRECT — unassigned

if "rank" in soldier:               # CORRECT — check first
    print(soldier["rank"])

# ─────────────────────────────────────────────
# 2. Capturing None from a modifying method
# ─────────────────────────────────────────────

soldier = {"name": "Raven"}
soldier = soldier.update({"score": 85})     # WRONG
print(soldier)                              # None

soldier = {"name": "Raven"}
soldier.update({"score": 85})               # CORRECT
print(soldier)                              # {'name': 'Raven', 'score': 85}

# same applies to: clear(), setdefault()

# ─────────────────────────────────────────────
# 3. Assignment is not a copy
# ─────────────────────────────────────────────

original = {"name": "Raven", "score": 85}
backup = original                   # WRONG — same dict, two names
backup["score"] = 99
print(original)                     # {'name': 'Raven', 'score': 99} — changed too

original = {"name": "Raven", "score": 85}
backup = original.copy()            # CORRECT — independent copy
backup["score"] = 99
print(original)                     # {'name': 'Raven', 'score': 85}
print(backup)                       # {'name': 'Raven', 'score': 99}

# ─────────────────────────────────────────────
# 4. in checks keys — not values
# ─────────────────────────────────────────────

soldier = {"name": "Raven", "score": 85}
print(85 in soldier)                # False — 85 is a value, not a key
print(85 in soldier.values())       # True  — CORRECT

print("name" in soldier)            # True  — "name" is a key

# ─────────────────────────────────────────────
# 5. Duplicate keys — last one wins
# ─────────────────────────────────────────────

soldier = {"name": "Raven", "score": 85, "name": "Wolf"}   # WRONG
print(soldier)                      # {'name': 'Wolf', 'score': 85}
                                    # "Raven" is gone — no error, no warning

# ─────────────────────────────────────────────
# 6. Modifying a dict while looping over it
# ─────────────────────────────────────────────

scores = {"Raven": 85, "Wolf": 74, "Ghost": 91}
# for name in scores:
#     if scores[name] < 80:
#         del scores[name]          # RuntimeError: dictionary changed size during iteration

passing = {}                        # CORRECT — build a new dict
for name, score in scores.items():
    if score >= 80:
        passing[name] = score
print(passing)                      # {'Raven': 85, 'Ghost': 91}

# ─────────────────────────────────────────────
# 7. pop() without a default
# ─────────────────────────────────────────────

soldier = {"name": "Raven", "score": 85}
# soldier.pop("rank")               # KeyError: 'rank'

soldier.pop("rank", None)           # CORRECT — no error
soldier.pop("rank", "not found")    # CORRECT — returns "not found"

# ─────────────────────────────────────────────
# 8. {} is a dict — not a set
# ─────────────────────────────────────────────

empty = {}
print(type(empty))                  # <class 'dict'>

empty_set = set()
print(type(empty_set))              # <class 'set'>

# ─────────────────────────────────────────────
# Quick reference
# ─────────────────────────────────────────────

# d["key"]              → KeyError if missing — use get() or check with in
# d = d.update(...)     → None — don't assign modifying methods
# backup = d            → same dict — use d.copy()
# x in d                → checks keys only — use x in d.values() for values
# {"k": 1, "k": 2}     → last value wins, no error
# del d[k] in for loop  → RuntimeError — build new dict instead
# d.pop("k")            → KeyError if missing — use d.pop("k", default)
# {}                    → empty dict — use set() for empty set
