מירי
כיתה י · מבני נתונים ואלגוריתמים

מילונים בפייתון מפתח וערך

ברשימה מוצאים ערך לפי המקום שלו: 0, 1, 2. במילון מוצאים ערך לפי שם: כמה תפוחים יש במלאי? מה הציון של "math"? כאן יוצרים dict, מוסיפים ומעדכנים מפתחות, עוברים עליו בלולאה וסופרים מופעים של אותיות ומילים. כדאי להכיר קודם רשימות ומחרוזות. בהמשך משתמשים במילונים גם ברשימה דו-ממדית ובסיבוכיות.

1

הרעיון

מילון הוא אוסף של זוגות: מפתח וערך. כמו בספר טלפונים: מחפשים לפי השם ומקבלים את המספר. המפתחות לא חוזרים על עצמם, ולכל מפתח יש ערך אחד.

stock = {"apple": 3, "pear": 1}
print(stock["apple"])     # 3
stock["kiwi"] = 5         # new key
stock["apple"] = 4        # change a value
print(stock)              # {'apple': 4, 'pear': 1, 'kiwi': 5}

קוראים ומשנים

d[key] מחזיר את הערך. d[key] = value מוסיף מפתח חדש, או מחליף ערך של מפתח שכבר קיים. d.update(other) מוסיף כמה זוגות בבת אחת.

בודקים בזהירות

מפתח שלא קיים גורם לשגיאה KeyError. לכן בודקים קודם עם key in d, או משתמשים ב-d.get(key, 0), שמחזיר 0 כשהמפתח חסר.

עוברים בלולאה

for k in d עובר על המפתחות. for k, v in d.items() עובר על הזוגות. len(d) הוא מספר המפתחות.

לזכור: לספירת מופעים יש שורה אחת שכדאי לזכור: counts[x] = counts.get(x, 0) + 1. בפעם הראשונה get נותן 0, ובכל פעם נוספת מוסיפים 1.
2

מעבדה: מלאי של דוכן פירות

בדוכן יש 3 תפוחים ואגס אחד. בחרו במחוונים איזה פרי מגיע ובאיזו כמות. אם הפרי כבר במילון, התוכנית מעדכנת אותו. אם לא, היא מוסיפה מפתח חדש. לחצו "שורה הבאה" ועקבו אחרי המילון.

נסו את אלה:

המילון stock בשלב הנוכחי:

הריצו בעצמכם

אפשר לשנות את הקוד ולהריץ פייתון אמיתי. בפעם הראשונה הטעינה לוקחת כמה שניות.

3

טעויות שכולם עושים

מפתח שלא קיים

קריאה של מפתח חסר עוצרת את התוכנית עם KeyError. get מחזיר ערך ברירת מחדל במקום.

✗ KeyError: 'plum'
stock = {"apple": 3}
print(stock["plum"])
✓ מדפיס 0
stock = {"apple": 3}
print(stock.get("plum", 0))

במילון אין מקום 0

מילון לא ממוספר כמו רשימה. d[0] מחפש מפתח שהוא המספר 0, ולא "הראשון".

✗ KeyError: 0
grades = {"math": 90, "art": 85}
print(grades[0])
✓ מדפיס 90
grades = {"math": 90, "art": 85}
print(grades["math"])

in בודק מפתחות, לא ערכים

in על מילון שואל רק על המפתחות. כדי לחפש ערך, שואלים את d.values().

✗ False
ages = {"cat": 4, "dog": 7}
print(7 in ages)
✓ True
ages = {"cat": 4, "dog": 7}
print(7 in ages.values())

אותו מפתח פעמיים

מפתח מופיע במילון פעם אחת בלבד. השמה שנייה לאותו מפתח מחליפה את הערך, לא מוסיפה זוג.

✗ "יש 2 זוגות"
d = {"a": 1}
d["a"] = 5
print(len(d))      # 1, not 2
✓ סופרים בלי למחוק
d = {"a": 1}
d["a"] = d["a"] + 5
print(d)           # {'a': 6}

לולאה על מילון נותנת מפתחות

for x in d נותן רק מפתחות. כדי לקבל גם ערך, משתמשים ב-items().

✗ רק apple, pear
for x in stock:
    print(x)
✓ apple 3, pear 1
for k, v in stock.items():
    print(k, v)
4

דוגמה פתורה: סופרים אותיות

כמה פעמים מופיעה כל אות במילה banana? עוברים על האותיות אחת אחת, ולכל אות מוסיפים 1 במילון. אות שעוד לא ראינו מתחילה מ-0 בזכות get.

המילון counts בשלב הנוכחי:

5

תרגול

6

שאלות שכולם שואלים

מתי משתמשים במילון ומתי ברשימה?

רשימה מתאימה לסדר: תור, ציונים לפי סדר המבחנים. מילון מתאים לחיפוש לפי שם: מלאי לפי מוצר, ציון לפי מקצוע, מספר מופעים לפי מילה. חיפוש במילון לפי מפתח מהיר מאוד, גם כשיש בו מיליון זוגות. נסו במעבדה.

מה ההבדל בין d[key] לבין d.get(key)?

כשהמפתח קיים, שניהם מחזירים את אותו ערך. כשהוא חסר, d[key] עוצר עם KeyError, ו-d.get(key) מחזיר None. עם d.get(key, 0) מקבלים 0, וזה נוח במיוחד לספירה.

מה יכול להיות מפתח במילון?

מחרוזת, מספר או אמת ושקר. רשימה לא יכולה להיות מפתח, כי אפשר לשנות אותה. ערך, לעומת זאת, יכול להיות כל דבר: גם רשימה או מילון אחר. תרגלו למטה.