מטא-תכנות
מתייחס לטכניקות שבהן קוד מתייחס לקוד כאל נתונים – כלומר, קוד פייתון שמסוגל לשנות או לנתח קוד פייתון אחר (כמו שינוי מחלקות, פונקציות ועוד בזמן ריצה).
האופי הדינמי של פייתון מאפשר גמישות רבה במטא-תכנות – מה שיכול להוביל לתבניות עוצמתיות, אך דורש זהירות לשמירה על קריאות ותחזוקה של הקוד.
מטא-קלאסים: יצירת מחלקות באופן דינמי
בפייתון, גם מחלקות הן אובייקטים.
כאשר אתם כותבים:
python
class MyClass:
פייתון מריץ את ההגדרה הזו, והתוצאה היא אובייקט מטיפוס type (או תת-מחלקה שלו).
המחלקה type היא המטא-קלאס הברירת מחדל של פייתון – זו המחלקה שבונה מחלקות.
מטא-קלאס הוא פשוט: "מחלקה של מחלקות" – כלומר, מחלקה שהמופעים שלה הם מחלקות.
על ידי הגדרה של מטא-קלאס מותאם אישית, ניתן להתערב בתהליך יצירת מחלקות:
למשל, לשנות תכונות או להוסיף מתודות בזמן ההגדרה, או לאכוף תבניות מסוימות בקוד.
כדי ליצור מטא-קלאס, יוצרים מחלקה שיורשת מ־type, ומממשים את type.__new__ או type.__init__.
כאשר פייתון רואה הגדרת מחלקה עם הפרמטר metaclass=MyMeta, הוא ישתמש ב־MyMeta.__new__ כדי לבנות את אובייקט המחלקה.
דוגמה – שימוש בסיסי במטא-קלאס:
במקרה הזה, PrintMeta הוא מטא-קלאס. כאשר מציינים metaclass=PrintMeta במחלקה MyClass, בעת יצירת המחלקה פייתון קוראת למתודה __new__ של המטא-קלאס ומדפיסה הודעה.
בדוגמה הזו אנחנו רק מתעדים את יצירת המחלקה, אך שימושים מעשיים כוללים:
- אכיפת שדות או מתודות במחלקות – לדוגמה, לוודא שלמחלקה יש שדה מסוים או להוסיף מתודות אוטומטית.
- רישום אוטומטי (Registry) – לדוגמה, כשמחלקה נוצרת, לרשום אותה באוסף גלובלי (כמו במערכות פלאגינים או ORMs).
- ירושה דינמית או התאמה לאינטרפייסים – שינוי המחלקות הבסיסיות או הוספת mixins בזמן יצירה.
- שימוש קלאסי: Django ORM – המטא-קלאס רושם את המודל מול Django ויוצר את השדות שהם descriptors.
מטא-קלאסים הם כלי עוצמתי אך עשויים להפוך את הקוד לפחות ברור. לעיתים קרובות ניתן להשיג את אותה המטרה עם דקורטורים למחלקות או פונקציות יצרניות פשוטות. השתמשו בהם במשורה ותתעדו היטב.