מה לגבי keyword arguments?

27/08/2025

לפייתון יש פיצ'ר שמפריד אותה מהרבה שפות אחרות וזו האפשרות לבחור בזמן הפעלת הפונקציה אם אנחנו רוצים להעביר את הפרמטרים בתור keyword או לפי סדר הכתיבה, כלומר בהינתן פונקציה:

def demo(a, b):
    print(f"{a=}, {b=}")

אני יכול להפעיל אותה בכל הדרכים האלה בלי בעיה:

demo(2, 4)
demo(a=2, b=4)
demo(b=4, a=2)
demo(2, b=4)

רובי, JavaScript ושפות רבות אחרות דורשות יותר טקס בשביל משחק דומה. לדוגמה ב JavaScript אני יכול לכתוב:

function demo(a, b) {
  console.log(`a = ${a}, b = ${b}`);
}

demo(2, 4);

או אם אני מעדיף keywords אני אצטרך לכתוב:

function demo({a, b}) {
  console.log(`a = ${a}, b = ${b}`);
}

demo({a: 2, b: 4});

שינוי גם של אופן הקריאה וגם של הגדרת הפונקציה. עכשיו לשאלות - למה לא כולם זרמו עם שיטת הקריאה הגמישה של פייתון? ומה עדיף?

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

with open('/etc/passwd', 'r', -1, 'utf8', None, None, True, None) as f:
    print(f.read())

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

def demo(*, a, b):
    print(f"{a=}, {b=}")

# ok
demo(a=2, b=4)

# doesn't work
demo(2, 4)

מעבר לזה ברירת המחדל של פונקציות פייתון מכריחה אותי לבחור את השמות הנכונים לפרמטרים מההתחלה, כי באופן אוטומטי אנשים שקוראים לפונקציה יכולים להשתמש בשמות שבחרתי. בפונקציה demo אם אני רוצה להחליף את השמות מ a ו b לשמות אחרים אני לא יכול להיות בטוח שאף אחד לא השתמש בשמות המקוריים.

נשווה את זה עם רובי שם הבחירה היא הפוכה - פונקציה שמוגדרת כך מחייבת הפעלה עם keyword arguments:

def demo(a:, b:)
  puts "a = #{a}, b = #{b}"
end

demo(a: 2, b: 4)

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

def demo(a, b)
  puts "a = #{a}, b = #{b}"
end

# ok
demo(2, 4)

# doesn't work - passing a single dictionary
demo(a: 2, b: 4)

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

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

def demo(a, b:, c:)
end

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

def demo(a, /, b, c):
    ...

ואם אני רוצה לחייב ש b ו c יתקבלו בתור keywords כדי לקבל את אותו אפקט של רובי אני כבר צריך לחבר לזה גם את הכוכבית:

def demo(a, /, *, b, c):
    ...

בפיתוח תוכנה כל דבר הוא Trade Off. כשאנחנו רואים פיצ'ר מדליק חשוב לשאול - איפה אני משלם על זה ומה המחיר.