לדלג לתוכן

2.1 בקרת זרימה הרצאה

בקרת זרימה (control flow)

  • פעמים רבות בתכנות אנחנו רוצים לשנות את הזרימה של התוכנה בהתאם לכל מיני תנאים.
  • בקרת זרימה מתייחסת לאופן שבו קוד בתוכנת מחשב מתבצע, או במילים אחרות, הסדר שבו הפקודות רצות. קחו למשל את הדוגמה הבאה:
    age = int(input("Enter your age: ")) # for example: 6
    
    if age > 18:
        print("you are over 18,") 
    
        print("access granted!")
    else: 
        print("you need to be over 18!")
    
    # The output of the code would be: you need to be over 18! 
    

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

את בקרת השליטה מבצעים באמצעות if ו - else שמטרתם היא לבדוק אם תנאי מסויים מתקיים. למשל, כמו בדוגמה למעלה, age > 18 .

התנאים האלו הם נקראים "ביטויים בולייאנים" או באנגלית "Boolean expression".

ביטויים בולייאנים

ביטויים בוליאניים (Boolean Expressions) הם ביטויים שמחזירים ערך אמת (True) או שקר (False). הם משמשים לבדיקת תנאים ולהחלטה על זרימת התוכנית. ביטויים אלה יכולים לכלול אופרטורים לוגיים כמו and, or, not, ואופרטורים השוואתיים כמו שווה ( == ), לא שווה ( != ), גדול מ- ( > ), קטן מ- ( < ) ועוד.

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

x == y
x != y 
x > y
x < y
x <= y
x >= y
x in [1, 2, 3]
x not in [1, 2, 3]
  • נהוג להשתמש ב-if בכל הביטויים האלה שאנחנו כותבים.
x = 4
if x == 4:
    print("x is equal to 4!")
  • ביטויים מורכבים יותר:
  • בדוגמה זו הצבנו שני תנאים אשר צריכים להתמשש בכדי שתחזור אלינו תוצאת True.
x == y and a < b
x > y or a == b
  • בגלל שביטויים בולייאנים הם בדיוק כמו ביטויים רגילים, אפשר להשתמש בהם בכל מקום.
print(x == 4) # prints true

condition = x == 4
print(condition)
  • עוד דרך תמיד להחזיר תוצאת True היא פשוט לכתוב את הקוד כך:

if condition:
    print("x is equal to 4!")

- למרות שהקוד לא תמיד יחזיר אמת, הוא תמיד יפעל אם condition היא אמת (True). כלומר, כל עוד התנאי condition הוא נכון, המשפט print("x is equal to 4!") ירוץ וידפיס את ההודעה "x is equal to 4!". הסיבה לכך היא שמבחינת הקוד, אין שום דבר שמגביל את התנאי לבדוק האם x שווה ל-4, ולכן כל עוד condition הוא True, ההדפסה תתבצע.

סינטקס

סינטקס - if

  • אם התנאי נכון, תריץ את הקוד.
    if expression:
        print("the expression is True!")
    

סינטקס - if else

  • אם התנאי נכון, תריץ את הקוד.
  • אחרת, תריץ את הקוד השני.
    password = "Password1"
    if password == "123456":
        print("Right password!")
    else: 
        print("Wrong password!")
    

סינטקס - if elif else

אם התנאי נכון, תריץ את הקוד.
אחרת, אם התנאי השני נכון, תריץ את הקוד השני.
אחרת, (שום תנאי לא נכון) , תריץ את הקוד השלישי.

action = "exit"

if action == 'play':
    print("game starts!")
elif action == "exit":
    print("game over :(")
else:
    print("invalid input!")

בשורה אחת - if else

  • אפשר לעשות if ו - else בשורה אחת בודדת כדי לגרום לקוד להיות קצר יותר.
    status = int(input("Enter your salary: "))
    
    status = "rich" if salary > 10000 else "poor"
    
    print(f"Your status is {status}.")
    
  • שימו לב שלכתוב תנאים מסובכים בשורה אחת (one line) זה יכול לגרום לקוד להיות מאוד לא קריא, דבר שנרצה להימנע ממנו.

משחק התנאים

  • נחש האם התנאי ירוץ (כלומר יחזיר True).
  • אתם מוזמנים להריץ אצ קטעי הקוד הבאים ולראות אם צדקתם או לא.
