פייתון גנרטורים
על מה נעבור
פייתון גנרטורים - מבוא
גנרטורים בפייתון הם סוג מיוחד של פונקציות, המאפשרות לנו ליצור איטרטורים (Iterators) על חישובים. הם מספקים דרך יעילה וחסכונית לטפל במצבים שבהם יש צורך לטפל ברצפים של ערכים גדולים או אינסופיים.
התכונה המרכזית של גנרטורים היא היכולת להפסיק ולהמשיך את הריצה באמצעות המילה השמורה yield
. כאשר הפונקציה מגיעה ל-yield
, היא "זוכרת" את המצב הנוכחי שלה ומחזירה את הערך שאחרי ה-yield
. בפעם הבאה שהגנרטור יקרא, הריצה תמשיך מנקודה זו.
כדי להמחיש את התכונות הבסיסיות של גנרטורים, בואו נתחיל עם דוגמה פשוטה:
1def count_up_to(max_val):2 n = 03 while n < max_val:4 yield n5 n += 167counter = count_up_to(3)8print(next(counter)) # 09print(next(counter)) # 110print(next(counter)) # 211print(next(counter)) # StopIteration
בדוגמה זו, count_up_to
היא גנרטור שמחזיר ערכים עוקבים מ-0 עד הערך המקסימלי שהוגדר. בכל פעם שאנו קוראים ל-next(counter)
, הגנרטור ממשיך את הריצה שלו מהנקודה האחרונה שבה הופסקה.
הגדירו גנרטור בשם my_range
שמקבל שני ערכים start
ו-end
, והוא מחזיר את הערכים מ-start
עד end-1
(כולל start
אך לא כולל end
), בדומה לפונקציה range
בפייתון.
גנרטורים יכולים להיות יעילים יותר מרשימות במצבים מסוימים, מכיוון שהם מחשבים את הערכים הבאים רק כאשר יש צורך בהם. זה עוזר לחסוך בזיכרון ובמחשוב מיותר. גנרטורים נפוצים במיוחד בעיבוד קבצים גדולים או בסטרימים של נתונים, שכן הם מאפשרים לנו לטפל בנתונים ביחידות קטנות ולא לשמור את כל הנתונים לזיכרון בבת אחת.
בשלב זה, חשוב להבין שגנרטורים אינם יוצרים רשימה או כל מבנה נתונים אחר, אלא הם מייצרים איטרטור על החישובים הנדרשים. כדי להמיר גנרטור לרשימה, ניתן להשתמש בפונקציה ()list
ולהעביר את הגנרטור כארגומנט.
סיכמנו את המבוא לגנרטורים. כעת נמשיך לדוגמאות מעשיות ומורכבות יותר כדי להעמיק את ההבנה בנושא חשוב זה.
פייתון גנרטורים - דוגמאות נוספות
עכשיו, לאחר שהכרנו את הרעיון הבסיסי של גנרטורים, בואו נראה כמה דוגמאות יותר מורכבות ומעשיות לשימוש בהם.
דוגמה 1: מחולל פיבונאצ׳י (Fibonanci Generator)
סדרת Fibonacci היא סדרה חשובה ומעניינת במתמטיקה. כל מספר בסדרה הוא סכום שני המספרים הקודמים, החל מ-0 ו-1. הסדרה נראית כך: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
נכתוב גנרטור שמחזיר את ערכי סדרת פיבונאצ׳י:
1def fibonacci():2 a, b = 0, 13 while True:4 yield a5 a, b = b, a + b
שימו לב שהגנרטור "זוכר" את הערכים הקודמים של a
ו-b
בכל פעם שהוא נקרא, ובאמצעות הקוד a, b = b, a + b
אנו מחשבים את הערך הבא בסדרה.
שימו לב שfibonacci
יכול לרוץ לנצח (תמיד יש את המספר הבא) על כן אי אפשר פשוט להחליף את fibonacci
ברשימה רגילה.
הפעילו את הגנרטור fibonacci
, והכניסו את 10 הערכים הראשונים לרשימה שתישמר במשתנה result_list
.
שימו לב ש
1list(fibonacci())
תיכשל כי במקרה הנוכחי הרשימה היא אינסופית וזה עלול להקריס לנו את המחשב.
דוגמה 2: מחולל משתנים אקראיים (Random Variable Generator)
נניח שאנו רוצים ליצור משתנים אקראיים מתוך התפלגות נתונה. במקום ליצור רשימה גדולה של ערכים אקראיים מראש (דבר שעלול לצרוך הרבה זיכרון), נוכל להשתמש בגנרטור כדי ליצור ערכים חדשים רק כאשר יש צורך בהם.
1import random23def random_variable(distribution):4 while True:5 yield random.choice(distribution)
הגנרטור random_variable
מקבל התפלגות (לדוגמה, רשימה או קובץ) ומחזיר ערכים אקראיים מההתפלגות הזו ללא סוף. הוא עושה זאת באמצעות לולאה אינסופית והמילה השמורה yield
.
בדומה לדוגמא הגדירו גנרטור random_variable
זמנו אותו עם ההתפלגות [1, 2, 3, 4, 5]
, ושמרו את 10 התוצאות הראשונות ברשימה בשם result_list
.
דוגמה 3: מחולל ערכים פרימיטיביים (Primitive Value Generator)
לעתים קרובות, אנו רוצים ליצור רצף של ערכים פרימיטיביים (כמו מספרים שלמים, מספרים ממשיים או מחרוזות) על פי כלל מסוים. במקום ליצור רשימה גדולה מראש, נוכל להשתמש בגנרטור כדי ליצור את הערכים הללו רק כאשר יש צורך בהם.
1def integers(start, stop, step=1):2 value = start3 while value < stop:4 yield value5 value += step67def floats(start, stop, step=0.1):8 value = start9 while value < stop:10 yield value11 value += step1213def strings(start, stop, step=1):14 current = start15 while ord(current) < ord(stop):16 yield current17 current = chr(ord(current) + step)
הגנרטורים integers
, floats
, ו-strings
מחזירים ערכים שלמים, ממשיים ומחרוזות, בהתאמה, בתחום הערכים שהוגדר. הם משתמשים בלולאה while
ובמילה השמורה yield
כדי להחזיר ערכים חדשים בכל פעם שהם נקראים.
יצרו גנרטור integers
עם הערכים מ-1 עד 10, שימרו את 5 הערכים הראשונים בmy_list
.
דוגמה 4: גנרטור למעבר על קבצים גדולים (File Iterator Generator)
גנרטורים הם כלי נפלא לטיפול בקבצים גדולים או בסטרימים של נתונים. במקום לקרוא את כל הקובץ לזיכרון בבת אחת, נוכל להשתמש בגנרטור כדי לקרוא את הקובץ שורה אחר שורה, ולבצע פעולות על כל שורה בנפרד.
1def file_iterator(file_path):2 with open(file_path, 'r') as file:3 for line in file:4 yield line.strip()
הגנרטור file_iterator
מקבל את נתיב הקובץ ומחזיר את כל השורות בקובץ, אחת אחר השנייה. הוא עושה זאת באמצעות לולאה for
על הקובץ הפתוח, ומחזיר כל שורה באמצעות yield
.
בדוגמאות אלו ראינו כמה שימושים שונים של גנרטורים, החל מיצירת רצפים של ערכים פרימיטיביים, דרך עיבוד קבצים גדולים, ועד לחישובים מתמטיים. גנרטורים הם כלי חזק ויעיל בפייתון, והם יכולים לסייע לנו בכתיבת קוד יעיל יותר ובשימוש נכון בזיכרון.
© 2022 DevIn. All rights reserved