פייתון תומכת בטיפול בחריגות. במקרה שתוכנית נתקלת בסיטואציה חריגה, על פי רוב שגיאה או נתונים עבורם תוצאת החישוב הרצויה איננה מוגדרת, ניתן "להרים" (או "לזרוק") חריגה באמצעות המילה השמורה raise (מקביל ל־throw בשפות אחרות). החריגה הנזרקת היא אובייקט, שיילכד במעלה הקריאה לפונקציה שזרקה אותו, בבלוק ייעודי מהצורה try ... except, שם יטופל באופן ספציפי. אם חריגה לא נלכדת על ידי המתכנת, היא נלכדת על ידי המפרש.
התחביר של לכידת חריגות הוא מהצורה
... # קוד העשוי לזרוק חריגה
except &lt;Exception Type&gt; as &lt;Exception name&gt;:
... # &lt;Exception Type&gt; קוד המטפל בחריגה מהטיפוס
... # קוד שיתבצע רק אם לא נזרקה חריגה
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, אחריה שם הפונקציה, ואחריו רשימה של 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)
»&gt; print_all(1, 2, 3, named=4, something=5)
פונקציות למדא.
ניתן לכתוב ביטוי המגדיר פונקציה, למשל כחלק מביטוי גדול יותר. התחביר עבור ביטוי כזה הוא מהצורה:
lambda &lt;arguments list&gt; : &lt;expression&gt;
ביטויי למדא שימושיים ליצירת פונקציות קטנות בתוך ביטוי גדול יותר, או כדי להעביר פונקציה כפרמטר. למשל, על מנת לעבור על כל המספרים הזוגיים בין 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)
List Comprehension.
צורת תחביר זו של השפה (הקשורה לתכנות פונקציונלי) נלקחה משפת 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
print(A.foo()) # prints 6
כאשר הפקודה class תתבצע, תודפס המילה hello, וייווצר אובייקט־מחלקה חדש בשם A ולו שני שדות: שדה בשם x המכיל את המספר 42, ושדה בשם foo המכיל פונקציה.
לאובייקט־המחלקה הזה, A, מוגדר אופרטור קריאה המאפשר להשתמש בו כאילו היה פונקציה, וכך לייצר אובייקטים חדשים שהטיפוס שלהם הוא A:
a = A() # create new object of type A
ירושה.