if True:
    print("will this work?")
x = 3
if x == 3:
    print("will this work?")
  • האחד הבא טיפה טריקי.
x = 0
if x:
    print("will this work?")
if None:
    print("will this work?")
if "a" in "abc":
    print("a is in abc!!")
if 1 in [1,2,3]:
    print("1 is in 123!!")
x = 3
if x != 2:
    print("x is not 2")
x = 3
if not (x == 2):
    print("x does not equal to 2")
x = True
if not x:
    print("x is false")

if not expression:
    # Code block

- זכרו: אם אנחנו רוצים לבדוק אם איזשהו משתנה הוא None צריך לעשות זאת ככה:
x = None
if x is None:
    # Code block

סקופ - scope

כשאנחנו כותבים תנאים, אנחנו עושים בעצם בלוקים של קוד, בלוק של קוד מאופיין על ידי 4 רווחים (tab), לכל תנאי יש בלוק של קוד - נחזור לדוגמה הראשונה שלנו:

age = int(input("Enter your age: "))

if age > 18:
    print("you are over 18,")

    print("access granted!")
else: 
    # :(
    print("you need to be over 18!")

- יש פה שני בלוקים של קוד.
- כאשר אנחנו יוצרים משתנים בבלוק של קוד, הם קיימים רק באותו בלוק.
אם ניצור משתנה בשם x בתוך בלוק קוד, לא נוכל לגשת ל-x מחוץ לבלוק - הנה דוגמה:
age = int(input("Enter your age: ")) # for example 21

if age > 18:
    x = "awesome!"
    print(x) # will print: awesome!   

print(x) # An error will occur because 'x' is not defined outside of the if statement.

  • הקוד הבא יחזיר שגיאה, בגלל שאנחנו מנסים לגשת למשתנה x שמוגדר בבלוק של קוד שנמצא בתוך התנאי.

  • הקונספט הזה נקרא סקופ, סקופ זה איפה (איזה שורות קוד) ניתן להשתמש במשתנה שהגדרנו בבלוק של קוד.

  • איפה אפשר? רק בבלוק של הקוד! אז: הסקופ של x במקרה הזה הוא הבלוק קוד של התנאי.

תנאים מסובכים עם match

  • הוסיפו רק בפייתון 3.10 (גרסא עדכנית יחסית)
  • הצהרת ה-match ב- Python משמשת להשוואת ערך מול מספר תבניות אפשריות. הוא מאפשר לכתוב קוד שבודק את הערך של משתנה או ביטוי מול מספר אפשרויות בצורה קריאה ותמציתית יותר, במיוחד כאשר עוסקים במספר תנאים.

הנה דוגמה:

password = input("enter password: ") 
match password:
    case "123456":
        print("access granted.")
    case "Password1" | "iloveyou":
        print("this password has changed 6 months ago.")
    case _:
        print("not authorized.")

הקוד הבא בנוי כך:
- בהתחלה הוא מבקש כקלט מחרוזת מסוימת, שהיא בעצם הססמה שלנו.
- לאחר מכן המחשב קורא את אותה מחרוזת ובודקת:
1. תחילה, המחשב בודק אם הססמה שכתבנו היא 123456. אם כן המחשב היה מחזיר: access granted.
2. אם הססמה שכתבנו היא לא 123456 אז המחשב עובר למקרה הבא.
3. המקרה הבא אומר כך: אם הססמה היא Password1 או iloveyou אז המחשב יחזיר this password has changed 6 months ago. במקרה של match התו שמסמל או הוא |.
4. לבסוף, אם הקוד שכתבנו הוא אף אחד מהמקרים הקודמים, אז המחשב יחזיר not authorized.
5. למקרה ותהיתם, __ case משמש כתוו כללי. משמעות הדבר היא שאם אף אחת מהצהרות המקרה הקודמות לא תואמת את הערך המוערך, מקרה _ יבוצע, שהוא בעצם מקרה כללי ולא ספציפי.

הפונקציה המובנית isinstance

  • כדי לכתוב תנאי שבודק את הסוג של משתנה מסויים אפשר להשתמש בפונקציה המובנית: isinstance
    something = 5
    if isinstance(something, int):
        print("integer!!")
    elif isinstance(something, str):
        print("string!!")
    
    # will print: integer!!