פרק שני

התניות

תוכן העניינים

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

age = input(‘Insert age; -1 to stop: ‘)

while age != ‘-1’:

    print(age)

    age = input(‘Insert age; -1 to stop: ‘)

 

(1) מבוא

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

(2) הוראת if - מבט ראשון

נשוב ונתבונן בתכנית עלויות הספרים שכתבנו בפרק הקודם:

import random

price1 = float(input(‘Price of book 1: ‘))

price2 = float(input(‘Price of book 2: ‘))

price3 = float(input(‘Price of book 3: ‘))

totalPrice = price1 + price2 + price3

reduc = random.randint(11, 20) 

print(‘The price after reduction is: ‘, totalPrice)

מכאן ועד סוף הפרק נתמקד בחלק התכנית הבא לאחר קליטת עלויות שלושת הספרים (כלומר החל מחישוב totalPrice ועד סוף התכנית). נרצה לשכתבו באופן שההנחה תינתן אך ורק אם סכום עלויות כל הספרים גדול מ-50. האלגוריתם שנשתמש בו לאחר קליטת כל עלויות הספרים הוא זה:

(1) נחשב את סכום עלויות כל הספרים ונשמור אותו במשתנה totalPrice

(2) אם totalPrice גדול מ-50

(2.1)          נחשב את ההנחה 

(2.2)          נפחית את ההנחה מ-totalPrice

(3) נודיע מה העלות הסופית, כלומר totalPrice

ההכרזה בדבר העלות הסופית (צעד 3) תתבצע בכל מקרה, דהיינו הן אם סכום העלויות הוא גדול מ-50 הן אם לאו.

תרשים זה ממחיש את פעילות האלגוריתם: 

נשים לב כי השאלה שאנו בודקים בנוגע לגובה סכום עלויות הספרים היא שאלת כן/לא, כלומר שאלה שיכולות להיות לה אך ורק שתי תשובות: כן או לא. במונחים של תִכנות נאמר שיש לשאלה כזו שתי תשובות אפשריות: אמת (True) או שקר (False). כדי להתנות ביצוע של קוד לפי בדיקה של שאלת אמת/שקר נשתמש במבנה קוד מסוים: מבנה if. נכתוב אותו כך:

if condition: 

    instruction(s)

 

השורה הראשונה במבנה if פותחת במילה השמורה if. אחר כך בא תנאי לבדיקה: התוצאה של בדיקתו יכולה להיות אחד משני ערכים: אמת או שקר. אחרי התנאי מופיע הסימן נקודתיים. השורה או השורות הבאות כולן מוזזות ימינה לעומת השורה הראשונה. יש בהן הוראות שיתבצעו אם התוצאה של בדיקת התנאי המופיע לצד המילה if היא אמת; נקרא למכלול הוראות אלו בשם ‘גוף ה-if’ (תרגום של if’s body). 

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

totalPrice = price1 + price2 + price3

if (IS totalPrice GREATER THAN 50?): 

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

בגוף הוראת ה-if כאן מופיעות שתי הוראות: האחת מחשבת את ההנחה והאחרת מפחיתה את ההנחה מסכום העלויות של שלושת הספרים. כאמור שתיהן יתבצעו רק אם תוצאת בדיקת התנאי היא אמת. התנאי במימוש החלקי הזה נכתב באנגלית ולא בפייתון. כדי להשלים את המימוש עלינו ללמוד כיצד מתרגמים תנאים או שאלות אמת/שקר משפה אנושית לפייתון. זה מוביל אותנו לעולמם של הביטויים הלוגיים.

(3) ערכים בוליאניים, סימני השוואה, וביטויים לוגיים

בפייתון מוגדרים הערכים True ו-False. אלה הם תוצאות המתקבלות בבדיקה של תנאים (למעשה יש לערכים True ו-False משמעות רחבה יותר מתוצאות של תנאים – ראו נספח ח’).  הם מכונים ‘ערכים בוליאניים’ (boolean values). שניהם מסוג אחד ששמו bool.

