2.30. Comprehensions¶
comprehension בונה רשימה, קבוצה, מילון או גנרטור חדשים מתוך iterable קיים, בביטוי יחיד. זוהי תחליף לתבנית הנפוצה של התחלה עם מכל ריק והוספה בתוך לולאה.
2.30.1. List comprehensions¶
squares = [x * x for x in range(5)]
print(squares)
פלט:
[0, 1, 4, 9, 16]
אותה לולאה בפירוט:
squares = []
for x in range(5):
squares.append(x * x)
צורת ה-comprehension היא ביטוי יחיד הבונה את הרשימה במקום. אין squares = [] ואין .append – התוצאה היא הערך של ה-comprehension.
הביטוי המוביל מייצר כל פריט; סעיף ה-for שם את משתנה הלולאה; if אופציונלי מסנן פריטים החוצה.¶
2.30.2. סינון עם if¶
סעיף if אופציונלי שומר רק את הפריטים התואמים:
evens = [x for x in range(10) if x % 2 == 0]
print(evens)
פלט:
[0, 2, 4, 6, 8]
המסנן רץ לפני הביטוי המוביל – x % 2 == 0 נבדק תחילה; רק ערכים תואמים מגיעים ל-x עבור הפלט.
2.30.3. Dict ו-set comprehensions¶
אותה צורה עובדת עם ליטרלים של dict ו-set.
ל-dict comprehension יש זוג key: value לפני ה-for:
squares = {x: x * x for x in range(5)}
print(squares)
פלט:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
set comprehension משתמש בסוגריים מסולסלים ובביטוי יחיד:
unique_lengths = {len(w) for w in ["a", "bb", "c", "bb"]}
print(unique_lengths)
פלט:
{1, 2}
2.30.4. ביטויי גנרטור¶
סוגריים עגולים מייצרים ביטוי גנרטור במקום רשימה. הערכים מחושבים אחד בכל פעם, לפי דרישה:
total = sum(x * x for x in range(1000))
אף פעם לא נבנית רשימה בת מיליון פריטים. הערכים זורמים אחד אחד לתוך sum(), אשר מחבר אותם ומשליך כל אחד תוך כדי תנועה.
ביטויי גנרטור הם הבחירה הנכונה כאשר מזינים ערכים לתוך פונקציית צמצום (sum(), max(), any(), all()) או כל קוד אחר הצורך איטרטור – הם חוסכים את הזיכרון שהרשימה השקולה הייתה משתמשת בו.
2.30.5. מתי לא להשתמש ב-comprehension¶
Comprehensions תמציתיים אך לא תמיד ברורים יותר. פנה ללולאת for רגילה כאשר:
הגוף זקוק ליותר ממשפט אחד (comprehension מכיל בדיוק ביטוי אחד).
לגוף יש תופעות לוואי (הדפסה, כתיבה לקובץ) – comprehensions מיועדים לבניית אוסף, לא להרצת פעולות.
למסנן או לטרנספורמציה יש כל כך הרבה חלקים עד שה-comprehension כבר לא נקרא משמאל-לימין.