יאללה תעמיסו

פוסט זה כולל טיפ קצר לעבודה יעילה עם Python. אם אתם רוצים ללמוד פייתון יותר לעומק אני ממליץ על קורס Python כאן באתר.
הקורס כולל עשרות שיעורי וידאו והמון תרגול מעשי וילמד אתכם Python בצורה מקצועית מההתחלה ועד הנושאים המתקדמים.

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

אם ניקח את Python כדוגמא נוכל לדמיין את הקוד הבא שמגדיר שני מימושים לאותה פונקציה:

@dispatch(tuple)
def go(point):
    x, y = point
    go(x, y)

@dispatch(int, int)
def go(x, y):
    print(f'x = {x}, y = {y}')

כאשר כל אחד מהמימושים אחראי על סט פרמטרים אחר. נרצה שהראשון ייקרא אם נפעיל את הפונקציה עם פרמטר יחיד:

loc = (10, 10)
go(loc)

ונרצה שהשני ייקרא כשנפעיל את הפונקציה עם שני פרמטרים:

go(10, 10)

נשמע לכם דמיוני? מסתבר שכל מה שצריך בשביל לגרום לקסם הזה לעבוד הוא לכתוב את ה Decorator. המפתח למימוש ה Decorator הוא לשמור מילון של מילונים, בו שם של פונקציה הוא המפתח הראשי, ואז לכל פונקציה אנחנו שומרים מילון שהמפתח שלו הוא סט פרמטרים מסוים והערך הוא הגדרה מסוימת של הפונקציה. במקרה שלנו המילון הגדול יראה כך:

{
    go: {
        (typle): <function at 0x1088b01e0>
        (int, int): <function at 0x1089d1488>
    }
}

הפונקציה go עצמה שהתוכנית מפעילה, כלומר זו שה Decorator מחזיר תסתכל ברשימת הפרמטרים שקיבלה, תלך למילון לחפש שם מפתח שמתאים לסוגים שלהם ולפי זה תחליט לאיזה פונקציה לקרוא.

מימוש פשוט של המנגנון יכול להיראות כך:

import collections

md = collections.defaultdict(dict)

def dispatch(*types):
    def decorator(f):
        md[f.__name__][types] = f
        def wrapper(*args, **kwargs):
            res = md[f.__name__][tuple(type(a) for a in args)]
            res(*args, **kwargs)

        return wrapper
    return decorator

ואם אתם בעניין של מימוש יותר רציני שגם נבדק בעולם האמיתי וכולל די הרבה אופטימיזציות שווה לבדוק את הספריה multipledispatch. זה דף הבית שלהם:

https://github.com/mrocklin/multipledispatch