כמו כל ערך אחר בשפה גם את הערכים True ו-False אפשר להציב במשתנים. דוגמות:

 

boolVar1 = True 

boolVar2 = False

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

ביטוי לוגי (logical expression) הוא ביטוי בשפה הבודק בדיקה שיש לה אחת משתי תוצאות: True או False. בפייתון יש כמה דרכים לכתוב ביטויים לוגיים, ובפרק זה נתוודע לאחת מהן, שכיחה למדי: שימוש בסימני השוואה (comparison operators). סימנים אלה כשמם כן הם: הם משמשים להשוואת ערך אחד לערך אחר. הנה ששת סימני ההשוואה שישמשו אותנו:

val1 == val2         האם הערך val1 שווה לערך val2

val1 != val2          האם הערך val1 שונה מערך val2

val1 > val2           האם הערך val1 גדול מהערך val2

val1 >= val2         האם הערך val1 גדול מהערך val2 או שווה לו

val1 < val2           האם הערך val1 קטן מהערך val2

val1 <= val2         האם הערך val1 קטן מהערך val2 או שווה לו

נעיין בדוגמה לביטוי לוגי המשתמש בסימן < :

result = 5 > 5 

print(result)

>>>

False

הביטוי הלוגי מופיע בצד הימני של הוראת ההשמה. הוא נכתב באמצעות הסימן  <  המציין ‘גדול מ-‘. הבדיקה היא: 5 הוא גדול מ-5. תוצאת הבדיקה היא False, התוצאה הזאת מושמת במשתנה result. 

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

result = name == ‘Charlie Chaplin’ 

אם הערך הנמצא במשתנה name הוא המחרוזת ‘Charlie Chaplin’, הוראת השמה זו תשים True במשתנה result, ואם יש במשתנה name ערך אחר, ההוראה תשים False במשתנה result. 

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

result = ‘cat’ < ‘bat’ 

print(result)

result = ‘aa’ < ‘aA’ 

print(result)

>> 

False

False

השוואות אלו ודומות להן נסמכות על סדר המילון. לפי סדר זה המחרוזת ‘cat’ באה אחרי המחרוזת ‘bat’ ולכן תוצאת הבדיקה הראשונה היא False. וגם לפי סדר זה אותיות ‘גדולות’ (upper case) באות לפני אותיות קטנות (lower case) . לכן גם תוצאת הבדיקה השנייה היא False. 

באמצעות הסימנים == ו- =! נוכל לבדוק גם תוכן של משתנים בוליאניים. דוגמה:

boolVar = True 

result = boolVar == True

print(result)

>>> 

True

 

ההוראה השנייה בקוד זה בודקת אם הערך המוצב במשתנה boolVar הוא True. 

(4) כתיבת תנאי בהוראת if

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

totalPrice = price1 + price2 + price3

if totalPrice > 50

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

לצד המילה השמורה if כתבנו ביטוי לוגי. ביטוי זה בודק אם סכום עלויות הספרים – הערך המוצב במשתנה totalPrice – גדול ממש מ-50. 

מה אם נרצה לרכך מעט את תנאי הזכאות להנחה ולתת הנחה גם אם סכום עלויות הספרים שווה ל-50? כל שעלינו לעשות הוא לשנות את סימן ההשוואה מ- < ל- =< :

if totalPrice >= 50:

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

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input month’s name: ‘)

if currentMonth == ‘May’:

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

בכל הדוגמות האלה ההוראות בגוף ה-if מבוצעות או לא מבוצעות לפי בדיקת התוצאה של תנאי אחד בלבד. נפנה עתה לעיין בהתניות לפי בדיקת שני תנאים או יותר.

(5) ביטויים לוגיים מורכבים

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

ביטוי לוגי אחד יכול לבדוק יותר מבדיקה אחת. בניסוח מדויק יותר מזה: ביטוי לוגי אחד יכול להיות צירוף של שני ביטויים לוגיים או יותר. הצירוף נעשה באמצעות שלוש מילים בשפה שהן ייעודיות לצורך זה ומכונות ‘אופרטורים לוגיים’ (logical operators): and, or ו-not. כל אופרטור לוגי משמש לסוג מסוים אחד של צירוף ביטויים. נתחיל ונבחן את האופרטורים and ו-or. 

