פונקציות

הגדרה

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

  • קלט – טמפרטורה מסוימת
  • תהליך – המרת הטמפרטורה למעלות צלזיוס
  • פלט – החזרת התוצאה

פונקציות הן למעשה אבני הבניין של תוכנה – כל פונקציה שואפת למלא תפקיד מוגדר בתוכנה, ובעזרת הרבה אבני בניין שכאלו אפשר לבנות תוכנה מורכבת.
התוכנות שבהן אתם משתמשים ביום־יום מורכבות בדרך כלל מכמות רבה מאוד של פונקציות.

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

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

דוגמאות

אחת הפונקציות שכמעט כולם מכירים היא העלאה בריבוע.
הקלט של הפונקציה הוא מספר כלשהו, התהליך שקורה בפונקציה הוא הכפלת המספר בעצמו, והפלט הוא תוצאת המכפלה.
לדוגמה, הקלט של פונקציה בשם "העלאה בריבוע" יכול להיות 5, והפלט שלה יהיה 25.
דוגמאות נוספות לקלט הן -3, שעבורו הפלט יהיה 9, או 0.5, שעבורו הפלט יהיה 0.25.

רעיונות נוספים לפונקציות

  • בהינתן שני מספרים, בדוק מי הגדול ביניהם והחזר אותו.
  • בהינתן מספר כלשהו, החזר את סכום כל המספרים הזוגיים מ־0 ועד אליו.
  • בהינתן שני מספרים ופעולת חשבון, החזר את תוצאת התרגיל.
  • בהינתן שם משתנה, בדוק מה הסוג שלו (נשמע מוכר?)
  • בדוק מה הטמפרטורה הצפויה הממוצעת ב־n הימים הקרובים והחזר את התוצאה.

כתיבת פונקציה

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

  1. מצאו את כמות הפחמימות במוצר והכפילו ב־4.
  2. מצאו את כמות השומן במוצר והכפילו ב־9.
  3. מצאו את כמות החלבון במוצר והכפילו ב־4.
  4. כמות הקלוריות במוצר היא חיבור הערכים שקיבלתם בשלבים 1–3.

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

חשוב!
פתרו לפני שתמשיכו!

והנה הפתרון לשאלה מלמעלה (אזהרת ספוילר!)


In [ ]:
carbs = int(input("How many carbohydrates does this product have?: "))
fat = int(input("How much fat does this product have?: "))
protein = int(input("How much protein does this product have?: "))

total_calories = carbs * 4 + fat * 9 + protein * 4
print("This product has " + str(total_calories) + " calories in it.")

הגדרת הפונקציה

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


In [ ]:
def calculate_calories():
    carbs = int(input("How many carbohydrates does this product have?: "))
    fat = int(input("How much fat does this product have?: "))
    protein = int(input("How much protein does this product have?: "))

    calories = carbs * 4 + fat * 9 + protein * 4
    print("This product has " + str(calories) + " calories in it.")

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

קריאה לפונקציה

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


In [ ]:
calculate_calories()

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

מזל טוב! יש לנו פונקציה עובדת.
זה אפילו היה די קל:

  1. הגדרנו פונקציה בעזרת הקוד def function_name():, כש־function_name הוא בעצם השם של הפונקציה.
  2. מייד אחרי השורה הזו, כתבנו את גוף הפונקציה – מה היא עושה בפועל. בחלק הזה שמרנו על הזחה.
  3. קראנו לפונקציה בציון השם שלה, ואז סוגריים. כך הפעלנו את הפונקציה, וגרמנו לכך שגוף הפונקציה ירוץ.

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

טרמינולוגיה

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


In [ ]:
#    שם הפונקציה
def hello_world():               # Function Header / כותרת הפונקציה
    print("Hello World!")        # גוף הפונקציה (מוזח!)

hello_world()                    # הקריאה לפונקציה

פרמטרים

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


In [ ]:
def calculate_calories():
    calories = carbs * 4 + fat * 9 + protein * 4
    print("This product has " + str(calories) + " calories in it.")


carbs = int(input("How many carbohydrates does this product have?: "))
fat = int(input("How much fat does this product have?: "))
protein = int(input("How much protein does this product have?: "))
calculate_calories()

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

בתוך הפונקציה אנחנו מתייחסים למשתנים fat, protein ו־carbs, שאינם חלק מהפונקציה.
ייתכן שבעתיד מישהו יעתיק את הפונקציה calculate_calories לתוכנית שלו, והמשתנים הללו לא יהיו מוגדרים בגוף התוכנית.
במקרה כזה, לפונקציה לא יהיה מאיפה לקחת את הערכים והיא תקרוס.

הדרך להתמודד עם הבעיה הזו היא לחייב את הפונקציה לקבל באופן מסודר את הנתונים האלו מבחוץ.
נראה דוגמה:


In [ ]:
def calculate_calories(carbs, fat, protein):
    calories = carbs * 4 + fat * 9 + protein * 4
    print("This product has " + str(calories) + " calories in it.")

