רשימות ב-Python

ב-Python יש סוג רשימה מובנה ונהדר שנקרא "list". הטקסטים של הרשימה נכתבים בתוך סוגריים מרובעים [ ]. הרשימות פועלות באופן דומה למחרוזות – צריך להשתמש בפונקציה len() ובסוגריים מרובעים [ ] כדי לגשת לנתונים, כשהרכיב הראשון באינדקס 0. (עיינו במסמכי הרשימה הרשמיים של python.org.)

  colors = ['red', 'blue', 'green']
  print(colors[0])    ## red
  print(colors[2])    ## green
  print(len(colors))  ## 3

רשימת מחרוזות 'אדום' 'כחול' 'ירוק'

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

  b = colors   ## Does not copy the list

גם הצבעים וגם b מצביעים על הרשימה האחת

הרשימה הריקה הוא רק זוג ריק של סוגריים [ ]. הסימן '+' עובדת על צירוף שתי רשימות, כך שאם תעשו את זה [1, 2] + [3, 4] תקבלו [1, 2, 3, 4] (בדיוק כמו + עם מחרוזות).

FOR ו-IN

המבנים *for* ו-*in* של Python הם שימושיים במיוחד, והשימוש הראשון בהם נראה באמצעות רשימות. המבנה *עבור* -- for var in list -- הוא דרך קלה להסתכל על כל רכיב ברשימה (או אוסף אחר). אין להוסיף או להסיר מהרשימה במהלך איטרציה.

  squares = [1, 4, 9, 16]
  sum = 0
  for num in squares:
    sum += num
  print(sum)  ## 30

אם אתם יודעים איזה סוג של דבר יש ברשימה, השתמשו בשם משתנה בלולאה שמתעד את המידע הזה, כמו 'num', 'שם' או 'url'. מאחר שלקוד Python אין תחביר אחר שמזכיר לכם סוגים שונים, שמות המשתנים הם אמצעי חשוב שעוזר לכם להבין בדיוק מה קורה. (זה קצת מטעה. ככל שאתם צוברים יותר חשיפה ל-python, רואים התייחסות להקליד רמזים שמאפשרים להוסיף הקלדה. מידע להגדרות הפונקציות. Python לא משתמש ברמזים מהסוג הזה בזמן הרצה בתוכניות שלכם. הם נמצאים בשימוש בתוכנות אחרות כמו סביבות פיתוח משולבות (IDE) בכלי ניתוח סטטיים, כמו איתור שגיאות בקוד (linters)/בודקי סוגים, כדי לוודא שהפונקציות נקראות עם ארגומנטים תואמים).

המבנה *in* בפני עצמו מאפשר לבדוק בקלות אם רכיב מופיע ברשימה (או באוסף אחר) – value in collection – בודק אם הערך נמצא באוסף, ומחזיר את הערך True/False.

  list = ['larry', 'curly', 'moe']
  if 'curly' in list:
    print('yay') ## yay

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

אפשר להשתמש גם בפונקציה 'for/in' כדי לעבוד על מחרוזת. המחרוזת משמשת כרשימה של התווים שלה, לכן for ch in s: print(ch) מדפיס את כל התווים במחרוזת.

טווח

הפונקציה range(n) מניבה את המספרים 0, 1, ... n-1 ו- range(a, b) מחזירה a, a+1, ... b-1 - עד למספר האחרון, אך לא כולל. השילוב של הפונקציה for-loop עם הפונקציה range() מאפשר ליצור לולאת <for> מסורתית:

  ## print the numbers from 0 through 99
  for i in range(100):
    print(i)

יש וריאנט xrange() שחוסך את העלויות של בניית הרשימה כולה למקרים תלויי ביצועים (ב-Python 3, פונקציית range() תתנהג בצורה טובה, ואפשר לשכוח מ-xrange() ).

בזמן לולאת