נשתמש באופרטור and כשנרצה להתנות ביצוע של קוד בקיומם של שני תנאים גם יחד. כך נכתב ביטוי לוגי המשתמש באופרטור and:

condition1 and condition2

תוצאתו של ביטוי המורכב באמצעות האופרטור and היא True אך ורק אם תוצאות שני הביטויים הלוגיים המרכיבים אותו הן True; בכל מקרה אחר תוצאת הביטוי המורכב היא False. זה המצב בשִכתוב התכנית שאנו חפצים בו כאן: מתן הנחה אך ורק אם החודש הנוכחי הוא מאי וגם סכום הספרים הוא גדול מ-50. הנה  כך ייראה הקוד המשוכתב:

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input month’s name: ‘)

if (currentMonth == ‘May’) and (totalPrice > 50):

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

התנאי הנבדק בהוראת ה-if כאן הוא ביטוי לוגי המורכב משני ביטויים המצורפים זה לזה באמצעות האופרטור and: האם החודש הוא מאי וגם האם סכום העלויות גדול מ-50. ההוראות בגוף ה-if יתבצעו אם ורק אם שני התנאים מתקיימים. 

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

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

if (totalPrice > 50) and (totalPrice <= 100):

נעיר שתי הערות חשובות בנוגע לביטוי הלוגי המופיע כאן. 

ראשית שימו לב כי בחישוב הביטוי, וכללית בחישוב ביטוי לוגי המבטא קשר מסוג “וגם” (and), אם תוצאת הביטוי המופיע משמאל למילה and היא False אין נבדק הביטוי המופיע מימין למילה, הואיל ובשלב זה כבר ברור שתוצאת הביטוי המורכב כולו היא False (כיוון שלא שני התנאים מתקיימים). במקרה זה אם נמצא שסכום העלויות אינו גדול מ-50, מובן מיד שתוצאת הביטוי המורכב כולו היא False, ועל כן אין מתבצעת בדיקה אם סכום העלויות קטן או שווה ל-100. 

בנוסף הביטוי הלוגי המורכב הזה:

(totalPrice > 50) and (totalPrice <= 100)

נועד לבדוק אם ערך אחד נמצא בטווח מספרים מסוים – כאן: בין 50 (לא כולל) ל-100 (כולל). בפייתון יש שיטת קיצור לכתיבת ביטוי לוגי מורכב מעין זה. במקרה דנן נשתמש בה כך:  

if 50 < totalPrice <= 100:

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

 

נִפנה לאופרטור or. כך נכתב ביטוי לוגי המורכב באמצעות האופרטור or:

condition1 or condition2

תוצאתו של ביטוי המורכב באמצעות האופרטור or היא True אם לפחות לאחד משני הביטויים הלוגיים המרכיבים אותו יש תוצאה True; רק אם התוצאות של שני הביטויים המצורפים הן False, התוצאה של הביטוי המורכב כולו היא False. 

במקרה שלפנינו, נוכל להשתמש באופרטור or כדי להתנות את ההנחה בקיומו של אחד לפחות משני התנאים, כלומר אם עכשיו חודש מאי, ואם הסכום גדול מ-50. לשם כך נשנה מילה אחת בקוד הקודם – במקום and נכתוב or:

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input month’s name: ‘)

if (currentMonth == ‘May’) or (totalPrice > 50):

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

קוד זה מקנה הנחה בשלושה מצבים אלה: 

• אם עכשיו חודש מאי וגם הסכום גדול מ-50

• אם עכשיו חודש מאי והסכום אינו גדול מ-50

• אם עכשיו לא חודש מאי והסכום גדול מ-50

נדגיש: על אף שאנו משתמשים במילה or, הביטוי הלוגי הנבדק במבנה if יחזיר True (גם) במצב ששני התנאים מתקיימים. כלומר ההנחה תינָתן כאן גם למי שקנו בחודש מאי וגם סכום עלויות הספרים שקנו גדול מ-50. 

