Smart-World Surf

יחידה 5: תכנות מונחה עצמים (OOP)

הבנת עקרונות ה-OOP ויישומם בפייתון.

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

יסודות התכנות מונחה העצמים בפייתון

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

מחלקה (Class): תבנית או שרטוט ליצירת אובייקטים. היא מגדירה את המאפיינים והמתודות המשותפים לכל האובייקטים מסוגה.
אובייקט (Object / Instance): מופע ספציפי של מחלקה. לכל אובייקט יש מצב משלו (ערכי המאפיינים שלו).
מאפיין (Attribute): משתנה השייך למחלקה או לאובייקט, המייצג תכונה של האובייקט.
מתודה (Method): פונקציה המוגדרת בתוך מחלקה, המייצגת התנהגות או פעולה שאובייקט יכול לבצע.

יצירת מחלקות ואובייקטים

  • הגדרת מחלקה מתבצעת באמצעות מילת המפתח class.
  • מתודת האתחול __init__(self, ...) היא מתודה מיוחדת (Dunder method) הנקראת אוטומטית בעת יצירת אובייקט חדש. היא משמשת לאתחול המאפיינים של האובייקט.
  • הפרמטר self הוא הפניה לאובייקט הנוכחי, והוא חייב להיות הפרמטר הראשון בכל מתודה של מחלקה.

עקרונות הליבה של OOP

ארבעת עקרונות הליבה של OOP הם אבני הבניין המאפשרות את היתרונות של הפרדיגמה:

כימוס (Encapsulation)

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

הורשה (Inheritance)

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

פולימורפיזם (Polymorphism)

היכולת של אובייקטים שונים להגיב לאותה קריאה למתודה בצורות שונות. בפייתון, פולימורפיזם מושג בעיקר באמצעות "Duck Typing" (אם זה נראה כמו ברווז ומגעגע כמו ברווז, אז זה ברווז) ודריסה של מתודות (Method Overriding).

הפשטה (Abstraction)

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

מתודות מיוחדות ושיקולי תכנון

מתודות מיוחדות (Dunder Methods)

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

  • __str__(self): מחזירה ייצוג מחרוזתי "ידידותי למשתמש" של האובייקט, המשמש על ידי print().
  • __repr__(self): מחזירה ייצוג מחרוזתי "חד משמעי" של האובייקט, המשמש לרוב לצרכי Debugging.
  • __eq__(self, other): מגדירה את אופן השוואת שוויון (==) בין שני אובייקטים.

קומפוזיציה לעומת הורשה

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

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

שאלות לדיון

  • הסבירו מדוע כימוס חשוב לתחזוקת קוד, וכיצד ניתן ליישם אותו בפייתון באופן אפקטיבי.
  • תארו מצב שבו הייתם בוחרים להשתמש בקומפוזיציה במקום בהורשה, והסבירו את היתרונות של בחירה זו.
  • כתבו קוד פייתון קצר המדגים פולימורפיזם באמצעות Duck Typing, עם שתי מחלקות שונות ופונקציה אחת המקבלת מופעים משתיהן.
  • מה ההבדל העיקרי בין __str__ ל-__repr__, ומתי נשתמש בכל אחת מהן?

נקודות לתשובת מודל

  • כימוס: מונע גישה ישירה לנתונים פנימיים, מפחית תלות, מאפשר שינויים פנימיים ללא השפעה חיצונית. בפייתון: שימוש ב-@property, מתודות Getters/Setters, מוסכמות שמות (_, __).
  • קומפוזיציה מול הורשה: קומפוזיציה עדיפה כאשר הקשר הוא "יש לו" (לדוגמה, "מכונית יש לה מנוע") ולא "הוא סוג של" (לדוגמה, "כלב הוא סוג של חיה"). יתרונות: גמישות רבה יותר, הפחתת צימוד (coupling), קל יותר לשינוי.
  • פולימורפיזם (דוגמה): הגדרת מחלקות Dog ו-Cat עם מתודת speak() שונה. הגדרת פונקציה animal_sound(animal) שקוראת ל-animal.speak(). יצירת אובייקטים משתי המחלקות והעברתם לפונקציה.
  • __str__ vs __repr__: __str__ מיועד לקריאה אנושית (print()), __repr__ מיועד לייצוג חד-משמעי של האובייקט (לרוב ניתן להשתמש בו כדי ליצור מחדש את האובייקט).
מצאתם טעות או שחסר משהו?
→ הקודמת
טיפול בקבצים וטיפול בשגיאות
הבאה ←
מודולים וחבילות