פייתון היא שפה שתומכת בשימוש במספר פרדיגמות תכנות שונות. ניתן לכתוב קוד מונחה עצמים, פרוצדורלי ובמידה מסוימת תכנות פונקציונלי. תכנות גנרי נתמך בשפה באופן טריוויאלי, בדומה לכל שפה בעלת טיפוסיות דינמית.
פייתון מאפשרת ואף מעודדת התבוננות־פנימה (Reflection), ותומכת בתכנות מקבילי ותכנות מוכוון־אירועים באמצעות מודולים מתאימים בספרייה הסטנדרטית.
ניהול הזיכרון ויצירת אובייקטים.
פינוי הזיכרון מבוצע בצורה אוטומטית, על ידי מנגנון איסוף זבל, בעיקר תוך שימוש במניית התייחסויות, ולא דורש התייחסות מפורשת מצד המתכנת.
אובייקטים מוקצים על גבי הערימה, כאשר הם נוצרים על ידי קריאה למחלקה, למשל (x=str(15 , או על ידי הצבה של ליטרלים בשפה – הכוללים מספרים, מחרוזות, רשימות, מילונים, פונקציות למבדה, או על ידי קריאה לפונקציה שיוצרת אותם. שני מנגנונים נוספים הם List Comprehension ו־Generators, שיתוארו בהמשך.
המשתנים עצמם, "הרפרנסים", הם מחרוזות פשוטות המשמשות כמפתחות במילון שמגדיר את תחום ההכרה (scope) הנוכחי.
המשמעות התחבירית של ההזחה.
בשפות רבות אין משמעות תכנותית להזחה כשלעצמה: כל בלוק מוקף בתווי בקרה מיוחדים המסמנים את תחילתו וסופו של הבלוק, אף ללא כל הזחה (סוגריים מסולסלים ב־C או Perl, ו־begin ו־end בפסקל וב־VB). בפייתון, המבנה של בלוקים של קוד בתוכנית נקבע על ידי ההזחה שלהם: עצם הזחת הבלוק מגדירה אותו כבלוק תכנותי שונה, באופן שמזכיר את שיטת העבודה ב־Haskell. תכונה זו מיועדת לשפר את קריאות התוכנית, בכך שהיא כופה על המתכנת כתיבה בסטנדרט אחיד (פחות או יותר), וחוסכת בקוד.
מערכת הטיפוסים.
מערכת הטיפוסים בפייתון היא בעלת המאפיינים הבאים:
טיפוסים מובנים בשפה.
השפה תומכת במגוון גדול יחסית של טיפוסי נתונים בסיסיים. בין המרכזים שבהם ניתן למנות:
אובייקטים מטיפוסי מספרים ומחרוזות הם בלתי ניתנים לשינוי (Immutable), כלומר שינוי ערכו של משתנה מטיפוס כזה הוא בעצם הסרת ההתייחסות אליו והפנייתה לערך חדש.
בשפה מוגדרים שני טיפוסים סדרתיים: tuple ו־list.
פעולת הגישה לאיברים במילון ובקבוצה ממומשת לרוב בעזרת טבלת גיבוב.
החל מהגרסאות האחרונות של השפה אוחדו המחלקות והטיפוסים, וכולם שייכים למטא־מחלקה "type" (כולל המחלקה type עצמה).
אנוטציות ובדיקת טיפוסים סטטית.
כאמור, פייתון היא שפה דינמית ולא מתבצעת בדיקת טיפוסים בזמן הידור. עם זאת, פייתון מאפשרת להוסיף אנוטציות – ביטויים שאין להם כל התנהגות בזמן ריצה – לפרמטרים של פונקציה ואף למשתנים, וישנה בשפה ספרייה בשם typing המאפשרת לבטא טיפוסים רבים. שילוב זה מאפשר לכתוב בשפה תוכניות אותן ניתן לבדוק על ידי כלים חיצוניים לבדיקת טיפוסים, וכך לאתר שגיאות טרם ההרצה.
להלן דוגמה לקוד פייתון עם סימון טיפוסים (הסימון &lt;- הוא עבור טיפוס ההחזרה. טיפוסי משתנים מסומנים בעזרת הערות):
def fib(n: int) -&gt; Iterator[int]:
a = 0 # type: int
b = 1 # type: int
while a &lt; 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')
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')
print("I don't know what x is")
ללא המילה elif היה צורך לבצע קינון עמוק במקרה זה – טכניקה מאוד לא נוחה באופן כללי, ובפרט בפייתון שבה כל קינון נוסף מגדיל את ההזחה:
if x % 2 == 0:
print('x is even')
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) אופרטור מהצורה "&lt;expr1&gt; if &lt;condition&gt; else &lt;expr2&gt;". ערכו של ביטוי כזה תלוי בערך האמת של הביטוי האמצעי. דוגמה לשימוש באופרטור הזה, השקולה לדוגמה הקודמת:
print('x is even' if x % 2 == 0 else 'x is odd')
לפני שהוסף האופרטור הזה, השתמשו מתכנתים בעובדה שהערך של פעולות and ו־or בפייתון הוא הערך המשמש בהן, ולאו דווקא ערך מטיפוס bool.
כך ניתן לכתוב ביטוי הדומה לביטוי תנאי בצורה "&lt;condition&gt; and &lt;expr1&gt; or &lt;expr2&gt;". למשל הדוגמה הקודמת תיכתב
print(x % 2 == 0 and 'x is even' or 'x is odd')
הדוגמה פועלת במקרה הזה, אך במקרים בהן ערך האמת של expr1 הוא שקר, הביטוי יחושב ל־expr2, גם אם condition מתקיים. קיומה של הטכניקה הזאת, יחד עם העובדה שהיא מביאה לבאגים קשים לגילוי, הביאו להכרה שאין ברירה אלא להוסיף ביטוי תנאי ייעודי לשפה.
לולאות.
לולאת while.
בלולאת 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.
מבנה נוסף ועיקרי בשפה הוא לולאת for. בלולאה זו מוגדר משתנה, ומתקבלת רשימה (או כל טיפוס שניתן לעבור עליו לפי סדר – "Iterable"). המשתנה מקבל בכל מחזור את ערכו של איבר אחר ברשימה, שוב ושוב עד שמגיעים לסוף הרשימה. מבנה זה אינו דומה ללולאת for בשפות ממשפחת ה־C, ומזכיר מעט את לולאת foreach בשפות אחרות. על מנת לבצע פקודה מספר פעמים מוגדר משתמשים בפונקציה (range(x המחזירה איטרטור העובר על המשתנים בין 0 ל־x (בגרסאות קודמות של השפה החזירה פקודה זו רשימה מתאימה).
דוגמה לשימוש בלולאת for להדפסת ריבועי המספרים בין 0 ל־5, לא כולל 5:
for i in range(5):
print(i ** 2)
הלולאה משתמשת במתודה __next__ המוגדרת על כל אובייקט שניתן לעבור עליו באופן סדרתי. כאשר מגיעים לאיבר האחרון, הקריאה הבאה ל־__next__ זורקת חריגה מטיפוס StopIteration. החריגה הזאת נלכדת באופן שקט על ידי הלולאה ומביאה לסיומה.
פקודת else לאחר לולאות מגדירה רצף פקודות שיתבצע לאחר סיום תקין של הלולאה.
פקודות יציאה.
להפסקת ביצוע לולאה בנקודה ספציפית ניתן להשתמש בפקודת break. הפקודה continue מסיימת את המחזור הנוכחי של הלולאה, ועוברת לחישוב ביטוי התנאי מחדש (בלולאת while) או לקידום המשתנה בסדרה (בלולאת for).
בנוסף, מתוך פונקציה ניתן להשתמש בפקודה return המסיימת את ריצת הפונקציה כולה, ומחזירה ערך. לא ניתן לסיים באמצעות return את ריצת התוכנית הראשית, שאיננה נחשבת לפונקציה (בשונה מהמצב בשפות ממשפחת ה־C).
חריגות.