בחישוב ביטוי לוגי המבטא קשר של “או” (or), אם תוצאת הביטוי המופיע לפני המילה or היא True אין נבדק הביטוי המופיע לאחר המילה. כאן:

(currentMonth == ‘May’) or (totalPrice > 50)

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

 

אופרטור לוגי שלישי ישמש אותנו לבדוק אי-קיום תנאים. זה האופרטור not. כך נכתב ביטוי לוגי המשתמש באופרטור not:

 

not condition

כפי שאפשר להיווכח, שלא כמו and ו-or האופרטור not פועל על ביטוי לוגי אחד בלבד, הביטוי המונח מימינו.

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

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input month’s name: ‘)

if not ((currentMonth == ‘May’) and (totalPrice > 50)): 

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

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

שימו לב לשימוש בסוגריים עגולים בהתניה האחרונה: 

if not ((currentMonth == ‘May’) and (totalPrice > 50)):

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

if not (currentMonth == ‘May’) and (totalPrice > 50):

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

(6) קינון if ב-if

נשוב ונעיין בהתניה שדנו בה בסעיף הקודם: מתן ההנחה אם רכישת הספרים נעשתה בחודש מאי וגם סכום הספרים גדול מ-50. ראינו שאפשר לתרגמה לקוד כך: 

if (currentMonth == ‘May’) and (totalPrice > 50):

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

 

if condition1: 

    zero or more statement(s) 

    if condition2: 

        statement(s) 

    zero or more statement(s)

מבחינת זרימת התכנית משמעות קינון הוראות if הוא שבדיקה אחת מתבצעת אם (ורק אם) בדיקה קודמת לה נבדקה ותוצאתה הייתה True. התרשים הזה ממחיש את הדברים בכל הנוגע להתניות המסוימות שאנו מתעניינים בהן כאן:

הנה תכנית משוכתבת המקנה את ההנחה לפי התנאים הנדרשים ומשתמשת בקינון הוראות if:

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input month’s name: ‘)

if currentMonth == ‘May’:

  if totalPrice > 50: 

    reduc = random.randint(11, 20)

    totalPrice = totalPrice – reduc

print(‘Total price is: ‘, totalPrice)

 

הוראת if אחת שמקוננת בה הוראת if אחרת יכולה להכיל הוראות נוספות חוץ מהוראת ה-if השוכנת בה. לדוגמה בקוד האחרון אפשר להוסיף לפני ההתניה הפנימית הדפסה של מחרוזת  החודש, ולאחר ההתניה – הודעה שהזכאות להנחה נבדקה. ההודעה על החודש וההודעה על בדיקת הזכאות להנחה אינן תלויות בתוצאת הבדיקה המתבצעת בהוראת ה-if הפנימית. הנה הקוד:

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input Month’s name: ‘)

if currentMonth == ‘May’:

  print(‘Current month is’, currentMonth)

  if totalPrice > 50: 

    reduc = random.randint(11, 20)

    totalPrice = totalPrice – reduc

  print(‘Reduction was considered.”)

print(‘Total price is: ‘, totalPrice)

שימו לב כי שתי הוראות ההדפסה בגוף ה-if החיצונית – הדפסת החודש והדפסת הסכום – שתיהן מוזזות ימינה לעומת ה-if החיצונית בדיוק כמו הוראת ה-if הפנימית. 

הזרימה בתכנית האחרונה מומחשת בתרשים זה:

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

(7) המבנה if...else

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

דרך אחת במימוש תהיה שימוש בשתי הוראות if, כך:

totalPrice = price1 + price2 + price3

if totalPrice > 50: 

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

if not(totalPrice > 50): 

  print(‘No reduction.’)

print(‘Total price is: ‘, totalPrice)