ב-Python יש גם את הלולאה הסטנדרטית, וההצהרות *break* ו-*continue* פועלות כמו ב-C++ וב-Java, והן משנות את המסלול של הלולאה הפנימית ביותר. לולאות ה-for/in שצוינו למעלה פותרות את המקרה הנפוץ של חזרה על כל רכיב ברשימה, אבל לולאת ה-time נותנת לכם שליטה מלאה על מספרי האינדקס. לפניכם לולאת זמן שנגישה לכל רכיב שלישי ברשימה:

  ## Access every 3rd element in a list
  i = 0
  while i < len(a):
    print(a[i])
    i = i + 3

הצגת רשימה של שיטות

לפניכם כמה שיטות נפוצות נוספות ליצירת רשימה.

  • list.append(elem) – מוסיף רכיב יחיד לסוף הרשימה. שגיאה נפוצה: לא החזרת הרשימה החדשה, אלא רק שינוי של הרשימה המקורית.
  • list.insert(index, elem) -- מכניס את הרכיב באינדקס הנתון, תוך העברת הרכיבים ימינה.
  • list.extend(list2) מוסיף את הרכיבים ברשימה 2 לסוף הרשימה. השימוש ב-+ או += ברשימה דומה לשימוש ב-expand().
  • list.index(elem) -- מחפש את הרכיב הנתון בתחילת הרשימה ומחזיר את האינדקס שלו. גורמת ל-ValueError אם הרכיב לא מופיע (יש להשתמש ב-"in" כדי לבדוק בלי ValueError).
  • list.remove(elem) – חיפוש המופע הראשון של הרכיב הנתון והסרתו (מבצע ValueError אם הוא לא קיים)
  • list.sort() -- ממיין את הרשימה במקום (לא מחזיר אותה). (עדיף להשתמש בפונקציה sorted() שמוצגת מאוחר יותר).
  • list.reverse() – הופכת את הרשימה הקיימת (לא מחזירה אותה)
  • list.pop(index) -- מסירה ומחזירה את הרכיב באינדקס הנתון. מחזירה את הרכיב הימני ביותר אם לא צוין אינדקס (בערך ההופכי של append() ).

שימו לב שאלו *methods* באובייקט רשימה, ואילו len() היא פונקציה שלוקחת את הרשימה (או מחרוזת או כל דבר אחר) כארגומנט.

  list = ['larry', 'curly', 'moe']
  list.append('shemp')         ## append elem at end
  list.insert(0, 'xxx')        ## insert elem at index 0
  list.extend(['yyy', 'zzz'])  ## add list of elems at end
  print(list)  ## ['xxx', 'larry', 'curly', 'moe', 'shemp', 'yyy', 'zzz']
  print(list.index('curly'))    ## 2

  list.remove('curly')         ## search and remove that element
  list.pop(1)                  ## removes and returns 'larry'
  print(list)  ## ['xxx', 'moe', 'shemp', 'yyy', 'zzz']

שגיאה נפוצה: שימו לב שהשיטות שלמעלה לא *מחזירות* את הרשימה ששונתה, אלא רק משנות את הרשימה המקורית.

  list = [1, 2, 3]
  print(list.append(4))   ## NO, does not work, append() returns None
  ## Correct pattern:
  list.append(4)
  print(list)  ## [1, 2, 3, 4]

יצירת רשימה

אחת הדפוסים הנפוצות היא להתחיל רשימה כרשימה הריקה [], ולאחר מכן להשתמש ב-append() או ב-expend() כדי להוסיף לה רכיבים:

  list = []          ## Start as the empty list
  list.append('a')   ## Use append() to add elements
  list.append('b')

הצגת רשימה של פלחים

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

  list = ['a', 'b', 'c', 'd']
  print(list[1:-1])   ## ['b', 'c']
  list[0:2] = 'z'    ## replace ['a', 'b'] with ['z']
  print(list)         ## ['z', 'c', 'd']

תרגיל: list1.py

כדי לתרגל את החומר בקטע הזה, אפשר לנסות את הבעיות ב-list1.py שלא משתמשות במיון (בתרגילים בסיסיים).