מדריך פייתון
ל Iterator וGenerators

מדריך פייתון ל Iterator וGenerators

מדריך פייתון ל Iterator וGenerators

Iterators הם מהיסודות של פייתון. הם נמצאים בכל מקום ואם נתקלים בהם בתכנית זו או אחרת. Iterators הם אובייקטים המאפשרים לכם לעבור דרך כל האלמנטים של אוסף, ללא קשר ליישום הספציפי שלו.
כלומר, אם פעם השתמשתם בלולאות כדי לחזור או לרוץ דרך הערכים ב container , בעצם השתמשתם ב Iterator. במאמר זה תלמדו עוד על Iterators בפייתון,


Iterators

Iterators הם אובייקטים המיישמים את פרוטוקול Iterator. פרוטוקול Iterator אינו אלא מחלקה בפייתון שמכילה אתה הפונקציה ___ netxt () ____. כלומר, בכל פעם שאתם מבקשים את הערך הבא, iterator יודע איך לחשב את זה.
הוא שומר מידע על המצב הנוכחי שה- iterable עובד עליו. Iteratorקורא את הערך הבא כאשר אתם קוראים()next על זה.
Iterators עוזרים לייצר קוד למראה נקי יותר, כי הם מאפשרים לנו לעבוד עם רצפים אינסופיים ללא צורך בהקצאת משאבים עבור כל רצף אפשרי, ובכך גם חוסכים במרחב המשאבים.
לפייתון יש מספר אובייקטים מובנים, אשר מיישמים את פרוטוקול Iteratorואתם חייבים לראות כמה כאלה לפני: lists, tuples, strings, collections ואפילו קבצים. יש גם Iterators רבים בפייתון, וכל פונקציות Iterables מחזירות Iterators.
Iterables
Iterables הם כל המחלקות, לא בהכרח מבנה נתונים שיכולות להחזיר Iterator. מטרתם העיקרית היא להחזיר את כל המרכיבים. Iterables יכול לייצג מקור סופי כמו גם מקור אינסופי של נתונים. Iterables יגדיר ישירות או בעקיפין שתי פונקציות: ___iter ___ ()שחייבת להחזיר את האובייקט iterator ואת הפונקציה ___ next () ___ שבעזרתה iterator זה נקרא.

יש הבדל חשוב בין Iterable לבין Iterator. בואו נראה את זה עם דוגמא:

a_set = {1, 2, 3}
b_iterator + iter(a_set)
next(b_iterator)
type(a_set)
type(b_iterator)

בדוגמא, a set הוא Iterable (סט) ואילו b_iterator הוא Iterator. שניהם סוגים שונים של נתוני פייתון.
תוהים איך עובד Iterator פנימי כדי לייצר את הרצף הבא? בואו נבנה Iteratorשיחזיר סדרה של מספרים:

Class Series(object):
def __init__(self, low, high):
self.current = low
self.high = high

def __iter__(self):
return self

def __next__(self):
if self.current > self.high:
raise StopIteration
else:
self.current += 1
return self.current – 1

n_list = Series(1,10)
print(list(n_list))

___iter___ מחזיר את האובייקט iterator עצמו ופונקצית ___next__ מחזירה את הערך הבא מ-iterator. אם אין פריטים נוספים להחזיר, אז זה מעלה שגיאה מסוג Stopiteration.

מודול Itertools

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

בואו נבדוק כמה דברים מעניינים שניתן לבצע עם הפונקציה count מהמודול ietrtools:

from itertools import count
sequence = count(start=0, step=1)
while(next(sequence) <= 10):
print(next(sequence)))
1
3
5
7
9
11
from itertools import cycle
dessert = cycle(['Icecream','Cake'])
count = 0
while(count != 4):
print('Q. What do we have for dessert? A: ' + next(dessert))
count+=1
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake
Q. What do we have for dessert? A: Icecream
Q. What do we have for dessert? A: Cake

 

Generators

Generators הם ״האחים האלגנטים״ של Iterator, המאפשרים לכם לכתוב Iterators כמו אלו שראיתם קודם, אבל בתחביר הרבה יותר קל, שבו אינכם צריכים לכתוב מחלקות עם הפונקציות ___iter ___ () ו-___ next ().
זוכרים את הדוגמא שראיתם קודם עם Iterator? בואו ננסה לשכתב את הקוד, אבל באמצעות הרעיון של Generators:

def series_generator(low, high):
while low <= high:
yield low
low += 1
n_list = []
for num in series_generator(1,10):
n_list.append(num)

print(n_list)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

מילת הקסם עם Generators היא yield. אין הצהרת החזרה בסדרת הפונקציה. ערך ההחזרה של הפונקציה יהיה למעשה Generator. בתוך הלולאה בזמן כאשר הביצוע מגיע הצהרת ה yield, הערך הנמוך מוחזר ומצב Generator מושעה.
במהלך הקריאה הבאה, מחולל הGenerator מן הערך בו הפסיק מוקדם יותר ומגדיל את הערך הזה באחד. זה ממשיך עם לולאה בזמן ומגיע שוב לדוח yield.
Yield בעצם מחליף את הצהרת החזרה של פונקציה ומספק אך מספק תוצאה של המתקשר שלה מבלי להרוס משתנים מקומיים. לפיכך, במקרה של איטרציה הבאה, זה יכול לעבוד על הערך המשתנה המקומי שוב. אז בניגוד לתפקוד הרגיל שראיתם בעבר, שם בכל קריאה הוא מתחיל עם סט חדש של משתנים – Generator יחדש את הביצוע שבו הוא היה כבוי.

טיפ

Lazy Factory הוא רעיון מאחורי הGenerator והIterator. כלומר, הם נסרקים עד שאתם שואלים את זה עבור ערך. רק כאשר נשאל הוא כאשר הם מקבלים לעבוד ולייצר ערך יחיד, שלאחריו יתברר שוב בחוסר מעש.
זוהי גישה טובה לעבוד עם הרבה נתונים. אם אינכם דורשים את כל הנתונים בבת אחת, אין צורך לטעון את כל הנתונים בזיכרון, אתם יכולים להשתמש בGenerator או בIteratorאשר יעביר לכם פיסת נתונים בכל פעם.
Generators הם חזקים מאוד. יש להם יותר זיכרון ויעילות CPU והם מאפשרים לכם לכתוב קוד עם פחות משתני ביניים ומבני נתונים. הם נוטים לדרוש פחות שורות קוד והשימוש בהם הופך את הקוד לקל יותר לקריאה ולהבנה. לכן חשוב שתנסו להשתמש ככל הניתן בGenerators בקוד שלכם.
איפה אתם יכולים להכניס Generators בקוד שלכם?

טיפ: מצאו מקומות בקוד שלכם, שבהם אתם מבצעים את הפעולות הבאות:

def some_funtion():
result = []
for … in …:
result.append(x)
return result

והחליפו אותו עם:

def iterate_over():
for … in …:
yield x

 

https://www.yaniv-arad.com/python-programming/ – למידע מפורט על קורס פייתון כנסו כאן 

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

דילוג לתוכן