שימו לב לכותרת הפונקציה.
הכנסנו לשם את שמות 3 המשתנים הדרושים להרצת הפונקציה.
אם תרצו, תוכלו להסתכל על זה כ"הקלט שנדרש עבור הפונקציה", או במקרה שלנו: "הנתונים שדרושים כדי לחשב את כמות הקלוריות במוצר".
החלק הזה שהוספנו לפונקציה נקרא הפרמטרים של הפונקציה: כל אחד מהנתונים carbs, fat ו־protein הוא פרמטר.

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

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


In [ ]:
calculate_calories(50, 90, 20)

אם כך, בארוחה שבה 50 גרם פחמימות, 90 גרם שומן ו־20 גרם חלבון, יש כ־1,090 קלוריות.

נסכם את מה שעשינו עד עכשיו ונרענן את הטרמינולוגיה שלנו:


In [ ]:
#       שם הפונקציה
#                               פרמטרים
def calculate_calories(carbs, fat, protein):  # כותרת הפונקציה
    calories = carbs * 4 + fat * 9 + protein * 4
    print("This product has " + str(calories) + " calories in it.")


product_carbs = int(input("How many carbohydrates does this product have?: "))
product_fat = int(input("How much fat does this product have?: "))
product_protein = int(input("How much protein does this product have?: "))
#                                        ארגומנטים
calculate_calories(product_carbs, product_fat, product_protein)

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

ערך החזרה

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

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

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

אוקיי, על פניו יש דרך פשוטה למדי לטפל בזה.
בואו ננסה להפעיל את הפונקציה, ואז ניגש לערך calories שנמצא בתוכה!


In [ ]:
def calculate_calories(carbs, fat, protein):
    calories = carbs * 4 + fat * 9 + protein * 4

calculate_calories(5, 30, 5)
print(calories)

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

אז איך בכל זאת אפשר לקבל את תוצאת החישוב שלנו מתוך פונקציה?
הביטו על הפונקציה הבאה:


In [ ]:
def calculate_calories(carbs, fat, protein):
    calories = carbs * 4 + fat * 9 + protein * 4
    return calories

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

ננסה לקרוא לפונקציה החדשה שהגדרנו, ונראה מה יקרה:


In [ ]:
calculate_calories(50, 17.5, 36)

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


In [ ]:
print("Calories in a Hamburger: " + str(calculate_calories(50, 17.5, 36)))
print("Calories in 2 Hamburgers: " + str(2 * calculate_calories(50, 17.5, 36)))

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


In [ ]:
print("Calories in a Hamburger: " + str(501.5))
print("Calories in 2 Hamburgers: " + str(2 * 501.5))

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


In [ ]:
calories_in_hamburger = calculate_calories(50, 17.5, 36)
print("Calories in a Hamburger: " + str(calories_in_hamburger))
print("Calories in 2 Hamburgers: " + str(2 * calories_in_hamburger))

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


In [ ]:
#       שם הפונקציה
#                               פרמטרים
def calculate_calories(carbs, fat, protein):  # כותרת הפונקציה
    calories = carbs * 4 + fat * 9 + protein * 4
    return calories  # ערך ההחזרה


product_carbs = int(input("How many carbohydrates does this product have?: "))
product_fat = int(input("How much fat does this product have?: "))
product_protein = int(input("How much protein does this product have?: "))
#                                     ארגומנטים
cal = calculate_calories(product_carbs, product_fat, product_protein)
print("This product has " + str(cal) + " calories in it.")

עקרונות נוספים

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


In [ ]:
def give_me_numbers(number):
    return number + 1
    return number + 2
    return number + 3

print(give_me_numbers(5))

במקרה הזה, הערך היחיד שחזר הוא 6.
הסיבה לכך היא שאחרי השורה return number + 1, הפונקציה החזירה ערך והפסיקה לרוץ.

דוגמה נוספת

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


In [ ]:
def absolute_value(number):
    if number < 0:
        number = number * -1
    return number

print(absolute_value(-5))

תרגול: כתבו פונקציה שמקבלת שני מספרים ומחזירה את הגדול מביניהם.
רוצים אתגר? פתרו את התרגיל ב־4 שורות.

מזהים?

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

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


In [ ]:
print(len('hello world'))

In [ ]:
# פתרו לפני שתריצו: מה יהיה הערך שיודפס? מה ההבדל בין האגפים?
len('hello world') * 2 == len('hello world' * 2)

מטרות
או: למה לי להשתמש בפונקציות בכלל

קְרִיאוּת

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

מניעת חזרה

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

מונחים

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

לסיכום

פונקציה היא מעין יחידת תוכנה בסיסית וקטנה.
היא עוזרת לנו לחלק את התוכנה שלנו לתתי־משימות, ועושה אותה לקריאה יותר ולקלה יותר לתחזוקה.
את הפונקציה אנחנו מגדירים בעזרת כותרת הפונקציה, שמכילה את מילת המפתח def, ואז את שם הפונקציה ואת הפרמטרים שהיא אמורה לקבל.
מייד לאחר כותרת הפונקציה נגדיר בהזחה את גוף הפונקציה – שכולל את החישובים או את הפעולות שהפונקציה צריכה לבצע,
ובסוף נבצע החזרה לערך ההחזרה שיופיע אחרי מילת המפתח return.
כדי להשתמש בפונקציה נקרא לפונקציה בהמשך הקוד על ידי כתיבת השם שלה, ובתוך סוגריים נפרט את הארגומנטים, שהם הערכים שנרצה להעביר לפונקציה.

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

