שיעור 8 of 18
בתהליך

לולאות for ו-while

לולאות — לעשות את זה שוב

איך לקרוא את השיעור הזה. עברו עליו מול המקלדת. בדרך תפגשו חמישה מלווים:

💡 טיפ · 🌍 מהעולם האמיתי · ⚠️ שימו לב · 🎓 בבחינה · 🧠 בדקו את עצמכם

למה השיעור הזה חשוב

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

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

יחד עם תנאים, לולאות משלימות את בלוק 2 של ה-PCEP — 29% מהבחינה, הבלוק הכבד ביותר שיש.

תוצאות למידה. בסוף השיעור תדעו:

  1. לבחור בין while ל-for לפי השאלה אם מספר החזרות ידוע.
  2. לכתוב range() עם אחד, שניים או שלושה ארגומנטים, ולחזות בדיוק אילו ערכים יופקו.
  3. לשלוט בלולאה מתוכה עם break ו-continue.
  4. להשתמש בסעיף ה-else שפייתון מצרפת ללולאות.
  5. לאבחן את שלושת הבאגים הקלאסיים: לולאה אינסופית, שגיאת אחד, ומונה שלא משתנה.

1. while — לחזור עד שמשהו משתנה

לולאת while חוזרת כל עוד התנאי שלה מתקיים. הצורה אמורה להיראות מוכרת — זו if שממשיכה לחזור:

counter = 3

while counter > 0:
    print(counter)
    counter -= 1

print("צא לדרך!")

התנאי נבדק לפני כל מעבר. אם הוא שקר כבר בפעם הראשונה, הגוף לא רץ בכלל.

1.1 הלולאה האינסופית

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

 counter = 3
   while counter > 0:
       print(counter)        # counter לא משתנה — זה לא נגמר לעולם

 counter = 3
   while counter > 0:
       print(counter)
       counter -= 1          # עכשיו התנאי יכול להפוך לשקר

⚠️ שימו לב: לולאה אינסופית אינה שגיאת תחביר. התוכנית פשוט נתקעת. לחצו Ctrl-C כדי לעצור. כשאתם כותבים while, הרגילו את עצמכם לשאול שאלה אחת לפני ההרצה: איזו שורה בגוף הזה משנה את התנאי? אם אתם לא יכולים להצביע עליה — יש לכם לולאה אינסופית.

1.2 השימוש הקלאסי: לולאת קלט

password = ""

while password != "letmein":
    password = input("סיסמה: ")

print("הגישה אושרה.")

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


2. for — לחזור מספר ידוע של פעמים

לולאת for עוברת על רצף, פריט אחר פריט, ונעצרת כשנגמר. אין תנאי ואין מונה לתחזק — ולכן היא לא יכולה לרוץ לנצח:

for letter in "cyber":
    print(letter)

for name in ["נועה", "אלון", "דנה"]:
    print("שלום,", name)

2.1 range()

צורהמשמעותמפיקה
range(5)עצירה בלבד0 1 2 3 4
range(2, 5)התחלה, עצירה2 3 4
range(0, 10, 3)התחלה, עצירה, צעד0 3 6 9
range(5, 0, -1)ספירה לאחור5 4 3 2 1

⚠️ שימו לב — שגיאת האחד. range() מתחילה ב-0 ולעולם לא כוללת את ערך העצירה. range(5) נותנת חמישה מספרים, והאחרון הוא 4 ולא 5. הכלל היחיד הזה אחראי ליותר באגים של מתחילים מכל כלל אחר בפייתון, וזה מה שהבחינה בודקת הכי הרבה. בספק — הדפיסו: print(list(range(5))).

🎓 בבחינה: מטרה 2.2 בודקת את גבולות ה-range() ללא הרף. צפו ל”כמה פעמים הלולאה רצה” ו”מה הערך האחרון שמודפס”. שתי התשובות תלויות באותו כלל: ההתחלה נכללת, העצירה לא.

2.2 מעבר לפי ערך או לפי מיקום

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

