Dict ו-File ב-Python

טבלת גיבוב (hash) של הכתבה

המבנה היעיל של טבלת גיבוב (hash) של מפתח/ערך ב-Python נקרא הכתבה. את התוכן של הכתבה ניתן לכתוב כסדרה של צמדי מפתח/ערך בתוך סוגריים מסולסלים { }, לדוגמה. הכתבה = {key1:value1, key2:value2, ... }. " חנות ריקה" היא רק זוג ריק של סוגריים מסולסלים {}.

כדי לחפש או להגדיר ערך ב-הכתבה משתמשים בסוגריים מרובעים. לדוגמה, הכתבה ['foo'] מחפשת את הערך שמתחת למפתח 'foo'. מחרוזות, מספרים ושילובים משמשים כמפתחות, וכל טיפוס יכול להיות ערך. סוגים אחרים עשויים לפעול או לא לפעול כראוי כמפתחות (מחרוזות והצמדות פועלים בצורה נקייה כי הם לא ניתנים לשינוי). חיפוש ערך שאינו ב-הכתבה גורם ל-KeyError – משתמשים ב-'in' כדי לבדוק אם המפתח נמצא ב-הכתבה, או משתמשים ב-edit.get(key) שמחזיר את הערך או ב-None אם המפתח לא קיים (או get(key, not-found) מאפשר לכם לציין את הערך שיוחזר במקרה שלא נמצא).

  ## Can build up a dict by starting with the empty dict {}
  ## and storing key/value pairs into the dict like this:
  ## dict[key] = value-for-that-key
  dict = {}
  dict['a'] = 'alpha'
  dict['g'] = 'gamma'
  dict['o'] = 'omega'

  print(dict) ## {'a': 'alpha', 'o': 'omega', 'g': 'gamma'}

  print(dict['a'])     ## Simple lookup, returns 'alpha'
  dict['a'] = 6       ## Put new key/value into dict
  'a' in dict         ## True
  ## print(dict['z'])                  ## Throws KeyError
  if 'z' in dict: print(dict['z'])     ## Avoid KeyError
  print(dict.get('z'))  ## None (instead of KeyError)

הכתבה באמצעות המקשים 'a' 'o' 'g'

כברירת מחדל, לולאת A במילון חוזרת על המפתחות שלה. המפתחות יופיעו בסדר שרירותי. השיטות dict.keys() ו-edit.values() מחזירות רשימות של המפתחות או הערכים באופן מפורש. יש גם תכונת items() שמחזירה רשימה של צמדים (מפתח, ערך) – זו הדרך היעילה ביותר לבחון את כל נתוני הערכים של המפתח במילון. אפשר להעביר את כל הרשימות האלה לפונקציה sorted() .

  ## By default, iterating over a dict iterates over its keys.
  ## Note that the keys are in a random order.
  for key in dict:
    print(key)
  ## prints a g o

  ## Exactly the same as above
  for key in dict.keys():
    print(key)

  ## Get the .keys() list:
  print(dict.keys())  ## dict_keys(['a', 'o', 'g'])

  ## Likewise, there's a .values() list of values
  print(dict.values())  ## dict_values(['alpha', 'omega', 'gamma'])

  ## Common case -- loop over the keys in sorted order,
  ## accessing each key/value
  for key in sorted(dict.keys()):
    print(key, dict[key])

  ## .items() is the dict expressed as (key, value) tuples
  print(dict.items())  ##  dict_items([('a', 'alpha'), ('o', 'omega'), ('g', 'gamma')])

  ## This loop syntax accesses the whole dict by looping
  ## over the .items() tuple list, accessing one (key, value)
  ## pair on each iteration.
  for k, v in dict.items(): print(k, '>', v)
  ## a > alpha    o > omega     g > gamma

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

עיצוב הכתבה

האופרטור % פועל בצורה נוחה כדי להחליף ערכים מ-הכתבה במחרוזת לפי שם:

  h = {}
  h['word'] = 'garfield'
  h['count'] = 42
  s = 'I want %(count)d copies of %(word)s' % h  # %d for int, %s for string
  # 'I want 42 copies of garfield'

  # You can also use str.format().
  s = 'I want {count:d} copies of {word}'.format(h)

