לולאות while

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

מה זה לולאה?

"לולאה" (loop) היא בלוק של קוד (תת תוכנית) שאנחנו מעוניינים שיתבצע שוב ושוב. בתחילת הלולאה חייב להופיע ביטוי כלשהו שמגדיר את התנאי לריצת הלולאה או את מספר הפעמים שנרצה שהיא תתבצע.

ניתן לחלק את הלולאות בפייתון לשני סוגים – לולאות תלויות ספירה (count controlled) ולולאות תלויות אירוע (event controlled). בלולאות תלויות ספירה, מספר הפעמים שהלולאה תתבצע מוגדר מראש ובדרך כלל אנחנו מגדירים את סוג הלולאות האלה באמצעות לולאות for, עליהן אסביר בפוסט הבא. הסוג השני, לולאות תלויות אירוע, מתייחס ללולאות המתבצעות כל עוד תנאי מסויים מתקיים. לולאות כאלה תמיד נגדיר באמצעות לולאות while, ובהן נתמקד בפוסט הזה.

לולאות while

המבנה של לולאת while מאוד פשוט וכשאנו כותבים לולאה כזאת אנחנו בעצם אומרים לפייתון, כל עוד (while) התנאי הבא מתקיים, בצע את תת התכנית הזאת.

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

בדוגמא הזאת ויתרתי על כתיבת הפלט מפני שהיא מייצרת לנו לולאה אין סופית – אם אתם מנסים להריץ את הקוד הזה בעצמכם, ראו הוזהרתם…

הסיבה שהדוגמה הזאת מייצרת תכנית שתוקעת לנו את המחשב היא שהגדרנו תנאי אשר תמיד מתקיים. בשורה הראשונה אנו מאתחלים משתנה בשם number למספר 1. הלולאה בודקת האם number קטן מ-11 והתשובה היא כמובן True. לכן הקוד שבתוך הלולאה מתבצע (הדפסת number). הבדיקה הבאה תניב את אותה התוצאה וגם זאת שאחריה וזאת שאחריה עד אין סוף פשוט כי 1 תמיד יהיה קטן מ-11 ואין שום פעולה שאנו נוקטים כדי לשנות את זה וכך אנחנו מקבלים זרם אין סופי של '1'.

שימוש במונה בלולאת while

כדי לתקן את הדוגמה הקודמת נוסיף שורה קטנה לקוד

עכשיו בכל איטרציה (ביצוע חוזר ) של הלולאה, המשתנה number גדל ב-1. בפוסט שעוסק במשתנים ראינו שאפשר לאתחל משתנה לחישוב על עצמו. במקרה הזה מדובר בערך המשתנה + 1 וכך אנחנו הופכים את number לסוג של מונה (counter) שלאט לאט מתקדם עד שהוא שווה ל-11. כשזה קורה התנאי כבר לא מתקיים ולכן הלולאה מפסיקה להתבצע – וכך קיבלנו 10 הדפסות בלבד.

באותה מידה היינו יכולים להתחיל מ-10 ו"לרדת" למטה ע"י הפחתה של אחד מהמונה בכל איטרציה. מכיוון שבתחילת כל לולאה אנחנו בודקים האם תנאי מתקיים, ניתן להוסיף אחרי הלולאה פסקת else שתתבצע כאשר התנאי יחדל להתקיים

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

ניתן לראות בשורה 5 את הכתיב המקוצר ואת התוצאה שלא הושפעה. כדי להשתמש בצורה המקוצרת, ראשית נכתוב את שם המשתנה, אחר כך את הפעולה שאנחנו מעוניינים לבצע עליו (חיבור, חיסור וכו') ולאחר מכן הסימן '=' (מסמל אתחול) ואת הערך שאנו מעוניינים להוסיף / להחסיר וכו'
בגלל שמדובר בכתיב מקוצר שגם קיים בשפות אחרות, הוא נחשב ליעיל יותר מבחינת נוחות כתיבה ולכן לא תיתקלו בצורה ה"מלאה" שכתבתי בשתי הדוגמאות הראשונות. כדי ליישר קו אשתמש בהמשך המדריך הזה רק בצורה המקוצרת.

בואו נבחן דוגמה נוספת המחשבת עצרת של המספר 10. מקובל לסמן עצרת באמצעות סימן קריאה (!) והתוצאה שלה על מספר מסוים היא מכפלת המספר בכל המספרים שקדמו לאותו מספר. לדוגמה, עצרת 3 תחזיר 1*2*3 = 6. הלולאה גם מציגה את כל תוצאות הביניים, כלומר לא רק את התוצאה הסופית של !10 אלא גם את כל העצרות של המספרים שקודמים ל-10.

שימוש בלולאת while לאימות קלט

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

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

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