פייתון/פייתון גרסה 3/פונקציות המתכנת

הגדרה

עריכה

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

לדוגמה, עבור כל   היא תוכל למצוא את ערך ה-  המתאים לו לפי ההגדרה אותה נקליד.

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

מדוע צריך פונקציה?

עריכה

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

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

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

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

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

איך כותבים פונקציה?

עריכה

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

לאחר הסוגרים יורדים שורה ומזיחים את הפקודות בארבעה רווחים (whitespace). כל הזחה נקראת רמה (level).

הפונקציה מסתיימת בפקודת return. [1]

def <name>(<parameters >):
'''documentation'''
    <Statements>
    return

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

עריכה
  • name הוא שם הפונקציה אותה מקליד המשתמש. מערכת פיתון אינה יודעת לזהות רווח ועל כן אם נרצה לתת שם ארוך ממילה אחת נעזר בקו תחתון (_)
  • documentation הוא תיעוד של הפונקציה.
  • Statements הם רצף של פקודות רצופות אותם מקליד המשתמש. במידה ותרצו לדלג על כתיבת הפונקציה תוחלפו להעזר ב-pass.
  • arguments הוא ביטוי אותו מקליד המשתמש וגורם לפונקציה לפעול. למשל, אחת הפונקציות הראשונות שהכרנו הייתה type, באמצעותה יכולה המשתמש לדעת מה הטיפוס אותו הוא מקליד במערכת.
<<<type ('I love you')
<<class str>
המחרוזת "I love you" היא הארגומנט של הפונקציה באמצעותה המערכת מתחילה לפעול. ניתן לייבא ארגומנטים גם דרך ה-#שורת הפקודות
    • פרמטר הוא סוג של ארגומנט

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

עריכה

לאחר שנכתוב את הפונקציה נרצה לקרוא לה (function call), דהינו, להשתמש בה. לשם כך נקליד את שם הפונקציה ואחריו סוגרים מסולסלים name().

נקליד את הפונקציה שבכל פעם שקוראים לה מקלידה את המחרוזת "hello world! I love you"

הפונקציה צריכה להראות כך:

def hello_world ():
    print('hello world! I love you!')
    return

בכדי לקרוא לה נקליד את הקלט:

>>>hello_world()
hello world! I love you!

לקרוא למיקום הפונקציה בזכרון:

print(hello_world)
>>><function hello_world at 0x03B1BAE0>

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

פרמטרים

עריכה

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

def solve(a,b):
    return 2*a+5*b
>>> solve(5,6)
40
>>>print(x)
בדוגמה זו שני פרמטרים מפעילים את הפונקציה.

ברירת מחדל של פרמטרים (parameters default value)

עריכה

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

def area_triangle(a, b, area=2):
    print(a*b *(1/area))
>>> area_triangle(4,5)
10.0
>>> area_triangle(4,5,6)
3.333333333333333
במקרה השני הפונקציה לא השתמש בברירת המחדל אלא בפרמטר אותו בחר המשתמש.

נהוג להציב את הפונקציות בראשית רצף הפקודות ואחריה יתר הפקודות.

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

#the function is print a name and the numbers of kids the person has

def How_many(name, *kids_ages):
    print(name)
    print(kids_ages)

How_many('Dani', 2, 23,45,65)

Dani
(2, 23, 45, 65)

**kwargs

עריכה
def data_print(**data):
    print (data)

data_print(name = 'Alon')
>>>{'name': 'Alon'}

שגיאות נפוצות

עריכה

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

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

def multiplication(str1, str2):
    return str1 * str2

print(multiplication(1, 2))

print(multiplication('ab', 'cd'))

>>>2
>>>Traceback (most recent call last):
  File "C:\Users\user\Downloads\de\a.py", line 9, in <module>
    print(multiplication('ab', 'cd'))
  File "C:\Users\user\Downloads\de\a.py", line 5, in multiplication
    return str1 * str2
TypeError: can't multiply sequence by non-int of type 'str'

