רשימה, כשמה כן היא, מייצגת אוסף מסודר של ערכים. רשימות יהיו סוג הנתונים הראשון שנכיר בפייתון, שמטרתו היא לקבץ ערכים.
הרעיון מוכר לנו מהיום־יום: רשימת פריטים לקנייה בסופר שמסודרת לפי הא–ב, או רשימת ההופעות בקיץ הקרוב המסודרת לפי תאריך.
נסו לדמיין רשימה כמסדרון ארוך, שבו עומדים בתור אחד אחרי השני איברים מסוגים שאנחנו מכירים בפייתון.
אם נשתמש בדימוי הלייזרים שנתנו למשתנים בשבוע הקודם, אפשר להגיד שמדובר בלייזר שמצביע לשורת לייזרים, שבה כל לייזר מצביע על ערך כלשהו.
0 | 1 | 2 | 3 | 4 | 5 |
"David Ben-Gurion" | "Moshe Sharett" | "David Ben-Gurion" | "Levi Eshkol" | "Yigal Alon" | "Golda Meir" |
-6 | -5 | -4 | -3 | -2 | -1 |
דוגמה לרשימה: 6 ראשי הממשלה הראשונים בישראל לפי סדר כהונתם, משמאל לימין
תרגול:
הרשימות שהוצגו למעלה הן רשימות הומוגניות, כאלו שכל האיברים שבהן הם מאותו סוג.
כתבו עבור כל אחת מהרשימות שהוצגו בדוגמה מה סוג הנתונים שיישמר בהן.
תרגול: נסו לתת דוגמה לעוד 3 רשימות שבהן נתקלתם לאחרונה.
רשימות הן אחד מסוגי הנתונים הכיפיים ביותר בפייתון, וזאת בזכות הגמישות האדירה שיש לנו בתכנות עם רשימות.
נגדיר בעזרת פייתון את הרשימה שפגשנו למעלה – 6 ראשי הממשלה הראשונים מאז קום המדינה:
In [ ]:
prime_ministers = ['David Ben-Gurion', 'Moshe Sharett', 'David Ben-Gurion', 'Levi Eshkol', 'Yigal Alon', 'Golda Meir']
מה התרחש בקוד?
התחלנו את הגדרת הרשימה באמצעות התו [
.
מייד אחרי התו הזה הכנסנו איברים לרשימה לפי הסדר הרצוי, כאשר כל איבר מופרד ממשנהו בפסיק (,
).
במקרה שלנו, כל איבר הוא מחרוזת המייצגת ראש ממשלה. הכנסנו את ראשי הממשלה לרשימה לפי סדר כהונתם.
שימו לב שהרשימה מכילה איבר מסוים פעמיים – מכאן שרשימה היא מבנה נתונים שתומך בחזרות.
לסיום, נסגור את הגדרת הרשימה באמצעות התו ]
.
In [ ]:
print(prime_ministers)
In [ ]:
type(prime_ministers)
נוכל להגדיר רשימה של המספרים הטבעיים עד 7:
In [ ]:
numbers = [1, 2, 3, 4, 5, 6, 7]
רשימה הומוגנית היא רשימה שבה האיברים שנמצאים בכל אחד מהתאים הם מאותו סוג. רשימות "בעולם האמיתי" הן בדרך כלל הומוגניות.
רשימה הטרוגנית היא רשימה שבה איברים בתאים שונים יכולים להיות מסוגים שונים.
ההבדל הוא סמנטי בלבד, ופייתון לא מבדילה בין רשימה הטרוגנית לרשימה הומוגנית.
לשם הדוגמה, נגדיר רשימה הטרוגנית:
In [ ]:
wtf = ['The cake is a', False, 42]
נוכל אפילו להגדיר רשימה ריקה, שבה אין איברים כלל:
In [ ]:
empty_list = []
לכל תא ברשימה יש מספר, שמאפשר לנו להתייחס לאיבר שנמצא באותו תא.
הדבר דומה ללייזר שעליו יש מדבקת שם ("שמות ראשי ממשלה"), והוא מצביע על שורת לייזרים שעל התווית שלהם מופיע מספר המתאר את מיקומם בשורה.
התא השמאלי ביותר ברשימה ממוספר כ־0, התא שנמצא אחריו (מימינו) מקבל את המספר 1, וכך הלאה עד לסוף הרשימה.
המספור של כל תא נקרא המיקום שלו ברשימה, או האינדקס שלו.
נגדיר את רשימת שמות התקליטים שיש לי בבית:
In [ ]:
# Index 0 1 2 3 4 5
vinyls = ['Ecliptica', 'GoT Season 6', 'Lone Digger', 'Everything goes numb', 'Awesome Mix Vol. 1', 'Ultimate Sinatra']
בהנחה שאנחנו מתים על Guardians of the Galaxy, נוכל לנסות להשיג מהרשימה את Awesome Mix Vol. 1.
כדי לעשות זאת, נציין את שם הרשימה שממנה אנחנו רוצים לקבל את האיבר, ומייד לאחר מכן את מיקומו ברשימה בסוגריים מרובעים.
In [ ]:
print(vinyls[4])
התא הראשון ממוספר 0, ולא 1.
יש לכך סיבות טובות, אבל פעמים רבות תרגישו שהמספור הזה לא טבעי ועלול ליצור באגים, שהם קטעי קוד שמתנהגים אחרת משציפה המתכנת.
כפועל יוצא, המיקום ברשימה של התא האחרון לא יהיה כאורך הרשימה, אלא כאורך הרשימה פחות אחד.
משמע: ברשימה שבה 3 איברים, מספרו של התא האחרון יהיה 2.
כפי שניתן לראות בתמונה, פייתון מנסה לעזור לנו ומאפשרת לנו לגשת לאיברים גם מהסוף.
חוץ מהמספור הרגיל שראינו קודם, אפשר לגשת לאיברים מימין לשמאל באמצעות מספור שלילי.
האיבר האחרון יקבל את המספר -1, זה שלפניו (משמאלו) יקבל -2 וכן הלאה.
In [ ]:
# 0 1 2 3 4 5
vinyls = ['Ecliptica', 'GoT Season 6', 'Lone Digger', 'Everything goes number', 'Awesome Mix Vol. 1', 'Ultimate Sinatra']
# -6 -5 -4 -3 -2 -1
אם נרצה לגשת שוב לאותו דיסק, אבל הפעם מהסוף, נוכל לכתוב זאת כך:
In [ ]:
print(vinyls[-2])
כדאי לזכור שהתוכן של כל אחד מהתאים הוא ערך לכל דבר.
יש לו סוג, ואפשר לבצע עליו פעולות כמו שלמדנו עד עכשיו:
In [ ]:
type(vinyls[0])
In [ ]:
print(vinyls[0] + ', By Sonata Arctica')
לסיום, נראה שבדיוק כמו במחרוזות, נוכל לבדוק את אורך הרשימה על ידי שימוש בפונקציה len
.
In [ ]:
# כמה תקליטים יש לי?
len(vinyls)
אם ננסה לגשת לתא שאינו קיים, נקבל IndexError
.
זה בדרך כלל קורה כשאנחנו שוכחים להתחיל לספור מ־0.
אם השגיאה הזו מופיעה כשאתם מתעסקים עם רשימות, חשבו איפה בקוד פניתם לתא שאינו קיים.
לפעמים נרצה לשנות את הערך של האיברים ברשימה.
נפנה ללייזר מסוים בשורת הלייזרים שלנו, ונבקש ממנו להצביע לערך חדש:
In [ ]:
print(vinyls)
vinyls[1] = 'GoT Season 7'
print(vinyls)
אופרטורים שהכרנו כשלמדנו על מחרוזות, יעבדו נהדר גם על רשימות.
כפי ש־+
משרשר בין מחרוזות, הוא יודע לשרשר גם בין רשימות:
In [ ]:
[1, 2, 3] + [4, 5, 6]
In [ ]:
['a', 'b', 'c'] + ['easy', 'as'] + [1, 2, 3]
וכפי ש־*
משרשר מחרוזת לעצמה כמות מסוימת של פעמים, כך הוא יפעל גם עם רשימות:
In [ ]:
['wake up', 'go to school', 'sleep'] * 365
אפשר גם לשלב:
In [ ]:
['Is', 'someone', 'getting'] + ['the', 'best,'] * 4 + ['of', 'you?']
שימו לב שכל אופרטור שתשימו ליד הרשימה מתייחס לרשימה בלבד, ולא לאיברים שבתוכה.
משמע + 5
לא יוסיף לכם 5 לכל אחד מהאיברים, אלא ייכשל כיוון שפייתון לא יודעת לחבר רשימה למספר שלם.
In [ ]:
[1, 2, 3] + 5
שימו לב גם שהפעלת אופרטור על רשימה לא גורמת לשינוי הרשימה, אלא רק מחזירה ערך.
כדי לשנות ממש את הרשימה, נצטרך להשתמש בהשמה:
In [ ]:
prime_ministers = ['David Ben-Gurion', 'Moshe Sharett', 'David Ben-Gurion', 'Levi Eshkol', 'Yigal Alon', 'Golda Meir']
In [ ]:
print(prime_ministers)
prime_ministers + ['Yitzhak Rabin']
print(prime_ministers)
In [ ]:
print(prime_ministers)
prime_ministers = prime_ministers + ['Yitzhak Rabin']
print(prime_ministers)
נגדיר את רשימת האנשים שנכחו בכיתה ביום ראשון, שני, שלישי ורביעי:
In [ ]:
pupils_in_sunday = ['Moshe', 'Dukasit', 'Michelangelo']
pupils_in_monday = ['Moshe', 'Dukasit', 'Master Splinter']
pupils_in_tuesday = ['Moshe', 'Dukasit', 'Michelangelo']
pupils_in_wednesday = ['Moshe', 'Dukasit', 'Michelangelo', 'Master Splinter']
רשימות תומכות בכל אופרטורי ההשוואה שלמדנו עד כה.
נתחיל בקל ביותר. בואו נבדוק באיזה יום הרכב התלמידים בכיתה היה זהה להרכב התלמידים שהיה בה ביום ראשון:
In [ ]:
print("Is it Monday? " + str(pupils_in_sunday == pupils_in_monday))
print("Is it Tuesday? " + str(pupils_in_sunday == pupils_in_tuesday))
print("Is it Wednesday? " + str(pupils_in_sunday == pupils_in_wednesday))
האם משה נכח בכיתה ביום שלישי?
In [ ]:
print('Moshe' in pupils_in_tuesday)
# זה אותו דבר כמו:
print('Moshe' in ['Moshe', 'Dukasit', 'Michelangelo'])
נוכיח שמאסטר ספלינטר הבריז באותו יום:
In [ ]:
'Master Splinter' not in pupils_in_tuesday
ולסיום, בואו נבדוק איזו גרסה חדשה יותר:
In [ ]:
python_new_version = [3, 7, 2]
python_old_version = [2, 7, 16]
print(python_new_version > python_old_version)
כדי לבצע השוואה בין רשימות, פייתון מנסה להשוות את האיבר הראשון מהרשימה הראשונה לאיבר הראשון מהרשימה השנייה.
אם יש "תיקו", היא תעבור לאיבר השני בכל רשימה, כך עד סוף הרשימה.
לעיתים דברים בחיים האמיתיים הם מורכבים מדי מכדי לייצג אותם ברשימה סטנדרטית.
הרבה פעמים נשים לב שיוקל לנו אם ניצור רשימה שבה כל תא הוא רשימה בפני עצמו.
הרעיון הזה ייצור לנו רשימה של רשימות.
ניקח לדוגמה את הרשימות שהגדרנו למעלה, שמתארות מי נכח בכל יום בכיתה:
In [ ]:
pupils_in_sunday = ['Moshe', 'Dukasit', 'Michelangelo']
pupils_in_monday = ['Moshe', 'Dukasit', 'Splinter']
pupils_in_tuesday = ['Moshe', 'Dukasit', 'Michelangelo']
pupils_in_wednesday = ['Moshe', 'Dukasit', 'Michelangelo', 'Splinter']
אנחנו רואים לפנינו רשימה של ימים, שקל להכניס לרשימה אחת גדולה:
In [ ]:
pupils = [pupils_in_sunday, pupils_in_monday, pupils_in_tuesday, pupils_in_wednesday]
print(pupils)
0 | 1 | 2 | 3 | |||||||||||||||||||||||||||||||||||||||
|
|
|
|
|||||||||||||||||||||||||||||||||||||||
-4 | -3 | -2 | -1 |
דוגמה לרשימה של רשימות: נוכחות התלמידים בימי ראשון עד רביעי
השורה שכתבנו למעלה זהה לחלוטין לשורה הבאה, שבה אנחנו מגדירים רשימה אחת שכוללת את רשימות התלמידים שנכחו בכיתה בכל יום.
In [ ]:
pupils = [['Moshe', 'Dukasit', 'Michelangelo'], ['Moshe', 'Dukasit', 'Splinter'], ['Moshe', 'Dukasit', 'Michelangelo'], ['Moshe', 'Dukasit', 'Michelangelo', 'Splinter']]
נוכל לקבל את רשימת התלמידים שנכחו ביום ראשון בצורה הבאה:
In [ ]:
pupils[0]
ואת התלמיד האחרון שנכח ביום ראשון בצורה הבאה:
In [ ]:
pupils_in_sunday = pupils[0]
print(pupils_in_sunday[-1])
# או פשוט:
print(pupils[0][-1])
אם קשה לכם לדמיין את זה, עשו זאת בשלבים.
בדקו מה יש ב־pupils
, אחרי זה מה מחזיר pupils[0]
, ואז נסו לקחת ממנו את האיבר האחרון, pupils[0][-1]
.
</p
כדי להבין טוב יותר איך רשימה של רשימות מתנהגת, חשוב להבין את התוצאות של הביטויים הבוליאניים הבאים.
זה קצת מבלבל, אבל אני סומך עליכם שתחזיקו מעמד:
In [ ]:
print("pupils = " + str(pupils))
print("-" * 50)
print("1. 'Moshe' in pupils == " + str('Moshe' in pupils))
print("2. 'Moshe' in pupils[0] == " + str('Moshe' in pupils[0]))
print("3. ['Moshe', 'Splinter'] in pupils == " + str(['Moshe', 'Splinter'] in pupils))
print("4. ['Moshe', 'Splinter'] in pupils[0] == " + str(['Moshe', 'Splinter'] in pupils[-1]))
print("5. ['Moshe', 'Dukasit', 'Splinter'] in pupils == " + str(['Moshe', 'Dukasit', 'Splinter'] in pupils))
print("6. ['Moshe', 'Dukasit', 'Splinter'] in pupils[0] == " + str(['Moshe', 'Dukasit', 'Splinter'] in pupils[0]))
['Moshe', 'Splinter']
.["Moshe", "Splinter"]
.
זכרו שעבור פייתון אין שום דבר מיוחד ברשימה של רשימות. היא בסך הכול רשימה רגילה, שכל אחד מאיבריה הוא רשימה.
מבחינתה אין הבדל בין רשימה כזו לכל רשימה אחרת.
באתרי אינטרנט ובתיעוד של פייתון אנחנו נפגש פעמים רבות עם המילה Iterable.
בקורס נשתמש במונח הזה פעמים רבות כדי להבין טוב יותר איך פייתון מתנהגת.
נגדיר ערך כ־iterable אם ניתן לפרק אותו לכלל האיברים שלו.
עד כה אנחנו מכירים 2 סוגי משתנים שעונים להגדרה iterables: רשימות ומחרוזות.
ניתן לפרק רשימה לכל האיברים שמרכיבים אותה, וניתן לפרק מחרוזת לכל התווים שמרכיבים אותה.
יש הרבה במשותף לכל הדברים שניתן להגיד עליהם שהם iterables:
על חלק גדול מה־iterables אפשר להפעיל פעולות שמתייחסות לכלל האיברים שבהם, כמו len
שמראה את מספר האיברים בערך.
על חלק גדול מה־iterables יהיה אפשר גם להשתמש בסוגריים מרובעים כדי לגשת לאיבר מסוים שנמצא בהם.
בעתיד נלמד על עוד דברים שמשותפים לרוב (או לכל) ה־iterables.
כתבו קוד שיסדר את רשימת נשיאי בית המשפט לפי סדר אלפבתי.
זה אכן אמור להיות מסורבל מאוד. בעתיד נלמד לכתוב קוד מוצלח יותר לבעיה הזו.
השתמשו באינדקסים, ושמרו ערכים בצד במשתנים.
In [ ]:
judges = ['Esther Hayut', 'Miriam Naor', 'Asher Grunis', 'Dorit Beinisch', 'Aharon Barak']
בונוס: כתבו קטע קוד שבודק שהרשימה (שמכילה 5 איברים) אכן מסודרת.
לפניכם רשימה של שמות טעמי גלידה שנמצאים בדוכן הגלידה השכונתי.
קבלו מהמשתמש קיפיק את הטעם האהוב עליו, והדפיסו למשתמש האם הטעם שלו נמכר בדוכן.
In [ ]:
ice_cream_flavours = ['chocolate', 'vanilla', 'pistachio', 'banana']
לפניכם כמה ביטויים.
רשמו לעצמכם מה תהיה תוצאת כל ביטוי, ורק אז הריצו אותו.
In [ ]:
rabanim = ['Rashi', 'Maimonides', 'Nachmanides', 'Rabbeinu Tam']
In [ ]:
'Rashi' in rabanim
In [ ]:
'RASHI' in rabanim
In [ ]:
['Rashi'] in rabanim
In [ ]:
['Rashi', 'Nachmanides'] in rabanim
In [ ]:
'Bruria' in rabanim
In [ ]:
rabanim + ['Gershom ben Judah']
'Gershom ben Judah' in rabanim
In [ ]:
'3' in [1, 2, 3]
In [ ]:
(1 + 5 - 3) in [1, 2, 3]
In [ ]:
[1, 5, 3] > [1, 2, 3]
In [ ]:
rabanim[0] in [rabanim[0] + rabanim[1]]
In [ ]:
rabanim[0] in [rabanim[0]] + [rabanim[1]]
In [ ]:
rabanim[-1] == rabanim[0] or rabanim[-1] == rabanim[1] or rabanim[-1] == rabanim[2] or rabanim[-1] == rabanim[3]
In [ ]:
rabanim[-1] == rabanim[0] or rabanim[-1] == rabanim[1] or rabanim[-1] == rabanim[2] and rabanim[-1] != rabanim[3]
In [ ]:
rabanim[-1] == rabanim[0] or rabanim[-1] == rabanim[1] or rabanim[-1] == rabanim[2] and rabanim[-1] == rabanim[3]
In [ ]:
1 in [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [ ]:
[1, 2, 3] in [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [ ]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][2]
In [ ]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][3]
In [ ]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][-1] * 5
In [ ]:
[[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][-1]] * 5
In [ ]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][-1]
In [ ]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]][0][-1] == [[7, 8, 9], [4, 5, 6], [1, 2, 3]][2][2]
In [ ]:
[[1, 2, 3]] in [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [ ]:
[[1, 2, 3], [4, 5, 6]] in [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
In [ ]:
[[1, 2, 3], [4, 5, 6]] in [[[1, 2, 3], [4, 5, 6]], [7, 8, 9]]