Del

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

  var = 6
  del var  # var no more!

  list = ['a', 'b', 'c', 'd']
  del list[0]     ## Delete first element
  del list[-2:]   ## Delete last two elements
  print(list)      ## ['b']

  dict = {'a':1, 'b':2, 'c':3}
  del dict['b']   ## Delete 'b' entry
  print(dict)      ## {'a':1, 'c':3}

Files

הפונקציה open() נפתחת ומחזירה כינוי לקובץ שיכול לשמש לקריאה או לכתיבה של קובץ בדרך הרגילה. הקוד f = open('name', 'r') פותח את הקובץ במשתנה f, מוכן לפעולות קריאה, ובסיום יש להשתמש ב-f.close(). במקום 'י', צריך להשתמש ב-'w' לכתיבה וב-'a' לצירוף. התקן של לולאה פועל בקובצי טקסט תוך חזרה על שורות הקובץ (פועל רק בקובצי טקסט, לא בקבצים בינאריים). שיטת הלולאה (for-loop) היא דרך פשוטה ויעילה להסתכל על כל השורות בקובץ טקסט:

  # Echo the contents of a text file
  f = open('foo.txt', 'rt', encoding='utf-8')
  for line in f:   ## iterates over the lines of the file
    print(line, end='')    ## end='' so print does not add an end-of-line char
                           ## since 'line' already includes the end-of-line.
  f.close()

קריאה של שורה אחת בכל פעם היא איכות נחמדה שלא כל הקובץ צריך להתאים לזיכרון בו-זמנית - שימושי אם רוצים לעיין בכל שורה בקובץ בגודל 10 ג'יגה-בייט בלי להשתמש ב-10 ג'יגה-בייט של זיכרון. השיטה f.readlines() קוראת את הקובץ כולו לזיכרון ומחזירה את התוכן שלו כרשימה של השורות שבו. השיטה f.read() קוראת את כל הקובץ למחרוזת אחת, כך שזו דרך נוחה להתמודד עם כל הטקסט, כמו למשל בביטויים רגולריים שנראה בהמשך.

לכתיבה, שיטת f.write(string) היא הדרך הקלה ביותר לכתוב נתונים בקובץ פלט פתוח. לחלופין, אפשר להשתמש באפשרות 'print' עם קובץ פתוח כמו 'print(string, file=f)'.

קבצים בפורמט Unicode

כדי לקרוא ולכתוב קבצים בקידוד Unicode, משתמשים במצב't' ומציינים במפורש את הקידוד:


with open('foo.txt', 'rt', encoding='utf-8') as f:
  for line in f:
    # here line is a *unicode* string

with open('write_test', encoding='utf-8', mode='wt') as f:
    f.write('\u20ACunicode\u20AC\n') #  €unicode€
    # AKA print('\u20ACunicode\u20AC', file=f)  ## which auto-adds end='\n'

התפתחות מצטברת בפעילות הגופנית

פיתוח תוכנית Python, אל תכתבו את כולו בשלב אחד. במקום זאת, מזהים רק אבן דרך ראשונה, למשל "השלב הראשון הוא לחלץ את רשימת המילים". כתוב את הקוד כדי להגיע לאבן הדרך הזו, ופשוט הדפיסו את מבני הנתונים שלך בנקודה הזו, ולאחר מכן תוכל לבצע sys.exit(0) כדי שהתוכנית לא תתרחש בחלקים שלא בוצעו. לאחר שקוד אבן הדרך יפעל, תוכלו לעבוד על הקוד לאבן הדרך הבאה. היכולת לבחון את תדפיסי המשתנים במצב אחד יכולה לעזור לכם לחשוב איך צריך להמיר את המשתנים האלה כדי להגיע למצב הבא. Python פועל מהר מאוד עם הדפוס הזה, ולכן הוא מאפשר לבצע שינוי קטן ולהריץ את התוכנה כדי לראות איך היא פועלת. תוכלו לנצל את הזמן הזה כדי לבנות את התוכנית בשלבים ספורים.

תרגיל: wordcount.py

שילוב כל החומר הבסיסי של Python -- מחרוזות, רשימות, ניקוד, tuples, קבצים -- נסה את תרגיל הסיכום wordcount.py בתרגילים הבסיסיים.