הפונקציה מסתיימת אחר המילה return גם אם קיימות אחריה מילים נוספות.

החזרת ערך חזרה יחיד

עריכה
def square(x):
    return x*x
>>> square(5)
25

החזרת שני ערך חזרה

עריכה

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

x=0
def square(x):
    return x*x, 3*x

>>> square(4)
(16, 12)

פעולות אחרי return

עריכה

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

def name_Alex():
    return 'Alex'
    print('Dana')

ערך החזרה

עריכה

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

פונקציה עם retun מחזירות "ערך חזרה" (return value) בו ניתן להשתמש עבור ערכים אחרים.

def minute(second=1):
    return second / 60

print('value return', minute())

def hours(how_many_hours):
    return how_many_hours / 60

print('minutes in an hour : ' + str(hours(minute())))

נבצע הפעלה:

value return 0.016666666666666666
minutes in an hour : 0.0002777777777777778

הפונקציה שניות (minute) יכולה להריץ עצמה באמצעות ברירת המחדל ומייצרת ערך החזרה 0.166.

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

ערך החזרה None

עריכה

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

def hello_world():
    print('hello_world')
x = hello_world()

print(x)

hello_world
None

המשתנה x מפעיל את הפונקציה שלנו hello world. נאחר שהיא ללא ערך חזרה מדפיס לנו פיתון שלפונקציה hello_world אין ערך (none).

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

תיעוד

עריכה

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

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

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

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

def zero_lst(lst):
    lst[0]=0

list_1=[1,2,3]
zero_lst(list_1)
print(list_1)

משתנים גלובליים, מקומיים

עריכה

המשתנים והפרמטרים בפונקציה נקראים "משתנים מקומיים" (Local variables) לעומת הפרמטרים שנמצאים מחוץ לפונקציה ונקראים "משתנים גלובלים" (global). בעוד אנו יכולים לשנות את המשתנים המקומיים, לא נוכל לשנות את הערכים הגלובליים.

x=0
def square():
    x=2
    return 4*x+x

print(x)

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


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

y=0
def a():
    y=1
    print(y)

#print the vaule of the function:
a()

#print vaule y:
print('the vaule of y is: ', y)

>>>1
>>>the vaule of y is: 0

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

טווח (scope) הוא התחום בו מוגדר המשתנה. יש לנו שני טווחים שונים עבור הערך y. אחד בתוך הפונקציה והשני מחוץ לו.


פונקציה ללא משתנה גלובלי תחזיר הודעת שגיאה:

counter = 1
def number(): 
    for i in (1,2,3):
        counter +=1
number()
print(counter)
>>>Traceback (most recent call last):
  File "C:/Users/user/Downloads/de/t4.py", line 16, in <module>
    number()
  File "C:/Users/user/Downloads/de/t4.py", line 15, in number
    counter +=1
UnboundLocalError: local variable 'counter' referenced before assignment

אם נרצה להגדיר את המשתנה שבפונקציה לפי המשתנה הגלובלי נוכל להעזר ב-global:

counter = 1
def number():
    global counter  
    for i in (1,2,3):
        counter +=1
number()
print(counter)
>>>4

הפונקציה global מקבלת את המשתנה הגלובלי ומפעילה אותו בפונקציה. נשם לב כי המשתנה הגלובלי שנה את ערכו!

הערכים של פונקציה

עריכה

נבחן את הערכים שמחזירה פונקציה:

def exm (a,b):
    return (a, b)

print(type(exm))
print(type(exm(2, 3)))

def number (a):
    return (a)

print(type(exm))
print(type(exm(2, 3)))
print(type(number(2)))

<class 'function'>
<class 'tuple'>
<class 'function'>
<class 'tuple'>
<class 'int'>

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

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

עריכה

קיימות פונקציות מקוננות במערכת ומוגרת לבצע פעולות שונות במערכת כמו פונקצית  . רשימה מלאה: רשימת פונקציות מערכת built-in

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