תרגול

תרגיל לדוגמה: מרתון

דני מתאמן למרתון הקרוב. הוא מתחיל להתכונן על אש נמוכה, ורץ אתמול 5 קילומטרים.
כתבו פונקציה שמקבלת כמה שעות לקח לדני לגמוע את 5 הקילומטרים הללו, ומחשבת מה קצב הריצה הממוצע של דני, בקמ"ש.
כתבו פונקציה נוספת שבודקת אם דני יכול להשלים מרתון בתוך 3 שעות.
אורכו של מסלול מרתון הוא 42.195 קילומטר.

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

$$speed = \frac{distance}{time}$$$$time = \frac{distance}{speed}$$$$distance = {time}\cdot{speed}$$

הפתרון מופיע בתחתית המחברת.

האריך במילים

כתבו פונקציה שמקבלת 3 מחרוזות כארגומנטים ומחזירה את המחרוזת הארוכה יותר מביניהן.

פיזבאז

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

כתבו פונקציה שמקבלת מספר.
אם המספר מתחלק ב־3 ללא שארית, הדפיסו Fizz.
אם המספר מתחלק ב־5 ללא שארית, הדפיסו Buzz.
אם המספר מתחלק גם ב־3 וגם ב־5 ללא שארית, הדפיסו FizzBuzz.
אם המספר לא מתחלק ב־3 ולא מתחלק ב־5, הדפיסו את המספר עצמו.

לדוגמה, עבור המספר 9 הדפיסו Fizz,
עבור המספר 10 הדפיסו Buzz,
עבור המספר 15 הדפיסו FizzBuzz,
ועבור המספר 7 הדפיסו 7.

מספר הפוך

כתבו פונקציה שמקבלת מספר דו־ספרתי שספרת האחדות שלו שונה מ־0.
הפונקציה תחזיר את המספר הפוך.
לדוגמה: עבור 53 הפונקציה תחזיר 35. עבור 19 הפונקציה תחזיר 91. עבור 91 הפונקציה תחזיר 19.

מפענח הצפנים

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

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

לדוגמה, אם המשתמש הקיש בניסיון הראשון 0634, הדפיסו לו שרק אחת הספרות שניחש נכונה.
אם המשתמש הקיש בסיבוב השני 1234, הדפיסו לו ש־3 ספרות תואמות את הקוד המקורי.
אם המשתמש הקיש בסיבוב השלישי 1284, הדפיסו לו ש־4 ספרות תואמות את הקוד המקורי, ואז הדפיסו לו שהופעלה האזעקה.
אם המשתמש הקיש באחד הסיבובים 4812, הדפיסו שהכספת נפתחה בהצלחה וסיימו את התוכנית מייד.

סכום מספרים

קבלו מספר וחשבו את העצרת שלו – מכפלת כל המספרים עד אותו מספר.
לדוגמה, 5 עצרת שווה ל־1 כפול 2 כפול 3 כפול 4 כפול 5, והתוצאה היא 120.
זהירות! זה תרגיל בונוס, והוא קשה מאוד. מאוד. מאוד מאוד. אנחנו לא אומרים סתם. הוא לא חובה ומיועד לאנשים שרוצים לאתגר את עצמם. מאוד.

פתרון התרגול לדוגמה: מרתון


In [ ]:
def calculate_km_per_hour_for_5_km(hours_to_finish):
    km_per_hour = 5 / hours_to_finish
    return km_per_hour


def check_if_run_marathon_in_three_hours(km_per_hour):
    hours_to_finish_marathon = 42.195 / km_per_hour
    return hours_to_finish_marathon <= 3


time = float(input("How many hours did it take to finish a 5km run? "))
km_per_hour = calculate_km_per_hour_for_5_km(time)
can_run_marathon_in_three_hours = check_if_run_marathon_in_three_hours(km_per_hour)

if can_run_marathon_in_three_hours:
    print("Yes you can!")
else:
    print("No you can't!")

בואו ננקה, נסדר ונהפוך דברים ליותר כלליים:


In [ ]:
MARATHON_DISTANCE = 42.195


def calculate_km_per_hour(km_to_run, hours_took_to_finish):
    km_per_hour = km_to_run / hours_took_to_finish
    return km_per_hour


def calculate_time_to_run(distance_to_run, km_per_hour):
    hours = distance_to_run / km_per_hour
    return hours


def print_if_can_run(target_time, actual_time):
    # זה בסדר להדפיס פה, כי זה ממש המטרה של הפונקציה.
    if actual_time <= target_time:
        print("Success! You can do it!")
    else:
        print("You can't do it :(")


time = float(input("How many hours did it take to finish a 5km run? "))
km_per_hour = calculate_km_per_hour(5, time)
hours_to_finish = calculate_time_to_run(MARATHON_DISTANCE, km_per_hour)
print_if_can_run(3, hours_to_finish)