2.12. לולאות

לולאה מריצה את אותו בלוק קוד שוב ושוב. ל-Python יש שתי צורות: while, שממשיכה כל עוד תנאי נשאר אמיתי, ו-for, שעוברת על הפריטים של רצף.

Side-by-side flowcharts. while: test the condition, run the body if true, repeat. for: take the next item from the iterable, run the body, repeat until exhausted.

while ממשיכה לבדוק תנאי; for עוברת על רצף עד שהוא נגמר.

2.12.1. לולאות while

לולאת while בודקת את התנאי שלה לפני כל איטרציה ומריצה את הגוף עד שהבדיקה הופכת לשקרית:

count = 0
while count < 5:
    print(count)
    count += 1

פלט:

0
1
2
3
4

אם התנאי אמיתי בהתחלה ולעולם אינו הופך לשקרי, הלולאה רצה לנצח. while True: הוא הניב הסטנדרטי ללולאה ראשית, שיוצאים ממנה במפורש עם break:

while True:
    step()
    if done():
        break

2.12.2. לולאות for

לולאת for עוברת על הפריטים של אובייקט ניתן לאיטרציה – רשימה, tuple, מחרוזת, bytes, dict, או כל דבר אחר שתומך באיטרציה:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

פלט:

apple
banana
cherry

אותה צורה עובדת על מחרוזת, שבה כל פריט הוא מחרוזת בת תו אחד:

for letter in "OpenMV":
    print(letter)

פלט:

O
p
e
n
M
V

איטרציה ישירה על dict מניבה את המפתחות שלו, בסדר ההכנסה:

for key in {"a": 1, "b": 2}:
    print(key)

פלט:

a
b

כל מעבר קושר את משתנה הלולאה (fruit, letter, key) לפריט הבא. לאחר שהלולאה מסתיימת, המשתנה שומר על הערך מהאיטרציה האחרונה.

2.12.3. range

ללולאות for על טווח מספרי, השתמשו ב-range():

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – עם צעד מותאם אישית (ערכים שליליים סופרים אחורה).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() מייצרת ערכים בעצלתיים – היא אינה בונה רשימה בזיכרון. כדי לקבל list אמיתי, עטפו אותה: list(range(10)).

2.12.4. enumerate

כאשר הלולאה זקוקה גם לאינדקס וגם לפריט, enumerate() מניבה זוגות (index, item):

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

התחילו את האינדקס במשהו אחר מאפס על ידי העברת ארגומנט שני: enumerate(items, start=1).

2.12.5. zip

כדי לעבור על שני (או יותר) אובייקטים ניתנים לאיטרציה בצעד אחיד, השתמשו ב-zip(). היא מניבה tuple אחד לכל מיקום ועוצרת בקלט הקצר ביותר:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

פלט:

alice 88
bob 92
carol 70

2.12.6. השמה בשורה עם :=

אופרטור הwalrus := הוא השמה שהיא גם ביטוי. הוא קושר שם ומוערך לאותו ערך באותו זמן. בלולאת while, זה מקפל את תבנית ה“קרא, בדוק, גוף“ הנפוצה לשורה אחת:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

שתי הצורות עושות את אותו הדבר. השתמשו ב-:= כאשר שכפול ההשמה באמת פוגע בקריאוּת; אל תשתמשו בו רק כדי להיות מתוחכמים. הסוגריים נדרשים ברוב המיקומים כדי לשמור על הביטוי חד-משמעי.