שתי הוראות ה-if בקוד הזה בודקות בדיקות מנוגדות: ברור כי אם תוצאת התנאי הנבדק בהוראת ה-if הראשונה היא False (כלומר הסכום אינו גדול מ-50), אז יש לבצע את גוף ה-if השנייה (הודעה שאין הנחה). ולהפך: אם תוצאת התנאי הנבדק בהוראת ה-if השנייה היא False (כלומר הסכום גדול מ-50), אז יש לבצע את גוף ה-if הראשונה (חישוב ההנחה והודעה על המחיר הסופי). ועולה השאלה: האפשר לאחד את שתי הוראות ה-if להוראת if אחת המממשת את האלגוריתם הזה: 

    (1) האם הסכום גדול מ-50?

    (1.1)     אם כן – יש לתת את ההנחה 

    (1.2)     אם לא – יש להודיע שאין הנחה

או את האלגוריתם הזה: 

    (1) האם הסכום אינו גדול מ-50

    (1.1)     אם כן – יש להודיע שאין הנחה

    (1.2)     אם לא – יש לתת את ההנחה 

ובאופן כללי, האם אפשר לממש תבנית אלגוריתמית זו: 

    (1) האם תנאי מתקיים? 

    (1.1)     אם כן – יש לבצע הוראות מסוימות

    (1.2)     אם לא – יש לבצע הוראות מסוימות 

בפייתון יש מבנה המאפשר לממש את האלגוריתמים האלה. זה מבנה if…else . כך נשתמש בו בתכנית המטפלת הן במקרה שסכום עלויות הספרים גדול מ-50 הן במקרה שהסכום אינו גדול מ-50. 

totalPrice = price1 + price2 + price3

if totalPrice > 50: 

  reduc = random.randint(11, 20)

  totalPrice = totalPrice – reduc

else:

  print(‘No reduction.’)

print(‘Total price is: ‘, totalPrice)

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

לפי הגדרתה הוראת else יכולה להופיע אך ורק בצירוף להוראת if, היא באה לטפל במקרה שתוצאת התנאי הנבדק בהוראת ה-if היא False. במקרה זה מתבצעת הוראה או סדרת הוראות, והן נכתבות בהזזה ימינה לעומת המילה else. הוראות אלה מכונות ‘גוף ה-else’. כאן גוף ה-else מכיל הוראה אחת: הדפסת הודעה שהנחה אינה ניתנת. 

התחביר הכללי של מבנה if..else הוא זה:

if condition: 

    instruction(s) 

else: 

    instruction(s)

כאמור הוראת ה-else מיושרת אנכית כמו הוראת ה-if. אך נדגיש שוב: הוראת ה-else מתבצעת אך ורק אם תוצאת הביטוי הלוגי הנבדק בהוראת ה-if היא False. כך בקוד הדוגמה האחרון אם סכום העלויות גדול ל-50 לא תודפס המחרוזת ‘No reduction’.

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

• מקרה א’ – סכום הספרים גדול מ-50 והחודש הוא מאי – במקרה זה ניתן את הנחה. 

• מקרה ב’ – סכום הספרים גדול מ-50 והחודש אינו מאי – במקרה זה דווקא נודיע על תוספת של 20 ש”ח בתשלום הסופי. 

• מקרה ג’ – שני המקרים הקודמים אינם מתקיימים – נוציא הודעה שהמחיר הסופי הוא ללא שינוי (כלומר אין הנחה ואין תוספת). 

כיצד נכתוב את התכנית? 

נתמקד ראשית בטיפול במקרה שסכום הספרים גדול מ-50 והחודש הוא מאי ובמקרה שסכום הספרים גדול מ-50 והחודש אינו מאי. ברור כי תהיה בקוד הוראה אחת הבודקת אם סכום הספרים גדול מ-50. אם תוצאתה תהיה True נצטרך לבדוק בדיקה נוספת – אם החודש הוא מאי – והתכנית תבצע פעולה אחת אם תוצאת הבדיקה תהיה True ופעולה אחרת אם תוצאת הבדיקה תהיה False. תרשים זה ממחיש את הדברים: 

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

