פייתון

פייתון (באנגלית: Python) היא שפת תכנות עילית דינמית למטרות כלליות מהנפוצות ביותר, ומדורגת באופן עקבי כאחת משפות התכנות הפופולריות ביותר. פייתון תוכננה תוך שימת דגש על קריאוּת הקוד, וכוללת מבנים המיועדים לאפשר ביטוי של תוכניות מורכבות בדרך קצרה וברורה. אחד המאפיינים הבולטים בתחביר השפה הוא השימוש בהזחה להגדרת בלוקים של קוד (ללא שימוש בסוגריים או במילים שמורות לצורך כך, כמו ברוב השפות הנפוצות). פייתון היא שפה מרובת־פרדיגמות, המאפשרת תכנות מונחה־עצמים, תכנות פרוצדורלי, ובמידה מסוימת גם תכנות פונקציונלי. לשפה ספרייה סטנדרטית גדולה וענפה, והיא תומכת באופן מובנה בהרחבה שלה אל שפות אחרות (בתלות במפרש: C‏, ++C,‏ Java‏ ו־#C). לשפה שתי גרסאות ראשיות, פייתון 2 ופייתון 3. פייתון 2 איננה בפיתוח יותר, והתמיכה בה הסתיימה בשנת 2020. השפה נוצרה על ידי חידו ואן רוסום בתחילת שנות התשעים, במקור בתור פיתוח של שפת התכנות ABC אשר יוכל לטפל בחריגות עבור Amoeba OS. מאז השתנתה השפה בצורה משמעותית, וגם כיום נמשך הפיתוח ומוכנסים שינויים רבים. השפה תומכת באופן מובנה בעדכון גרסאות, ומושם דגש על תאימות־לאחור של גרסאות שונות. עם זאת, גרסה 3 של פייתון איננה תואמת באופן מלא לגרסאות קודמות. (הקוד המופיע בערך זה תואם לגרסה 3.0 ומעלה, ועבור גרסאות ותיקות יותר יש לבצע שינויים מינוריים). זכויות היוצרים על גרסאות פייתון החל מ־2.1 שייכות לקרן התוכנה של פייתון. פייתון פותחה מתוך רצון להגיע לשפה פשוטה ומובנת, נוחה לקריאה וקלה לתחזוקה. לנגד עיניהם של מפתחי השפה, עמדה המטרה לאפשר קוד "יפה", "מפורש" ו"פשוט". בין הכללים על פיהם מתוכננת השפה: "צריכה להיות דרך אחת, ועדיף אחת בלבד, לבצע זאת" (כתגובה לתפיסה של התכנות בשפת פרל: "יש יותר מדרך אחת לבצע זאת"). "כולנו אנשים בוגרים כאן" – כלומר, אפשר לסמוך על מתכנת המשתמש בקוד קיים שלא יבצע בו דברים שברור שלא התכוונו אליהם מלכתחילה (בין היתר, כנימוק לשאלה מדוע השפה תומכת בכימוס פחות משפות מונחות־עצמים אחרות). תוכניות פייתון נכתבות בקובצי טקסט, שעל־פי קונבנציה נשמרים במערכת ההפעלה בסיומת py. תוכניות פייתון עשויות לכלול קבצים רבים. על מנת להריץ קוד פייתון יש לבחור מימוש – מהדר או מפרש – שיתרגם את הטקסט של התוכנית לפקודות שיתבצעו במעבד. לפייתון קיים "מימוש־ייחוס" כלומר מערכת שהיא זו שמגדירה את ההתנהגות של קוד שנכתב בשפה – בשם CPython. המימוש־ייחוס פועל בשני שלבים נפרדים: הידור והרצה. בשלב הראשון, קוד פייתון מהודר לשפת ביניים נמוכה, מבוססת מחסנית (Bytecode). תוצאת ההידור הזה נשמרת בקבצים עם הסיומת pyc. בעת הרצה, סביבת זמן הריצה (המפרש) מריצה את קוד הביניים. לעיתים קרובות שני השלבים מתבצעים בתגובה לפקודה בודדת של המשתמש (כגון לחיצה כפולה על אייקון של קובץ שנכתב בשפה), אך תוצאת השלב הראשון נשמרת בקובץ נפרד כך שבהיעדר שינוי לקובץ הטקסט (קובץ py.) אין צורך לחזור על פעולת ההידור. כמו עבור כל שפת ביניים, יש להתקין מפרש פייתון על המכונה המבצעת, שמסוגל להריץ את קוד הביניים הנתון; מפרשים הם סטנדרט המובנה ברוב ההפצות של לינוקס, אך עבור מערכות הפעלה אחרות (כגון חלונות) יש לבצע התקנה עצמאית. בנפרד מהתהליך המתואר לעיל, CPython תומך במצב פיתוח אינטראקטיבי, המאפשר לכתוב שורות קוד בודדות אשר יורצו מידית. מצב זה מאפשר לראות במהירות מה יהיו התוצאות של חלקים קטנים מהקוד, לערוך ניסויים, או לשמש כמחשבון שולחני. מלבד CPython ישנם מימושים נוספים לשפה, בהם כאלה המשתמשים במנגנון JIT, וקיימים גם קומפיילרים לשפה המהדרים קוד של השפה אל שפת מכונה, לעיתים דרך שפת ביניים כגון ++C. IPython מהווה מעטפת פקודה לשפת תכנות זו. פייתון היא שפה שתומכת בשימוש במספר פרדיגמות תכנות שונות. ניתן לכתוב קוד מונחה עצמים, פרוצדורלי ובמידה מסוימת תכנות פונקציונלי. תכנות גנרי נתמך בשפה באופן טריוויאלי, בדומה לכל שפה בעלת טיפוסיות דינמית. פייתון מאפשרת ואף מעודדת התבוננות־פנימה (Reflection), ותומכת בתכנות מקבילי ותכנות מוכוון־אירועים (אנ') באמצעות מודולים מתאימים בספרייה הסטנדרטית. פינוי הזיכרון מבוצע בצורה אוטומטית, על ידי מנגנון איסוף זבל, בעיקר תוך שימוש במניית התייחסויות, ולא דורש התייחסות מפורשת מצד המתכנת. אובייקטים מוקצים על גבי הערימה, כאשר הם נוצרים על ידי קריאה למחלקה, למשל (x=str(15 ‏, או על ידי הצבה של ליטרלים בשפה – הכוללים מספרים, מחרוזות, רשימות, מילונים, פונקציות למבדה, או על ידי קריאה לפונקציה שיוצרת אותם. שני מנגנונים נוספים הם List Comprehension ו־Generators, שיתוארו בהמשך. המשתנים עצמם, "הרפרנסים", הם מחרוזות פשוטות המשמשות כמפתחות במילון שמגדיר את תחום ההכרה (scope) הנוכחי. בשפות רבות אין משמעות תכנותית להזחה כשלעצמה: כל בלוק מוקף בתווי בקרה מיוחדים המסמנים את תחילתו וסופו של הבלוק, אף ללא כל הזחה (סוגריים מסולסלים ב־C או Perl, ו־begin ו־end בפסקל וב־VB). בפייתון, המבנה של בלוקים של קוד בתוכנית נקבע על ידי ההזחה שלהם: עצם הזחת הבלוק מגדירה אותו כבלוק תכנותי שונה, באופן שמזכיר את שיטת העבודה ב־Haskell. תכונה זו מיועדת לשפר את קריאות התוכנית, בכך שהיא כופה על המתכנת כתיבה בסטנדרט אחיד (פחות או יותר), וחוסכת בקוד. מקדימים תמיד את התו ':' (נקודתיים) לבלוקים של קוד – בלולאות, מחלקות, פונקציות וכדומה. תנאים בפקודות תנאי ולולאות נכתבים ללא סוגריים, ומזוהים על ידי המהדר בעזרת מילים שמורות ותו ':' המופיע לאחריהם. פקודות מופרדות לרוב על ידי מעבר שורה. שימוש בתו ';' (נקודה ופסיק) להפרדה בין פקודות הוא אופציונלי, וכמעט שלא בשימוש בפועל. מערכת הטיפוסים בפייתון היא בעלת המאפיינים הבאים: חזקה: לא ניתן להפעיל על משתנה פעולה שלא מוגדרת על הטיפוס אליו הוא שייך. לדוגמה, ניסיון לבצע פעולת חזקה בין שתי מחרוזות – גם אם הן מסמנות מספרים, למשל "5" בחזקת "6" – יגרור שגיאה. דינמית: האובייקטים, ולא המשתנים בשפה, הם השייכים לטיפוס. כל משתנה בשפה יכול להצביע על אובייקט מכל טיפוס. כאשר מגדירים פונקציה, אין הגבלה על סוג הטיפוס שיועבר בכל קריאה אליה. ייתכן שבקריאה אחת יועבר מספר שלם, ובקריאה אחרת תועבר מחרוזת. הטיפוסיות היא "טיפוסיות ברווז" (Duck Typing), דהיינו נקבעת על פי הפעולות אותן ניתן לבצע על המשתנה. אם יש צורך לוודא כי משתנה שהתקבל כפרמטר בפונקציה, לדוגמה, הוא מטיפוס "מספר שלם", יש לבצע בדיקה מפורשת (בדרך כלל בעזרת פקודת assert או if). מובלעת: אין הכרזה על קיום משתנים. שם של משתנה מוגדר אם הוא מופיע בצידה השמאלי של פעולת השמה, כפרמטר לפונקציה, כמשתנה לולאה, כפרמטר לתפיסה של חריגה או בפקודת del. מאפיין זה מאפשר גמישות רבה בכתיבת הקוד, וכתיבת קוד קצר יותר, אך מנגד מקשה על זיהוי ואיתור שגיאות בזמן ההידור, ומקשה על איתור טעויות הקלדה. סמנטיקת התייחסות (Reference): משתנים הם שמות של מצביעים (References) אל אובייקטים, ולא שמות של האובייקטים עצמם. כאשר מתבצעת פעולת השמה בין משתנים בצורה x=y, לא מועתק תוכן האובייקט אליו מצביע y. במקום זה, המשתנה x מוגדר כך שיצביע אל אותו אובייקט אליו מצביע y. פרמטרים לפונקציות מועברים על ידי העתקה של המצביעים אליהם. טכנית זו "קריאה על ידי ערך" (Call by Value) אך רבים (ובהם ממציא השפה) מכנים זאת "קריאה על ידי התייחסות לאובייקט" (Call by Object Reference). קריאה לפונקציה בצורה (foo(x, שבתוכה מבצעים x=5, לא תגרום למשתנה x להתייחס לאובייקט אחר מזה שהוא התייחס אליו קודם. טווח הכרה סטטי (או לקסיקלי): שם של משתנה מוגדר רק בקטעי קוד המוכלים בקטע שבו בוצעה אליו פעולת כריכה. למשל, משתנה בשם x המוגדר בתוך פונקציה אחת לא יהיה קשור בשום דרך למשתנה x המוגדר בפונקציה אחרת. השפה תומכת במגוון גדול יחסית של טיפוסי נתונים בסיסיים. בין המרכזים שבהם ניתן למנות: טיפוס הנתונים int מאחסן מספר שלם. בגרסה 3.0 אוחד טיפוס זה אל תוך long (בגרסאות x.‏2 מספרים מטיפוס long מסומנים באות L בקצה), ואין לו הגבלת גודל (מעבר למה שמאפשר הזיכרון הווירטואלי של המחשב) – אין בשפה כל קושי לחשב את מספר פיבונאצ'י ה־100,000 (בדומה ל־BigInteger בשפת Java). טיפוס הנתונים נקודה צפה (float) מאפשר אחסון ערך מקורב של מספר ממשי באמצעות ייצוג נקודה צפה. טיפוס זה זהה לטיפוס double בשפת C (ולמעשה ברוב המקרים ממומש על ידיו). בנוסף, ניתן לייבא את המודול decimal המאפשר ייצוג של שברים עשרוניים, ונוח יותר לעבודה במקרים בהם הייצוג הזה מדויק יותר (כגון חשבונאות). מספר מרוכב גם הוא נתמך בפייתון (נכתב בצורה 3+4j). טיפוס זה נוסף לשפה בשל השימוש הרב שעושים בו מדענים ומהנדסים, שהם אחת מהקהילות העיקריות המשתמשות בשפה, ועל מנת למנוע מהם את הצורך "להמציא את הגלגל" בכל פעם מחדש. ישנה תמיכה מובנית במחרוזות – str. מחרוזת לא נחשבת לטיפוס סדרתי (ראה בהמשך), כיוון שאין בשפה טיפוס מסוג תו, וההתייחסות לתו בודד היא כאל מחרוזת באורך 1. עם זאת, ניתן לגשת אל כל תו במחרוזת באמצעות גישה לפי אינדקס, כמו בטיפוסים הסדרתיים, וניתן להמיר ביניהם בקלות. ניתן לכתוב מחרוזות הן בעזרת גרשיים כפולים: "hello" והן בעזרת גרש יחיד: 'hello'. אין כל הבדל בין צורות אלו, אך מקובל להשתמש בגרש יחיד. מחרוזות הנכתבות בין שלושה גרשיים רצופים – """hello""" או '''hello''' – ניתן לפרוש על פני מספר שורות ברצף. החל מגרסה 3, המחרוזות הן Unicode, אם כי ישנו טיפוס bytes עבור רצפים של בתים. בגרסה 2 המצב הפוך – המחרוזות הבסיסיות הן בתקן ASCII, וישנו טיפוס מיוחד עבור מחרוזות Unicode. אובייקטים מטיפוסי מספרים ומחרוזות הם בלתי ניתנים לשינוי (Immutable), כלומר שינוי ערכו של משתנה מטיפוס כזה הוא בעצם הסרת ההתייחסות אליו והפנייתה לערך חדש. בשפה מוגדרים שני טיפוסים סדרתיים: tuple ו־list. הטיפוס tuple הוא ייצוג ממוחשב של N־יה סדורה: רצף קבוע של ערכים מטיפוסים אחרים (כלשהם), המיוצג על פי רוב בתוך סוגריים. לדוגמה (1, 2, 3). טיפוס זה מקל על דימוי של החזרת מספר ערכים מפונקציה בודדת, או ביצוע פעולת החלפה בין משתנים (כך ניתן להחליף בין המשתנים a, b באמצעות הפקודה "a, b = b, a"). גם אובייקט מטיפוס זה איננו ניתן לשינוי, דבר המאפשר שימוש בו כמפתח עבור מילון (ראה בהמשך), בשל היכולת להשתמש בו בטבלת גיבוב. (למעשה, בשל העובדה שפייתון היא בעלת טיפוסיות דינמית, ובשל השימוש בסמנטיקת רפרנס, זהו מערך לכל דבר). המקבילה למערך בפייתון הוא מבנה הנתונים "רשימה" (list). זהו שם מטעה במקצת; על אף שמו, טיפוס זה הוא למעשה מערך שגודלו משתנה, באופן שקוף למתכנת, וניתן לגשת אל כל איבר בו על ידי אינדקס. רשימה תוגדר בין סוגריים מרובעים, לדוגמה ['x','y','z']. בניגוד ל־tuple, שתוכנו אינו ניתן לשינוי, ברשימה ניתן לשנות כל אחד מהאיברים, וכן להרחיב אותה או להסיר ממנה איברים. בשל כך, לא ניתן להשתמש ברשימות כמפתחות למילון. בשביל אופציות אחרות של מערך שאינן אפשריות ברשימה, ניתן לייבא מודול מתאים. המילון (dict), הנקרא לעיתים "מערך אסוציאטיבי" או "hash", הוא טיפוס המאפשר מיפוי ממפתחות לערכים. כל מילון כולל קבוצה של זוגות כאלה, וגישה אל איבר על פי המפתח שלו מחזירה את הערך המתאים. הקבוצה (set) היא אוסף של איברים שונים, המאפשר לבצע פעולות כמו איחוד, חיתוך, הפרש, בדיקת שייכות וכדומה. קבוצה ומילון הם טיפוסים הניתנים לשינוי, אך אין בהם סדר מוגדר. פעולת הגישה לאיברים במילון ובקבוצה ממומשת לרוב בעזרת טבלת גיבוב. החל מהגרסאות האחרונות של השפה אוחדו המחלקות והטיפוסים, וכולם שייכים למטא־מחלקה "type" (כולל המחלקה type עצמה). כאמור, פייתון היא שפה דינמית ולא מתבצעת בדיקת טיפוסים בזמן הידור. עם זאת, פייתון מאפשרת להוסיף אנוטציות – ביטויים שאין להם כל התנהגות בזמן ריצה – לפרמטרים של פונקציה ואף למשתנים, וישנה בשפה ספרייה בשם typing המאפשרת לבטא טיפוסים רבים. שילוב זה מאפשר לכתוב בשפה תוכניות אותן ניתן לבדוק על ידי כלים חיצוניים לבדיקת טיפוסים, וכך לאתר שגיאות טרם ההרצה. להלן דוגמה לקוד פייתון עם סימון טיפוסים (הסימון <- הוא עבור טיפוס ההחזרה. טיפוסי משתנים מסומנים בעזרת הערות): def fib(n: int) -> Iterator[int]: a = 0 # type: int b = 1 # type: int while a < n: yield a a, b = b, a+b רוב מבני הבקרה הנפוצים נתמכים בפייתון, כאשר החריג הבולט הוא מנגנון switch-case, שנוסף לשפה בתור match-case בגרסה 3.10. בדומה לרוב שפות התכנות, פייתון איננה כוללת תמיכה ב־Continuation. מבני הבקרה פועלים בדומה למקובל בשפות כגון ++C או בג'אווה, ולא בעזרת "בקרת זרימה הפוכה" כגון זו המשמשת בשפת סמולטוק או בחלק מהמקרים בשפות Ruby או Swift. כמו בכל שפת תכנות אימפרטיבית (מבוססת פקודות), ישנה אפשרות לביצוע מותנה של פקודות על ידי פקודת if, בה מחושב ערכו של ביטוי מסוים ומתבצע רצף פקודות במידה וערך זה הוא "אמיתי", אחרת מתבצע רצף פקודות המפורט לאחר המילה "else", אם קיים כזה. אין בפייתון מבנה switch כמו בשפות אחרות, אך ניתן להשתמש במילה elif המהווה קיצור עבור else if. ערך "אמיתי" איננו רק הערך True של הטיפוס bool, אלא כל ערך שהמחלקה שלו מגדירה אותו כאמיתי – למשל מספרים השונים מ־0, רשימות לא ריקות, מחרוזות לא ריקות, וכדומה. דוגמה לתחביר של פקודת תנאי, הבודקת אם משתנה x הוא זוגי על ידי בדיקת שארית בחלוקה ל־2, ומדפיסה הודעה מתאימה: if x % 2 == 0: print('x is even') else: print('x is odd') בפקודה זו ניתן לראות את היתרון הגדול שמעניקה ההזחה: לא תיתכן תופעה של else "מידלדל" – כל else קשור בדיוק לפקודת ה־if הרשומה הישר מעליו. זאת בניגוד לשפות כמו C, C++, Java ודומותיהן, שבהן יש צורך להבין את סדר העדיפויות של התנאי. מוקש אחר שאיננו קיים בשפה הוא השגיאה הנפוצה לכתוב = בתנאי במקום ==, ובכך לבצע פעולת השמה במקום השוואה. בפייתון פעולת השמה היא פקודה, Expression, ואיננה יכולה להיחשב לביטוי, Statement, ולכן איננה יכולה להימצא בתוך תנאי, וקוד כזה לא יעבור הידור. פייתון לא תמכה בבורר מרובה כניסות (בדומה ל־switch בשפת C ודומותיה) עד לגרסה 3.10, אך אלטרנטיבה הייתה המילה השמורה elif המאפשרת לבדוק רצף של תנאים, באופן דומה למנגנון זה: if x % 2 == 0: print('x is even') elif x % 3 == 0: print('x is divisible by 3') elif x % 5 == 0: print('x is divisible by 5') else: print("I don't know what x is") ללא המילה elif היה צורך לבצע קינון עמוק במקרה זה – טכניקה מאוד לא נוחה באופן כללי, ובפרט בפייתון שבה כל קינון נוסף מגדיל את ההזחה: if x % 2 == 0: print('x is even') else: if x % 3 == 0: print('x is divisible by 3') else: if x % 5 == 0: print('x is divisible by 5') else: print("I don't know what x is") בניגוד לשפות רבות אחרות, לפקודה else שימושים בהקשרים אחרים – לולאות וניהול חריגות. עם הזמן, לאור דרישה של מתכנתים להוסיף גם ביטוי תנאי (בדומה לאופרטור :? בשפות ממשפחת ה־C) הוסף לשפה (החל מגרסה 2.5) אופרטור מהצורה "<expr1> if <condition> else <expr2>". ערכו של ביטוי כזה תלוי בערך האמת של הביטוי האמצעי. דוגמה לשימוש באופרטור הזה, השקולה לדוגמה הקודמת: print('x is even' if x % 2 == 0 else 'x is odd') לפני שהוסף האופרטור הזה, השתמשו מתכנתים בעובדה שהערך של פעולות and ו־or בפייתון הוא הערך המשמש בהן, ולאו דווקא ערך מטיפוס bool. כך ניתן לכתוב ביטוי הדומה לביטוי תנאי בצורה "<condition> and <expr1> or <expr2>". למשל הדוגמה הקודמת תיכתב print(x % 2 == 0 and 'x is even' or 'x is odd') הדוגמה פועלת במקרה הזה, אך במקרים בהן ערך האמת של expr1 הוא שקר, הביטוי יחושב ל־expr2, גם אם condition מתקיים. קיומה של הטכניקה הזאת, יחד עם העובדה שהיא מביאה לבאגים קשים לגילוי, הביאו להכרה שאין ברירה אלא להוסיף ביטוי תנאי ייעודי לשפה. בלולאת while מחושב ערכו של ביטוי, בדומה לפקודת if, ותוכן הלולאה מתבצע כל עוד ערכו של הביטוי הוא אמת. דוגמה לתוכנית השואלת את המשתמש אם הוא אוהב דגים, וממשיכה עד שהמשתמש מכניס את המחרוזת "No": print('Do you like fish?') while input() != 'No': print('Do you like fish?') ניתן היה לוותר על השורה הראשונה בקטע הקוד, אילו היה בשפה מבנה do-while המבצע את תוכן הלולאה פעם אחת לפחות. עם זאת, אין בשפה מבנה בקרה כזה. אפשר לדמות את מבנה הבקרה הזה על ידי הצבת התנאי (בצורה הפוכה) בשורה האחרונה בלולאה: while True: print('Do you like fish?') if input() == 'No': break למימוש כזה יש חסרונות, שכן לאחר קריאה לפקודת continue בגוף הלולאה לא יתבצע שיערוך מחדש של התנאי המבוקש, בניגוד למצב בלולאה מהסוג הקודם, בלולאות for, ובלולאות do-While בשפות אחרות. מבנה נוסף ועיקרי בשפה הוא לולאת for. בלולאה זו מוגדר משתנה, ומתקבלת רשימה (או כל טיפוס שניתן לעבור עליו לפי סדר – "Iterable"). המשתנה מקבל בכל מחזור את ערכו של איבר אחר ברשימה, שוב ושוב עד שמגיעים לסוף הרשימה. מבנה זה אינו דומה ללולאת for בשפות ממשפחת ה־C, ומזכיר מעט את לולאת foreach בשפות אחרות. דוגמה לשימוש בלולאת for להדפסת רשימה של שמות עונות השנה: seasons = ["autumn","winter","spring","summer"] for season in seasons: print(season) על מנת לבצע פקודה מספר פעמים מוגדר משתמשים בפונקציה (range(x המחזירה איטרטור העובר על המשתנים בין 0 ל־x (בגרסאות קודמות של השפה החזירה פקודה זו רשימה מתאימה). דוגמה לשימוש בלולאת for להדפסת ריבועי המספרים בין 0 ל־5, לא כולל 5: for i in range(5): print(i ** 2) הלולאה משתמשת במתודה __next__ המוגדרת על כל אובייקט שניתן לעבור עליו באופן סדרתי. כאשר מגיעים לאיבר האחרון, הקריאה הבאה ל־__next__ זורקת חריגה מטיפוס StopIteration. החריגה הזאת נלכדת באופן שקט על ידי הלולאה ומביאה לסיומה. בכדי לקבוע ערך התחלתי ללולאה ואת הפרש הקפיצה בכל איטרציה יש להשתמש בפרמטרים בפונקציית range. פקודת else לאחר לולאות מגדירה רצף פקודות שיתבצע לאחר סיום תקין של הלולאה. להפסקת ביצוע לולאה בנקודה ספציפית ניתן להשתמש בפקודת break. הפקודה continue מסיימת את המחזור הנוכחי של הלולאה, ועוברת לחישוב ביטוי התנאי מחדש (בלולאת while) או לקידום המשתנה בסדרה (בלולאת for). בנוסף, מתוך פונקציה ניתן להשתמש בפקודה return המסיימת את ריצת הפונקציה כולה, ומחזירה ערך. לא ניתן לסיים באמצעות return את ריצת התוכנית הראשית, שאיננה נחשבת לפונקציה (בשונה מהמצב בשפות ממשפחת ה־C). פייתון תומכת בטיפול בחריגות. במקרה שתוכנית נתקלת בסיטואציה חריגה, על פי רוב שגיאה או נתונים עבורם תוצאת החישוב הרצויה איננה מוגדרת, ניתן "להרים" (או "לזרוק") חריגה באמצעות המילה השמורה raise (מקביל ל־throw בשפות אחרות). החריגה הנזרקת היא אובייקט, שיילכד במעלה הקריאה לפונקציה שזרקה אותו, בבלוק ייעודי מהצורה try ... except, שם יטופל באופן ספציפי. אם חריגה לא נלכדת על ידי המתכנת, היא נלכדת על ידי המפרש. התחביר של לכידת חריגות הוא מהצורה try: ... # קוד העשוי לזרוק חריגה except <Exception Type> as <Exception name>: ... # <Exception Type> קוד המטפל בחריגה מהטיפוס else: ... # קוד שיתבצע רק אם לא נזרקה חריגה finally: ... # קוד שצריך להתבצע בכל מקרה, בין אם נזרקה חריגה ובין או לא בפייתון כל שגיאה מעלה (raise) חריגה, וכל שגיאה ניתן ללכוד – חלוקה באפס, שגיאות קלט־פלט, שמות שטרם הוגדרו בקוד, וכו' – למעט שגיאות תחביר. החל מגרסה 3.0, שגיאות המוגדרות על ידי המשתמש צריכות להיות מחלקות היורשות מהמחלקה BaseException – לא ניתן לבצע פעולה כגון "raise "error, כיוון שהמחרוזת "error" היא מטיפוס str שאיננה יורשת מ־BaseException. בפייתון קיים מבנה תחבירי בשם with המאפשר "ניהול הקשר" (context management) ובפרט ניהול משאבים בעל טווח חסום (scoped resource management). המבנה מאפשר הגדרה של תחילת שימוש במשאב בתחילת ביצוע בלוק, ומבטיח שחרור של המשאב בסופו. למשל, קריאה של תוכן של קובץ והדפסתו למסך מתבצעת כך: with open('readme.txt') as f: print(f.read()) מנגנון זה מבטיח סגירת הקובץ f גם במקרה של זריקת חריגה, ביצוע של פקודת return באמצע הבלוק, או כל דרך אחרת שבה הבלוק יסתיים, זאת באופן קריא, ללא כניסה לפרטים של המשאב הספציפי (בניגוד לשימוש במבנה try-finally). ניתן להשתמש במנגנון לכל משימה הדורשת ביצוע קטע פתיחה לפני קטע קוד, וסגירה בטוחה לאחריו. לדוגמה, המנגנון מתאים לנעילה של מנעולים, כניסה לתיקייה באופן זמני, וכדומה. הפונקציות והשיטות בשפה הן אובייקטים לכל דבר. ישנם 7 סוגים של עצמים ברי־קריאה (callable) בפייתון: פונקציות מובנות ושיטות מובנות. אלה נכתבו בשפת האם של המפרש והוטמעו אל תוך השפה. פונקציות המוגדרות על ידי המשתמש, נכתבות באמצעות שימוש במילה השמורה def (קיצור של define – להגדיר). שיטות המוגדרות על ידי המשתמש, נכתבות בדומה לפונקציות, אך מוגדרות בתוך מחלקה. כל השיטות בפייתון הן סטטיות, אך כאשר קוראים לשיטה מתוך אובייקט, בצורה ()x.foo, האובייקט מועבר בתור הארגומנט הראשון. (מקובל לקרוא לו self, המקביל ל־this בשפות ממשפחת ++C, אך זו איננה מילת מפתח ולא מילה שמורה). ביטויי למדא – פונקציה אנונימיות בת שורה אחת, המוגדרת תוך שימוש במילה השמורה lambda. מחלקות – כל מחלקה בפייתון היא אובייקט מהטיפוס type, וקריאה אליה באמצעות אופרטור הקריאה לפונקציה () יוצר אובייקט מהטיפוס שלה. כל אובייקט שהוגדרה עבורו השיטה __call__, הוא אובייקט בר־קריאה (פעולה זו מקבילה להעמסה של אופרטור () בשפת ++C). בדומה למרבית שפות התכנות הפרוצדורליות, ניתן להגדיר בפייתון פונקציה – מבנה סינטקטי המגדיר חישוב ומחזיר ערך. בשל היותה שפה בעלת טיפוסיות דינמית, פונקציות בפייתון אינן מגדירות את טיפוס ההחזרה שלהן, ואינן מגדירות את טיפוסי הארגומנטים. פונקציה מוגדרת באמצעות המילה השמורה def, אחריה שם הפונקציה, ואחריו רשימה של 0 או יותר שמות של פרמטרים פורמליים (ארגומנטים) בתוך סוגריים. לאחר אלה מופיע גוף הפונקציה – בלוק המגדיר את החישוב אותו היא מבצעת. כמו כל בלוק בשפת פייתון, הוא מתחיל בנקודתיים וממשיך עד לשורת הקוד הראשונה שאיננה מוזחת עוד. פונקציה מסיימת את החישוב שבה ומחזירה ערך באחת משתי דרכים: או על ידי המילה השמורה return או על ידי הגעה לסוף הבלוק המגדיר אותה. במקרה האחרון, או כאשר פקודת return מופיעה ללא ביטוי אחריה, מוחזר מהפונקציה הערך None מהטיפוס NoneType. פונקציה עשויה להסתיים גם על ידי זריקת חריגה, אך במקרה כזה היא איננה מחזירה ערך. דוגמה לפונקציה מופיעה בתמונה משמאל. קריאה לפונקציה מתבצעת על ידי כתיבת שם הפונקציה (או כל ביטוי המתייחס אליה) ולאחריו בתוך סוגריים רשימת ארגומנטים (פרמטרים אקטואליים) המתאימה לרשימה שבהגדרת הפונקציה. העברת הפרמטרים לפונקציה מתבצעת באמצעות מנגנון העברה על־פי־ערך (call by value), אך כיוון שמדובר בסמנטיקת התייחסות, הערך המועבר הוא המצביע אל האובייקט ולא האובייקט עצמו. אי לכך ניתן לשנות בתוך גוף הפונקציה את התוכן של האובייקט שהועבר אליה, אך אי אפשר לשנות את ההתייחסות של המשתנים שהועברו כארגומנטים. הקוד הבא, לדוגמה, מנסה לבצע החלפה בין המשתנים שהועברו כארגומנטים, אך פעולה זאת לא תצליח: def swap(a, b): #דוגמה לפונקציה שאיננה פועלת temp = a a = b b = temp קריאה לפונקציה על משתנים a, b כלשהם לא תשפיע עליהם כלל. שיטת העברה זאת נקראת גם "העברה באמצעות שיתוף" או "העברה על ידי התייחסות לאובייקט", ולמעשה מדובר בביצוע פעולת השמה בין הארגומנטים (הפרמטרים האקטואליים - המשתנים שהועברו לפונקציה) לבין הפרמטרים הפורמליים, המופיעים בהגדרת הפונקציה. פייתון מאפשרת העברת פרמטרים על פי מיקום או על פי שם, וכן בהעברה של מספר כלשהו של פרמטרים על פי מיקום (המתקבלים כ־tuple) או על פי שם (המתקבלים כ־dict): def print_all(pos, *args, named, **kwargs): print(pos) print(args) print(named) print(kwargs) >>> print_all(1, 2, 3, named=4, something=5) 1 (2, 3) 4 {'something': 5} ערך מורחב – פונקציות למדא ניתן לכתוב ביטוי המגדיר פונקציה, למשל כחלק מביטוי גדול יותר. התחביר עבור ביטוי כזה הוא מהצורה: lambda <arguments list> : <expression> ביטויי למדא שימושיים ליצירת פונקציות קטנות בתוך ביטוי גדול יותר, או כדי להעביר פונקציה כפרמטר. למשל, על מנת לעבור על כל המספרים הזוגיים בין 0 ל־100, ניתן לכתוב for i in filter(lambda x : x % 2 == 0, range(100)): print(i) פונקציות למדא שונות מפונקציות רגילות בכך שאין דרך ישירה לכתוב פונקציית למדא רקורסיבית. אי אפשר להגדיר משתנים חדשים בתוך ביטוי למדא, כיוון שמשתנים מוגדרים בפיתון באמצעות פקודות המבצעות כריכה, ובביטוי למדא אין פקודות. פונקציות למדא, כמו פונקציות מקוננות, הן סגור (Closure). התמיכה בפונקציות למדא בפייתון היא חלק מהתמיכה של פייתון בטכניקות של תכנות פונקציונלי. ערך מורחב – פונקציה מחוללת כל פונקציה שבה מוחזר ערך בעזרת המילה yield, נקראת פונקציה מחוללת (Generator Function). קריאה אליה מחזירה אובייקט המשמש כאיטרטור. בקריאה ראשונה לאובייקט מוחזר הערך שמופיע בביטוי yield, ובכל קריאה נוספת הפונקציה ממשיכה מהמקום בו היא הפסיקה. כאשר הפונקציה "חוזרת" (בעזרת return או כשמגיעים לקצה שלה), נזרקת חריגה. השימוש הפשוט ביותר הוא בלולאת for, אשר מקדמת כל פעם את האיטרטור (למשל, זה שנוצר בפונקציה המחוללת range) בעזרת הפקודה ()next, ולוכדת את החריגה באופן 'שקט' בסוף הלולאה. להלן דוגמת קוד לפונקציה מחוללת המחזירה אובייקט המשמש כאיטרטור לסדרת פיבונאצ'י עד האיבר ה־n. ניתן לשים לב לכך שההבדל בינה לבין פונקציה רגילה המחשבת את האיבר ה־n הוא קטן ביותר: def fib(n): a, b = 0, 1 for i in range(n): a, b = b, a + b yield a על מנת להדפיס את מספרי פיבונאצ'י הראשון עד ה־15 ניתן להשתמש בלולאת for פשוטה: for i in fib(15): print(i) צורת תחביר זו של השפה (הקשורה לתכנות פונקציונלי) נלקחה משפת Haskell, ומאפשרת ליצור רשימות מורכבות בקלות, בתחביר המזכיר כתיבה פורמלית של קבוצות במתמטיקה (אם כי התוצאה היא רשימה ולא קבוצה). למשל, בהינתן הגדרת fib לעיל, על מנת לקבל רשימה רגילה של 15 האיברים הראשונים ניתן לכתוב: [i for i in fib(15)] תחביר דומה אך עם סוגריים עגולים במקום מרובעים יביא ליצירת פונקציה מחוללת בעלת אותם איברים בדיוק. ישנן צורות מורכבות יותר של תחביר זה, או פשוטות יותר (ללא התנאי), והרשימה שבפנים יכולה להיות גם היא בצורה דומה לזאת, או מכל טיפוס סדרתי אחר. על מנת לקבל את כל ריבועי המספרים הזוגיים בסדרת פיבונאצ'י, ניתן להרחיב את הביטוי בעזרת תנאים ולהגדיר ביטויים מורכבים יותר: [i**2 for i in fib(15) if i % 2 == 0] אפשר גם לקנן ביטויים מסוג זה. למשל, הביטוי להלן יוצר את רשימת המספרים הראשוניים הקטנים מ־100: [i for i in range(2, 100) if all(i % k for k in range(2, i // 2 + 1))] להלן רשימה של האופרטורים בשפה כל אופרטור מתמטי/לוגי ניתן לשלב יחד עם פעולת השמה, בדומה לשפת C – פעולות כגון x+=5 המוסיפות 5 למשתנה המוצבע על ידי x. השפה תומכת בתכנות מונחה-עצמים, אך איננה כופה את המתכנת להשתמש בו. כך ניתן לכתוב תוכניות קצרות ופשוטות, וגם מערכות תוכנה מורכבות. כל ישות בשפה היא אובייקט, ובפרט כל מחלקה היא בעצם אובייקט של המחלקה type. ישנה אפשרות להורשה מרובה, וכל מחלקה יורשת ישירות או בעקיפין מן המחלקה object. אין בפייתון מחלקות אבסטרקטיות, אך ניתן לדמות את האפקט בעזרת זריקת חריגה מטיפוס "NotImplementedException". אין בפייתון ממשקים כמו בג'אווה כיוון שאין צורך בהם בשפה בעלת טיפוסיות ברווז. כמו הגדרת פונקציה, גם הגדרת מחלקה היא בעצם פקודה המורכבת מפקודות אחרות. כאשר המפרש נתקל בהגדרת מחלקה, הוא מבצע את כל הפקודות המופיעות בתוכה. כאשר הוא מסיים לבצע את כל הפקודות, הוא מעביר את אוסף המשתנים שהפקודות הללו יצרו אל המטא־מחלקה type, שיוצרת ממשתנים אלו אובייקט מחלקה חדש שהמשתנים הם שדות (fields) שלו: class A: print("hello") x = 42 def foo(): print(6) print(A.x) # prints 42 A.foo() # prints 6 כאשר הפקודה class תתבצע, תודפס המילה hello, וייווצר אובייקט־מחלקה חדש בשם A ולו שני שדות: שדה בשם x המכיל את המספר 42, ושדה בשם foo המכיל פונקציה. לאובייקט־המחלקה הזה, A, מוגדר אופרטור קריאה המאפשר להשתמש בו כאילו היה פונקציה, וכך לייצר אובייקטים חדשים שהטיפוס שלהם הוא A: a = A() # create new object of type A השפה תומכת בירושה מרובה, על אף הקשיים שהיא מציבה במקרים כגון ירושת־יהלום או מספר מתודות בעלות אותו שם. האלגוריתם המשמש לפתירת מקרים בהם המזהים הם רב משמעיים הוא מורכב, ועבר שינויים משמעותיים עם התפתחות השפה. השפה מאפשרת הגדרת שדות נתונים – משתנים – השייכים למחלקה (משתני מחלקה, נקראים גם משתנים סטטיים) או לאובייקט (משתני מופע). ניתן לגשת לשדות באופן ישיר, ואין דרך להגדיר "תכונות" – שדות שהגישה אליהם מבוקרת באמצעות מתודות – כמו בשפת Ruby. שיטות שייכות באופן בלעדי למחלקה, כלומר הן תמיד סטטיות. בהצהרה של שיטה, אם מתבצעת קריאה לשיטה דרך אובייקט ספציפי, הוא מועבר בתור הפרמטר הראשון של השיטה (שמקובל לקרוא לו self), באופן מובלע. ניתן לבצע קריאה כזאת גם באופן מפורש: class A(): def __init__(self, name): self.name = name def foo(self): print("foo is called for " + self.name) a = A("Example") a.foo() A.foo(a) שתי הקריאות ל־A.foo שקולות במקרה זה, וידפיסו את אותה תוצאה: "foo is called for Example". בניגוד לשפות מונחות־עצמים אחרות, ניתן להוסיף לכל אובייקט (ומחלקה, שגם היא אובייקט) שדות נתונים בכל זמן נתון, גם לאחר סיום הגדרת המחלקה, כלומר גם בזמן ריצה, או באופן מותנה. למעשה, כל האמור הוא התעסקות עם מרחב השם (namespace) בלבד – כלומר, בכל יצירה של אובייקט, מכל טיפוס, נוצר מרחב־שם, ואליו ניתן לשייך אובייקטים אחרים בכל זמן נתון (במגבלות כלשהן. וכל זה נכון גם לגבי מודולים). אין בפייתון שיטה המהווה בנאי (Constructor), אך קיימת בכל מחלקה (באופן מובלע או מפורש) שיטה בשם __init__, המאתחלת את האובייקט לאחר שהוא נוצר. באופן דומה, אין שיטה המשמשת כהורס (Destructor) עבור הריסה של אובייקט, בשל השימוש במנגנון איסוף זבל, אך ישנה שיטה בשם __del__ הנקראת על ידי המנגנון, ומשמשת באופן דומה לזה של השיטה finalize של Java. פייתון תומכת בהעמסת אופרטורים, וכן בירושה מטיפוסים מובנים בשפה, כגון int. בניגוד לשפות מונחות־עצמים רבות אחרות, בפייתון אין שום דרך לשלוט על הגישה אל שדות של אובייקט או מחלקה, באופן שיקביל לשדות private למשל, בשפות C++, Java או #C. מעצבי השפה מניחים שאם לא צריך לגשת אל שדה, לא ייגשו אליו. על מנת לסמן ששדה או שיטה לא נועדו לגישה מבחוץ מקובל להעניק להם שם המתחיל במקף תחתון בודד "_". שמות המתחילים בזוג מקפים תחתונים "__" עוברים שינוי לאחר יצירת המחלקה, כך שלא ניתן לגשת אליו בקלות מבחוץ, וכן לא ניתן למצוא אותם בעזרת הפקודה dir. למשל, משתנה בשם y__ במחלקה A ייקרא A__y_. על אף שהשפה עצמה לא מכילה כמות גדולה של כלים, הספרייה הסטנדרטית של פייתון כוללת עשרות מודולים, אשר מקלים מאוד על כתיבת קוד. ישנם לדוגמה מודולים אשר מאפשרים שימוש בפרוטוקולי אינטרנט רבים כגון MIME, HTTP ו־SMTP, שימוש בקידודים ובפורמטי דחיסה שונים כמו base64 ו־zlib, עבודה עם XML־ים ועוד. לפייתון יש מספר רב של חבילות הרחבה (packages) המוסיפות יכולות נוספות ופונקציות ספרייה חדשות. דוגמאות להרחבות נפוצות ושימושיות: NumPy – חבילת הרחבה מתמטית הכוללת מבנה מערכים רב-ממדיים משופר (ndarray), פונקציות מתמטיות רבות, וקטורים וכפל מטריצות, אלגברה ליניארית, טרנספורם פורייה ועוד. זוהי אחת החבילות השימושיות ביותר וחבילות הרחבה רבות מבוססות עליה. SciPy – חבילת הרחבה למדעים מדויקים והנדסה, כוללת כלים כמו טרנספורם פורייה מהיר, כלים לעיבוד אותות, אנליזה נומרית, אופטימיזציה ועוד. SciKit-Learn – חבילת הרחבה ללמידת מכונה ועיבוד מידע על בסיס SciPy, ידועה בקיצור כ-sklearn. MatPlotLib – חבילת הרחבה המאפשרת יצירת תרשימים וגרפים בדומה ל־MATLAB. Librosa – חבילה לעיבוד קובצי אודיו. Pandas – חבילת הרחבה המיועדת לעיבוד מידע, ניהול מבני נתונים ומדע הנתונים. TensorFlow – חבילה לבינה מלאכותית, למידה עמוקה ורשתות נוירונים מבית גוגל. PyTorch – חבילה לבינה מלאכותית, למידה עמוקה ורשתות נוירונים בשימוש פייסבוק. Flask – חבילת הרחבה לפיתוח צד שרת באתרי אינטרנט. turtle – חבילת המאפשרת יצירת משחקונים קטנים ושיפור השפה. NetworkX - ספרייה ללימוד גרפים ורשתות. חבילות כאלו מותקנות לרוב באמצעות החבילה pip, מנהל החבילות שמגיע עם השפה: python -m pip install PackName כאשר את המחרוזת PackName יש להחליף בשם החבילה אותה רוצים להתקין. על מנת להשתמש בחבילות נדרש לטעון אותן - להוסיף בראש קובץ הקוד בפקודת import את הספרייה באופן הבא: import numpy as np import matplotlib.pyplot as plt import scipy as sp השפה משמשת למספר מטרות. אחד השימושים המקובלים הוא לכתיבת תוכנות שייעודן הוא זמני – לכתוב ולזרוק. מהירות הפיתוח מאפשרת ביצוע משימה כזאת בקלות רבה יותר מאשר שפות מקובלות יותר כמו ++C,‏ C,‏ Java ואחרות. הרחבה של הרעיון הזה הוא בכתיבת הוכחת היתכנות (POC - Proof Of Concept). כאשר עולה דרישה לתוכנה מסוג חדש, ויש צורך להוכיח שהרעיון ישים באופן עקרוני, אפשר לפתח את כל התוכנה במהירות בפייתון. לאחר הוכחת ההיתכנות עוברים לפיתוח בשפות אחרות, המאפשרות לעיתים ביצועים יעילים יותר, על פי הצורך. עם זאת, אין פירוש הדבר שלא נעשה בשפה שימוש לכתיבת תוכנות גדולות. דוגמאות לכך הן Zope וביטורנט. שימוש נוסף בפייתון הוא לפיתוח אלגוריתמים בתחומי המדעים המדויקים וההנדסה, בדומה לשימוש ב־MATLAB. חבילות ההרחבה, כגון NumPy, המאפשרות עבודה יעילה עם וקטורים ומטריצות, הופכות אותה לנוחה ושימושית למטרה זו. פייתון היא אחת מהשפות העיקריות שבהן עובדת חברת גוגל. בין השאר, הגרסה הראשונה של זחלן הרשת של מנוע החיפוש גוגל נכתבה בפייתון, כל מערכת הפיתוח של גוגל (ניהול גרסאות ובניית מהדורות) מתבצעת בטכנולוגיה מבוססת פייתון וחלק מאתריה הגדולים כגון יוטיוב כתובים בצורה כמעט גורפת בפייתון. בנוסף, באפריל 2008 הזמינה גוגל גולשים לכתוב אפליקציות פייתון ולהתקינן על מערכת שרתיה. אנקונדה היא הפצה של שפות התכנות פייתון לתכנות מדעי (מדעי הנתונים, יישומי למידת מכונה, עיבוד נתונים בקנה מידה גדול, ניתוח ניבויי וכו'). תוכנה FreeCAD נכתבה בשפת פייתון. עוד שימושים נוספים בפייתון הם: כריית מידע, בינה מלאכותית, טסטים, אוטומציות, מחשוב בענן, תוכנות, בניית אתרים, ו-Big data. שם השפה "פייתון" נבחר כמחווה לקבוצה הקומית הבריטית "מונטי פייתון" עקב כך שחידו ואן רוסום, יוצר השפה, היה מעריץ שלהם, אזכורים למונטי פייתון מופיעים גם בקוד ובתרבות של פייתון. לדוגמה, המשתנים המטא-תחביריים שנמצאים בספרות של שפת פייתון הם "spam" ו"eggs", כאזכור לבדיחה שמופיעה בפרקים הראשונים של מונטי פייתון, במקום "foo" ו"bar" שנמצאים בשימוש ברוב שפות התכנות. בנוסף, התיעוד הרשמי של פייתון מכיל אזכורים שונים לבדיחות של מונטי פייתון. Cython IronPython הזן של פייתון אנקונדה (מנהל חבילות תוכנה) אתר האינטרנט הרשמי של פייתון (באנגלית) תכנות בשפת פייתון - ספר לימוד פייתון בעברית התיעוד של פייתון ברק גונן, תכנות בשפת פייתון, בהוצאת המרכז לחינוך סייבר PyDev – סביבת פיתוח משולבת לפייתון עבור eclipse Python Software Foundation (PSF), באתר פייתון GitHub Language Stats, madnight.github.io Stack Overflow Developer Survey 2022, Stack Overflow (באנגלית) the development and release schedule for Python 2.7. Nuitka Home, www.nuitka.net מערכת mypy לבדיקת טיפוסים בפייתון What’s New In Python 3.10 — Python 3.10.5 documentation, docs.python.org PEP 634 – Structural Pattern Matching: Specification | peps.python.org, peps.python.org בגרסאות 2.7 ומטה יש להשתמש ב־raw_input במקום input. ראה במאמר הזה ומקורות שמובאים בתוכו Stanford BackRub Web Project Google App Engine: גוגל תארח אפליקציות רשת בשפת פייתון, לינמגזין עבור מה פייתון משמשת? מדריך למתחילים באתר קורסרה שימושים באתר הרשמי של פייתון StefanBStreet, Guido Van Rossum and the Rise of Python - CodeX - Medium, CodeX, ‏ביוני 2021 Whetting Your Appetite, python.org דוגמה לשאלה ותשובות באתר stackoverflow שמשתמשים במילים הללו אזכור בספר "Learning Python: Powerful Object-Oriented Programming", אזכור בספר "Python"