דילוג לתוכן המרכזי
מודול 6 · שיעור 3 מתוך 423/36 בקורס~10 min
שיעורי מודול (3/4)

ביטוי מחולל

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

Python
gen = (n * n for n in range(1_000_000))
# istantaneo, memoria costante: nessun calcolo ancora fatto

list_comp = [n * n for n in range(1_000_000)]
# alloca 1M di int in memoria

עצלות (הערכה עצלנית)

המחולל לא עושה כלום עד שמישהו מבקש את הערך הבא:

Python
gen = (n * n for n in range(5))
next(gen)    # 0    (calcolato adesso)
next(gen)    # 1
next(gen)    # 4
# ... e così via, fino a StopIteration

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

מתי להשתמש בו

כאשר אתה מעביר את התוצאות לפונקציה שצורכת אותן ברצף:

Python
total = sum(n * n for n in range(1_000_000))
# nessuna lista intermedia, memoria costante

sum, any, all, max, min, "".join(...) כולם מקבלים גנרטורים. אם הפונקציה החיצונית דורשת רק את סוגרי השיחה, אתה יכול השמט את זה של הגנרטור:

Python
sum((n * n for n in range(10)))    # OK
sum(n * n for n in range(10))      # IDENTICO, più leggibile

any וall: קצר חשמלי

any(...) ו-all(...) מפסיקים לבצע איטרציה ברגע שיש להם את התשובה. עם גנרטור, האלמנטים הבאים אפילו לא מחושבים.

Python
nums = [1, 2, 3, 4, 5]
any(n > 3 for n in nums)    # True (si ferma a 4)
all(n > 0 for n in nums)    # True
all(n > 2 for n in nums)    # False (si ferma a 1)

דפוס: צינור עצלן

Python
righe = (linea.strip() for linea in testo.splitlines())
non_vuote = (r for r in righe if r)
prime_dieci = []
for r in non_vuote:
    prime_dieci.append(r)
    if len(prime_dieci) == 10:
        break

אין רשימת ביניים, אפילו בתשומות ענקיות.

צריכת גנרטורים עם סכום, כל, הכל

ביטויי מחולל מושלמים למעבר ישירות לפונקציות שצורכות איטרנס, כמו sum(), any() או all(). במקרה זה, אתה יכול להשמיט את הסוגריים החיצוניים של ביטוי המחולל, פשוט לכתוב:

Python
squares_sum = sum(x**2 for x in range(10))

זה שומר על הקוד שלך נקי וחסכוני מאוד בזיכרון.

נסה את זה

פעילות גופנית#python.m6.l3.e1
ניסיונות: 0טוען...

חשב את סכום הריבועים של המספרים מ-1 עד 100 (כולל) באמצעות ביטוי מחולל בתוך sum(). הקצה אותו ל'טוט'. הערך `טוט`.

טוען עורך...
הצג רמז

range(1, 101) כולל 100.

הפתרון זמין לאחר 3 ניסיונות

סקירת התרגיל

פעילות גופנית#python.m6.l3.e2
ניסיונות: 0טוען...

בהינתן `words = ['ciao', 'mondo', 'PYTHON', 'java']`, השתמש ב- any() עם ביטוי מחולל כדי לבדוק אם לפחות מילה אחת היא אותיות גדולות (.isupper()). הקצה את התוצאה ל'יש_אותיות גדולות'. הערך את 'יש_אותיות גדולות'.

טוען עורך...
הצג רמז

any(p.isupper() עבור p במילים)

הפתרון זמין לאחר 3 ניסיונות

אתגר נוסף

פעילות גופנית#python.m6.l3.e3
ניסיונות: 0טוען...

Use a generator expression passed directly to the `sum()` function to calculate the sum of the squares of all integers from 1 to 100 inclusive. Store the result in `total_sum` and evaluate it.

טוען עורך...
הצג רמז

כתוב total_sum = sum(x**2 עבור x בטווח(1, 101)). אין צורך בסוגריים כפולים.

הפתרון זמין לאחר 3 ניסיונות