נתרגם את התרשים לאלגוריתם זה: 

             (1) נבדוק את התנאי totalPrice > 50

            (1.1)     אם התנאי מתקיים: נבדוק את התנאי currentMonth == ‘May’a

            (1.1.1)             אם תנאי זה מתקיים: נחשב את ההנחה ונפחית אותה מ-totalPrice

            (1.1.2)             אם תנאי זה אינו מתקיים: נודיע על ייקור התשלום הסופי ב-20 ש”ח. 

            (1.2)    אם התנאי אינו מתקיים: נודיע שאין הנחה ואין התייקרות. 

            (2) נודיע מה המחיר הסופי 

שימו לב למספור הצעדים באלגוריתם. הוא נועד לקבץ יחדיו צעדים ותת-צעדים הקשורים אלה באלה. למשל לצעד הלפני-אחרון ניתן המספור 1.2 כיוון שהוא תת-צעד של הצעד המתבצע בהוראה 1 – הוא מטפל במקרה שהתנאי הנבדק בהוראה 1 לא התקיים. 

הדרך מכאן לכתיבת הקוד היא קצרה: 

totalPrice = price1 + price2 + price3

currentMonth = input(‘Please input Month’s name: ‘)

# 1 

if totalPrice > 50: 

  # 1.1

  if currentMonth == ‘May’: 

    # 1.1.1

    reduc = random.randint(11, 20)

    totalPrice = totalPrice – reduc

  else: 

    # 1.1.2

    totalPrice = totalPrice + 20 

else: 

  # 1.2

  print(‘No change in final price.’) 

# 2

print(‘Total price is: ‘, totalPrice)

ראינו אפוא את המבנה if ואת המבנה if…else. עתה נפנה למבנה נוסף המשמש בכתיבת התניות.

(8) המבנה if...else...elif

נשוב ונשנה את התנאים לקבלת הנחה. הפעם ההנחה לא תהיה אחידה: 

* מי שהעלות הכוללת של הספרים שקנו גדולה מ-50 ש”ח, יקבלו הנחה של 20 ש”ח;

* מי שהעלות הכוללת של הספרים שקנו גדולה מ-100 ש”ח, יקבלו הנחה של 30 ש”ח; 

* מי שהעלות הכוללת של הספרים שקנו גדולה מ-150 ש”ח, יקבלו הנחה של 40 ש”ח; 

* ומי שהעלות הכוללת של הספרים שקנו גדולה מ-200 ש”ח, יקבלו הנחה של 50 ש”ח. 

אין הנחה כפולה. 

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

היא מתחילה בבדיקת תנאי אחד. 

• אם נמצא שהתנאי מתקיים, מתבצעת פעולה מסוימת. 

• אם נמצא שהוא אינו מתקיים, נבדק תנאי שני. 

            o אם התנאי השני מתקיים, מתבצעת פעולה מסוימת, 

            o אם נמצא שהתנאי השני אינו מתקיים, נבדק תנאי שלישי. 

                       וכן הלאה וכן הלאה… 

התבנית מסתיימת בתנאי אחרון שנבדק ונמצא שהוא אינו מתקיים – או אז לא נבדק תנאי נוסף והזרימה מסתיימת. 

הנה כך נוכל לכתוב אלגוריתם של תכנית שתממש את הזרימה הזאת: 

       (1) נבדוק את התנאי totalPrice > 200

       (1.1)     אם תנאי זה מתקיים ניתן הנחה של 50 ש”ח 

       (1.2)     אם תנאי זה אינו מתקיים 

                   נבדוק את התנאי totalPrice > 150

                   (1.2.1)     אם תנאי זה מתקיים ניתן הנחה של 40 ש”ח 

                   (1.2.2)     אם תנאי זה אינו מתקיים 

                                        נבדוק את התנאי totalPrice > 100 

                                        (1.2.2.1)    אם תנאי זה מתקיים ניתן הנחה של 30 ש”ח 

                                        (1.2.2.2)    אם תנאי זה אינו מתקיים 

                                                          נבדוק את התנאי totalPrices > 50

                                                          (1.2.2.2.1)  אם תנאי זה מתקיים ניתן הנחה של 20 ש”ח 

                                                          (1.2.2.2.2)  אם תנאי זה אינו מתקיים לא ניתן הנחה כלל 

       (2) נודיע מה העלות הסופית