names = ["נועה", "אלון", "דנה"]

 for name in names:              # רק הערך מעניין
       print(name)

 for i in range(len(names)):     # באמת צריך את המיקום
       print(i, "->", names[i])

 for i in range(len(names)):     # המיקום נשלף ולא בשימוש
       print(names[i])              # הצורה הראשונה אומרת זאת טוב יותר

len() מחזירה את מספר הפריטים, אז range(len(names)) מפיקה 0 1 2 — בדיוק המיקומים החוקיים, כי גם range() וגם אינדוקס רשימה מתחילים מאפס. זו שגיאת האחד עובדת לטובתכם, לשם שינוי.

2.3 מתי כל אחת

השתמשו ב-for כאשרהשתמשו ב-while כאשר
אתם יודעים כמה חזרות, או יש רצף לעבור עליו.מספר החזרות תלוי במשהו שקורה בתוך הלולאה.
“בדוק את כל 50 רשומות היומן.”“המשך לשאול עד שהסיסמה נכונה.”

3. שלושת הדפוסים שתשתמשו בהם כל הזמן

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

3.1 צובר — לבנות סכום

יוצרים משתנה לפני הלולאה, מוסיפים אליו בתוכה, קוראים אותו אחריה:

total = 0                        # לפני

for price in [12, 7, 30, 5]:
    total += price               # בתוך

print("סה\"כ:", total)           # אחרי — 54

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

3.2 מונה — כמה מתאימים?

failures = 0

for entry in ["ok", "fail", "ok", "fail", "fail"]:
    if entry == "fail":
        failures += 1

print(failures, "כשלונות")       # 3

3.3 הטוב ביותר עד כה

scores = [72, 91, 65, 88]
highest = scores[0]              # מתחילים מהראשון, לא מאפס

for score in scores:
    if score > highest:
        highest = score

print("הגבוה ביותר:", highest)   # 91

⚠️ שימו לב: להתחיל מ-highest = 0 נראה תמים ונשבר בשקט ברגע שכל הערכים שליליים — התשובה חוזרת כ-0, ערך שמעולם לא היה בנתונים. התחילו מהפריט האמיתי הראשון.


4. לעקוב אחרי לולאה כמו שפייתון מריצה אותה

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

n = 10
while n > 0:
    n -= 3
    print(n)

מלאו שורה למעבר, ובדקו את התנאי לפני כל אחד:

מעברn לפניn > 0?n אחרימדפיס
110כן77
27כן44
34כן11
41כן‎-2-2
5‎-2לא — עצירה

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

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


5. break ו-continue

  • break — לצאת מהלולאה מיד, ולדלג על כל מה שנשאר.
  • continue — לדלג על שאר המעבר הנוכחי ולעבור ישר לבא.
for i in range(6):
    if i % 2 != 0:
        continue
    print(i)                 # 0 2 4 — אי-זוגיים דולגו

while True:
    answer = input("הקלד 'צא' לעצירה: ")
    if answer == "צא":
        break

6. ה-else של הלולאה

לפייתון יש תכונה שלרוב השפות אין: ללולאה יכול להיות סעיף else. הוא רץ כשהלולאה הסתיימה כרגיל — כלומר כשהיא לא הופסקה ב-break:

for name in ["נועה", "אלון", "דנה"]:
    if name == "יוסי":
        print("נמצא")
        break
else:
    print("לא ברשימה")     # רץ — לא היה break

קראו “for … else” כ“ואם מעולם לא יצאנו”. זו הדרך המסודרת ביותר לומר “חיפשתי בכל ולא מצאתי”, בלי משתנה דגל נפרד.


7. לולאות מקוננות

for row in range(3):
    for col in range(3):
        print(row, col, end="  ")
    print()

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

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


8. שלוש התקלות הקלאסיות

הטעותמה רואיםהתיקון
מונה שלא משתנההתוכנית נתקעת לנצחלהצביע על השורה שמשנה את התנאי.
שגיאת אחד ב-range()אין שגיאה — איטרציה אחת חסרה או עודפתהתחלה נכללת, עצירה לא.
עבודה אחרי breakאין שגיאה — השורות לא רצותלפני ה-break, או ב-else של הלולאה.

