דקורטורים בפייתון - צלילה עמוקה ב-2 חלקים (1/2)
- ולריה איינבינדר
- תוכנה
- 12 Jul, 2024
מבוא
סדרת 2 חלקים זו:
- חלק 1 (נוכחי): הקדמה + כתיבת דקורטור ראשון
- חלק 2: דקורטורים לפונקציות שמקבלות פרמטרים ומחזירות ערכים, דקורטורים שמקבלים ארגומנטים, דקורטורים במחלקות + תרגילים מתקדמים עם פתרונות
דקורטור הוא תכונה מיוחדת בפייתון שמאפשרת לשנות את ההתנהגות של פונקציות קיימות מבלי לשנות את הקוד שלהן. כן, קראת נכון — אפשר לשנות פונקציות בלי לשנות את הקוד שלהן בפועל! זה מה שהופך דקורטורים לכלי חזק ושימושי מאוד בפייתון. בכתבה זו נחקור מה הם דקורטורים וכיצד ניתן להשתמש בהם כדי להפוך את הקוד שלך לנקי ויעיל יותר.
בסוף המדריך הזה, תדע מהו דקורטור, איך הוא עובד, ואיך ליצור אחד בעצמך. בדרך, אולי תלמד גם כמה דברים חדשים על פונקציות! 😊 דקורטורים משמשים לעיתים קרובות לדברים כמו רישום לוגים, בדיקת הרשאות, או הוספת פונקציונליות בצורה נקייה. בואו נתחיל!
צפה בסרטון שלי על דקורטורים בפייתון עם דוגמאות קוד להבנה טובה יותר.
משימה מוטיבציונית
נתחיל בדוגמה שמראה למה אנחנו צריכים דקורטורים.
דמיין שיש לך מודול פייתון שנקרא various_functions.py שמכיל כמה פונקציות שימושיות, כמו חישוב עצרת, עיצוב שם, והמרת טמפרטורות. כל אחת מהפונקציות האלה מקבלת קלט מהמשתמש, מבצעת חישובים ומדפיסה את התוצאה:
אם נריץ את הפונקציות האלה, נקבל את הפלט הבא:
המודול עובד טוב, אבל אני רוצה להפוך אותו לידידותי יותר למשתמש. אני רוצה שכל פונקציה תדפיס הודעת ברוכים הבאים כשהיא מתחילה ולאחר מכן הודעת פרידה לפני שהיא מסתיימת. כך, החוויה עבור המשתמש תהיה טובה יותר.
הדרך הפשוטה אך המייגעת לעשות זאת היא לשנות כל פונקציה ולהוסיף את הודעות הברוכים הבאים והפרידה ידנית. עם זאת, זה אומר לחזור על אותו קוד בכל פונקציה. בנוסף, אם אוסיף פונקציות חדשות בעתיד, אצטרך לזכור להוסיף את ההודעות שוב. זה הרבה עבודה חוזרת, מה שהופך את הקוד לקשה לתחזוקה.
אבל הנה החדשות הטובות: דקורטורים בפייתון יכולים לפתור את הבעיה הזו בדרך טובה הרבה יותר. בעזרת דקורטור, אני יכולה להוסיף את ההתנהגות שאני צריכה מבלי לגעת בלוגיקה המרכזית של כל פונקציה. בואו נראה איך דקורטורים עושים זאת (שימו לב ל- @greeting_decorator בהמשך):
עכשיו, כשנריץ את main.py כמו קודם, הפלט ייראה כך:
כפי שאתם רואים, הוספת @greeting_decorator לפני כל פונקציה עשתה את העבודה! עם שורת קוד אחת בלבד, הוספנו הודעת ברוכים הבאים והודעת פרידה לכל פונקציה מבלי לשנות את הקוד של הפונקציה עצמה.
בכתבה זו, תלמדו איך @greeting_decorator עובד ואיך ליצור דקורטורים משלכם. בסופו של דבר, תבינו איך דקורטורים יכולים לעזור לכם לכתוב קוד נקי וקריא יותר.
הבנת אובייקטי פונקציה
נתחיל בהבנה מעמיקה יותר של פונקציות. בפייתון, פונקציות הן יותר מסתם קטעי קוד — הן למעשה אובייקטים מהשורה הראשונה. זה אומר שניתן להשתמש בהן כמו כל אובייקט אחר. אפשר להקצות אותן למשתנים, להעביר אותן כארגומנטים, ואפילו להחזיר אותן מפונקציות אחרות.
הנה דוגמה לפונקציה פשוטה:
אפשר לקרוא לפונקציות
הדרך הנפוצה ביותר להשתמש בפונקציה היא לקרוא לה עם סוגריים. לדוגמה:
כשאתה מוסיף סוגריים greet(), אתה בעצם מריץ את הפונקציה. אם אתה משתמש ב- greet ללא סוגריים, אתה מתייחס לפונקציה עצמה.
פונקציות הן אובייקטים רגילים בפייתון
בפייתון, פונקציות הן אובייקטים, כמו מחרוזות או מספרים. אפשר להקצות פונקציה למשתנה, לבדוק את הסוג שלה, ואפילו להדפיס אותה:
שימו לב: כשניגשים לפונקציה כאובייקט, לא משתמשים בסוגריים. אתם לא מריצים את הפונקציה — רק מתייחסים אליה.
מכיוון שפונקציות הן אובייקטים, אפשר גם להוסיף להן תכונות, וזה יכול להיות מאוד שימושי במקרים מסוימים. זה הופך את הפונקציות בפייתון לגמישות מאוד.
פונקציות יכולות לעבור כפרמטרים
מכיוון שפונקציות הן אובייקטים, הן יכולות גם לעבור כארגומנטים לפונקציות אחרות. זה מאוד חזק, כיוון שזה מאפשר להרחיב או לשנות את ההתנהגות של פונקציה מבלי לשנות אותה ישירות. הנה דוגמה:
בקוד זה, יש לנו פונקציה בשם wrapper שלוקחת פונקציה אחרת (other_function) כפרמטר. היא קוראת ל- other_function (שהיא הפונקציה greet שלנו), ולכן אתם רואים את הפלט “Hello All!”. העברת פונקציות כארגומנטים בצורה זו היא מאוד שימושית ליצירת דקורטורים, מכיוון שהיא מאפשרת לנו לעטוף התנהגות נוספת סביב פונקציה.
פונקציות יכולות ליצור ולהחזיר פונקציות אחרות
הקונספט האחרון שצריך להבין לפני שניצור את הדקורטור הראשון שלנו הוא שפונקציות יכולות גם להיווצר בתוך פונקציות אחרות ולהיות מוחזרות. הנה דוגמה:
בדוגמה שלמעלה, display_quote מוגדרת בתוך create_quote. הפונקציה create_quote לא רק מריצה את הפונקציה הפנימית — היא מחזירה אותה, מה שמאפשר לנו לקרוא ל- display_quote מאוחר יותר.
עכשיו, בואו נראה איך ניתן להשתמש בפונקציה create_quote:
המשתנה created_function הוא למעשה פונקציה, וכשאנחנו קוראים לה, היא מדפיסה את הציטוט:
היכולת הזו ליצור ולהחזיר פונקציות היא מה שהופך דקורטורים לחזקים כל כך. על ידי עטיפת פונקציה אחת באחרת, אפשר לשנות את ההתנהגות שלה בצורה נקייה וניתנת לשימוש חוזר.
אוקיי, עכשיו אתם מוכנים ליצור את הדקורטור הראשון שלכם בפייתון! ניצור את greeting_decorator שראיתם קודם.
מימוש דקורטור
אז, מה זה בעצם דקורטור? דקורטור הוא פונקציה שלוקחת פונקציה אחרת כארגומנט, מגדירה פונקציה פנימית שמוסיפה התנהגות כלשהי, ואז מחזירה את הפונקציה הפנימית. זה אולי נשמע מסובך, אבל זה לא כל כך קשה כשרואים את זה בפעולה.
הנה מה שאנחנו רוצים שהדקורטור שלנו יעשה:
- להדפיס הודעת ברוכים הבאים.
- לקרוא לפונקציה המקורית.
- להדפיס הודעת פרידה.
אנחנו רוצים להוסיף את ההתנהגות הזו לפונקציות המקוריות שלנו מבלי לשנות אותן. במקום זאת, נשתמש בדקורטור שיעטוף את הפונקציות המקוריות עם ההתנהגות החדשה הזו.
הנה איך מממשים את greeting_decorator:
ב- greeting_decorator, אנחנו מגדירים פונקציה פנימית בשם wrapper_func שמדפיסה הודעת ברוכים הבאים, קוראת לפונקציה המקורית (func()), ואז מדפיסה הודעת פרידה. בסוף, אנחנו מחזירים את wrapper_func.
כדי להשתמש בדקורטור, פשוט צריך להוסיף @greeting_decorator לפני הגדרת הפונקציה שלנו, כך:
התחביר @greeting_decorator הוא קיצור לכתיבה הבאה:
# קוד פסאודו
factorial = greeting_decorator(factorial)
במקום שהמשתנה factorial יצביע על הקוד המקורי, הוא עכשיו מצביע על wrapper_func שמוחזרת על ידי greeting_decorator. כך שכאשר קוראים ל- factorial(), אנחנו בעצם קוראים לפונקציית ה- wrapper שמוסיפה את ההתנהגות הנוספת.
זו הסיבה שבזכותה, לאחר שעיטרנו את הפונקציה factorial עם @greeting_decorator, הפונקציה עכשיו מדפיסה הודעות לפני ואחרי הרצת הקוד המקורי של factorial.
דקורטורים הם מאוד מועילים בפייתון. הם מאפשרים לך לשנות או להרחיב את ההתנהגות של פונקציות מבלי לשנות את הקוד המקורי. זה שימושי במיוחד למשימות כמו רישום לוגים, ולידציה, או בקרת גישה, שיכולות לשמש עבור פונקציות רבות מבלי לחזור על קוד.
סיכום
אני מקווה שהמדריך הזה נתן לך הבנה טובה של דקורטורים בפייתון. בעזרת דקורטורים, אפשר לכתוב קוד נקי, שימושי מחדש, וקל לתחזוקה.
אל תהסס לנסות את הדוגמאות בקוד בעצמך כדי לראות איך דקורטורים עובדים. תוכל למצוא את הקוד ב-GitHub שלי וב-Google Colab.
דקורטורים מופיעים לעיתים קרובות במסגרת עבודה כמו Flask ו-Django, שם הם משמשים למשימות כמו ניהול בקשות, בקרת גישה, והגדרת middleware. הגמישות שלהם מאפשרת לך לכתוב קוד נקי, יעיל, וקל להבנה.