לולאות

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

1. לולאות while

לולאת while עובדת כפי שאתם מצפים, והפקודות break ו continue מאפשרות יציאה מהלולאה או מעבר לאיטרציה הבאה בהתאמה. אפשר לחשוב על לולאות while כגירסא חלופית של הפקודה if כאשר במקום לבצע את הבלוק פעם אחת בלבד הלולאה תבצע אותו שוב ושוב כל עוד התנאי מתקיים.

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

line = raw_input()

while line.startswith('a'):
    print "I don't like a'", line
    line = raw_input()

הקוד הנ"ל עובד אך דורש רישום של שורת קריאת הקלט פעמיים. באמצעות הפקודה break נוכל לשפר את מבנה הלולאה באופן הבא:

while True:
    line = raw_input()
    if not line.startswith('a'): break

    print "I don't like a'", line

כעת הבדיקה מבוצעת בגוף הלולאה ואם התנאי מתקיים אנו יוצאים מהלולאה באופן יזום עם הפקודה break.

2. ספירת מילים

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

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

word_count = 0
line = raw_input()

while len(line) > 0:
    word_count += len(line.split())
    line = raw_input()

print "You typed a total of %d words" % word_count

שימו לב שסיום הקלט באמצעות תו-סוף-קלט (הצמד Ctrl+D ביוניקס או Ctrl+Z בחלונות) יביא לזריקת שגיאה מהתוכנית. בפרקים הבאים נלמד כיצד לטפל בשגיאות אלו. מוזמנים לקרוא בתיעוד על הפקודה split עבור יכולות נוספות של פקודה זו. מאחר והפקודה הינה חלק מאובייקט מחרוזת נפתח את התיעוד באמצעות הקלדה בשורת הפקודה:

pydoc string.split

3. לולאות for

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

sentence = "Don't think twice it's alright"

for word in sentence.split():
    print "Word: ", word
    print "First letter is:", word[0]
    print "The word has:", len(word), "characters"

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

>>>> range(5)
[0, 1, 2, 3, 4]

>>>> range(2,4)
[2,3]

>>>> range(1,10,2)
[1,3,5,7,9]

התוכנית הבאה מחשבת את סכום המספרים הזוגיים בין 0 ל-100 באמצעות הפקודה range:

sum = 0
for n in range(0,101,2):
    sum += n

print "Sum = %d" % sum

4. לוח הכפל

ניתן לקנן לולאות כדי לקבל איטרציה כפולה. כך למשל נוכל לקנן שתי לולאות for כדי להדפיס את לוח הכפל. שימו לב שהקוד בשורה 3 יתבצע בכל איטרציה של הלולאה הפנימית בעוד שהקוד בשורה 4 יתבצע בכל איטרציה של הלולאה החיצונית:

for i in range(1,11):
    for j in range(1,11):
        print "%*d" % (3,i * j),
    print

מעניין גם לראות את פקודת ההדפסה בשורה 3 המשתמשת בסימן הכוכבית בתוך print (לקוח משפת C). השפעת סימן זה היא יישור לימין של המספרים לאורך מקסימלי של 3 ספרות.


תוכנית לדוגמא המשתמשת בלולאת while:

while True:
    print "Please type in a number"
    num = int(raw_input())

    if num % 2 == 0:
        print "Bravo, it's an even number"
    else:
        break

print "The End"

תוכנית לדוגמא המשתמשת בלולאת for:

"""
For loops demo
- Iterate over a sequence
- Iterate over numbers
"""

sentence = "Got two reasons why I cry"
words = sentence.split()

for word in words:
    print "The word is: ", word, "And its length:", len(word)

total = 0
for i in range(101):
    total += i

print "1 + 2 + 3 + 4 + ... + 100 = ", total

תיקיית הדוגמאות עם כל קבצי הדוגמא שהוצגו במדריך:
https://github.com/ynonp/python-examples/tree/master/03_flow