שימו לב: 

• כאשר נבדק אם העלות הכוללת גדולה מ-150, כבר ידוע שהיא אינה גדולה מ-200. 

• כאשר נבדק אם העלות הכוללת גדולה מ-100, כבר ידוע שהיא אינו גדולה מ-150.

• כאשר נבדק אם העלות הכוללת גדולה מ-50, כבר ידוע שהיא אינה גדולה מ-100. 

• וכשמתבצע מבנה הצעד האחרון באלגוריתם, כבר ידוע שהעלות הכוללת קטנה מ-50 או שווה ל-50. 

נקודה חשובה אחרת נוגעת לרגע הסיום של זרימת האלגוריתם: רגע זה יכול להגיע גם אם לא נבדוק את כל התנאים המופיעים בו. לדוגמה אם מצאנו שהסכום אינו גדול מ-200 אך גדול מ-150, תתבצע הוראת ההדפסה המודיעה על ההנחה (40 ש”ח), הקוד לא ימשיך לבדוק אם הסכום גדול מ-100, והזרימה תגיע מיד לצעד 2 – הדפסת ההודעה שהתכנית הסתיימה.  

נוכל לממש את האלגוריתם באמצעות קינון של כמה הוראות if אחת באחרת. ואולם כאן הקינון יהיה מרובה, וקינון כזה אינו רצוי. במקרה של קינון הנגרם כתוצאה ממבנה אלגוריתם כמו זה הנדון כאן – כלומר בדיקת תנאי המתפצלת לבדיקת תנאי, המתפצלת לבדיקת תנאי, המתפצלת לבדיקת תנאי, וכו’ – נוכל לפשט את הכתיבה של הקוד ואת הבנתו באמצעות שימוש במבנה if…elif..else. במבנה זה חלק else הפותח בהוראת if מוחלף בהוראה אחת: elif. בדוגמה שאנו עוסקים בה אפשר לבצע שלוש החלפות כאלה. הנה כך ייראה הקוד: 

if totalPrice > 200: 

  print(‘The price after reduction is: ‘, totalPrice – 50)

elif totalPrice > 150: 

  print(‘The price after reduction is: ‘, totalPrice – 40)

elif totalPrice > 100: 

  print(‘The price after reduction is: ‘, totalPrice – 30)

elif totalPrice > 50: 

  print(‘The price after reduction is: ‘, totalPrice – 20)

else:

  print(‘No change in final price.’)

print(‘Total price is: ‘, totalPrice) 

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

בכל הנוגע לזרימת הקוד, היא יכולה להגיע לסיומה גם אם לא ייבדקו כל התנאים. לדוגמה אם מצאנו שהסכום אינו גדול מ-150 וגם גדול מ-100, תתבצע הוראת ההדפסה המודיעה על ההנחה (30 ש”ח), הקוד לא ימשיך לבדוק אם הסכום גדול מ-50, ותודפס ההודעה בדבר העלות הסופית. 

(9) סיכום

בפרק זה למדנו כמה מבנים בשפה המאפשרים להתנות ביצוע של קוד. ראינו כי ההתניות במבנים אלה מבוססות על בדיקת תוצאתם של ביטויים לוגיים: כך הדברים בהרצה של מבנה if, וכך הדברים בביצוע ההוראות בחלק ה-else וההוראות בחלק ה-elif, אם חלקים אלה נלווים ל-if. למדנו לכתוב ביטויים לוגיים באמצעות סימני השוואה ולהרכיב אותם באמצעות האופרטורים and, or ו-not. בפרקים שיבואו נעיין באופנים נוספים לכתיבת ביטויים לוגיים, וגם ניווכח כי יש לביטויים אלה שימושים חשובים אחרים בשפה. בין השאר הם מאפשרים לבצע קטע קוד מספר פעמים לפי תוצאת חישוב של ביטוי לוגי, וספציפית: לכתוב לולאת while – נושאו של הפרק הבא.