🧠 בדקו את עצמכם

  1. כמה פעמים רצה for i in range(2, 9, 3), ומה הערך האחרון?
  2. מה ההבדל בין break ל-continue?
  3. מתי ה-else של לולאה לא רץ?

תשובות: (1) שלוש פעמים — 2, 5, 8. הבא היה 11, מעבר לעצירה. (2) break יוצא מהלולאה כולה; continue מדלג למעבר הבא. (3) כשהלולאה הופסקה ב-break.


9. הכל ביחד — דוגמה מלאה

CORRECT_PASSWORD = "letmein"
LOCKOUT_THRESHOLD = 3

for attempt in range(LOCKOUT_THRESHOLD):
    entered = input("סיסמה: ")

    if entered == CORRECT_PASSWORD:
        print("הגישה אושרה.")
        break

    remaining = LOCKOUT_THRESHOLD - attempt - 1
    print("שגוי.", remaining, "ניסיונות נותרו.")
else:
    print("החשבון ננעל. פנו לתמיכה.")

ה-for נותן בדיוק שלושה ניסיונות ולא יכול לברוח. ה-break יוצא ברגע שהסיסמה נכונה. וה-else של הלולאה — שרץ רק אם לא היה break — הוא הנעילה. בלי משתנה דגל ובלי דרך לטעות בחשבון. שימו לב ל-- 1: זו שגיאת האחד מופיעה בקוד אמיתי, כי במעבר הראשון attempt הוא 0.

🧪 מקום שמור לתרגול — סביבת פייתון אינטראקטיבית.

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


10. מילון מונחים

מונחמשמעות
לולאהבלוק קוד שנכתב פעם אחת ורץ שוב ושוב.
איטרציהמעבר בודד אחד דרך גוף הלולאה.
whileחוזרת כל עוד תנאי מתקיים.
forעוברת על רצף, פריט למעבר.
range()מפיקה רצף מספרים; העצירה אינה נכללת.
breakיוצא מהלולאה מיד.
continueמדלג על שאר המעבר הנוכחי בלבד.
צוברמשתנה שנוצר לפני הלולאה ונבנה בתוכה.
לולאה אינסופיתלולאה שהתנאי שלה לא הופך לשקר לעולם.
שגיאת אחדאיטרציה אחת יותר מדי או פחות מדי.

11. סיכום

  • while חוזרת כל עוד תנאי מתקיים — כשמספר החזרות תלוי במה שקורה בפנים.
  • משהו בגוף ה-while חייב לשנות את התנאי, אחרת הלולאה לא נגמרת.
  • for עוברת על רצף ולא יכולה לרוץ לנצח.
  • ב-range()ההתחלה נכללת, העצירה לא.
  • break יוצא; continue מדלג מעבר; ה-else רץ רק כשלא היה break.
  • רוב הלולאות האמיתיות הן צובר, מונה, או הטוב ביותר עד כה.
  • לולאות מקוננות מכפילות. שתי לולאות של אלף פריטים = מיליון פעולות.

➡️ בהמשך: מבני נתונים. עברתם עכשיו על מחרוזת ועל רשימה שכתבתם ביד. בשיעור הבא תפגשו את המכולות כמו שצריך — רשימות שאפשר לשנות, tuples שאי אפשר, ומילונים שמחפשים לפי שם במקום לפי מיקום. זה בלוק 3 של הבחינה, עוד 25%, ושם לולאות מפסיקות להיות טכניקה ומתחילות להיות הדרך שבה באמת עובדים עם נתונים.


12. הקלטות שיעור וחומרי עזר

ההקלטות והחומרים של השיעור הזה, כפי שהועברו בכיתה. חומרי ה-PDF מופיעים גם בלשונית “חומרים”.

מצגת השיעור : https://gamma.app/docs/Python-for-while-1et6h2yyo6s8055

הקלטת שיעור:

פטרון מעבדות: