iterable vs iterators

در پایتون Iterator ها یک Object هستند که متد __iter__ روی آن ها پیاده سازی می شود تا بتوان روی یک iterable عمل iterate را انجام داد. در حقیقت __iter__ یا متد ()iter یک iterable دریافت کرده و یک iterator را بر می گرداند (متد ()iter آبجکت iterator را initialize می کند). لیست ها، تاپل ها، دیکشنری ها، مجموعه ها و رشته ها به عنوان iterable شناخته می شوند و می توان با استفاده از for روی آن ها عمل iterate را انجام داد.هر Iterator باید متد های __iter__ و __next__ را پیاده سازی کند.__iter__این متد آبجکت iterator را initialization می کند و یک iterable دریافت کرده و یک iterator برمیگرداند.__next__ این متد یک iterator دریافت کرده و به مقدار بعدی در iterator اشاره می کند و اگر مقدار بعدی وجود نداشت (به انتهای iterator رسیدیم) StopIteration را raise می کند.حال با یک مثال تعاریف بالا را بررسی می کنیم:values = [1, 2, 3, 4, 5] iterator_values = iter(values) print(next(iterator_values)) print(next(iterator_values)) print(next(iterator_values)) # output >>> 1 >>> 2 >>> 3در مثال بالا ابتدا یک iterable تعریف کردیم (values) و سپس با استفاده از متد iter آن را به یک iterator تبدیل کردیم و در نهایت با استفاده از متد next روی آن عملیات iterate را انجام دادیم (به عنصر بعدی دسترسی پیدا کردیم).برای مشاهده تفاوت iterable و iterator مثال بالا را اندکی تغییر می دهیم تا با خطای زیر مواجه شویم:values = [1,2,3,4,5] next(values) >>>TypeError: 'list' object is not an iteratorهمانطور که مشاهده می کنید متد next انتظار یک iterator دارد تا روی آن iterate کند اما لیستی که به آن پاس داده شده این قابلیت را ندارد، چون یک iterable است.مثال) ایجاد یک custom iteratorمثال زیر یک iterator را پیاده سازی می کند که یک عدد دریافت کرده و در صورتی که از 10 کوچکتر نباشد از 10 تا ورودی را پرینت می کند:class Test: def __init__(self, limit): self.limit = limit def __iter__(self): self.x = 10 return self def __next__(self): x = self.x if x > self.limit: raise StopIteration self.x = x + 1 return x for i in Test(15): print(i)for i in Test(5): print(i)خروجی10 11 12 13 14 15مثال) ایجاد یک custom iteratorدر مثال زیر یک iterator که کار متد range در for را انجام می دهد پیاده سازی می کنیم. تنها توضیح درباره این مثال اینکه برای اینکه بتوان روی یک object عملیات iterate را پیاده سازی کرد باید دو متد __iter__ و __next__ را پیاده سازی کرد.class Range: def __init__(self, start, end, step=1): self.start = start self.end = end self.step = step def __iter__(self): return self def __next__(self): if self.start < self.end: current = self.start self.start += self.step return current raise StopIteration r = Range(10, 20, 3) for i in r: print(i) # output >>> 10 >>> 13 >>> 16 >>> 19کتابخانه itertoolsیک کتابخانه پایتونی است که توابع مختلفی برای کار کردن روی iterator ها در اختیار برنامه نویسان قرار می دهد. این ماژول به عنوان ابزاری سریع و استفاده حداقلی از حافظه (memory-efficient) کار می کند.در زیر برخی از مهمترین متد های این کتابخانه را مرور می کنیم:count(start, step):برای تولیدiterator بی نهایت که از start شروع می شود و به تعداد step حرکت می کند. اگر step پاس نداده باشد به طور پیش فرض 1 در نظر گرفته می شود.import itertools for i in itertools.count(5, 5): if i == 35: break else: print(i, end =&quot &quot) خروجی5 10 15 20 25 30cycle(iterable):این متد عبارات داخل پرانتز را به صورت چرخه تکرار شونده بر می گرداندimport itertools count = 0for i in itertools.cycle('AB'): if count > 7: break else: print(i, end = &quot &quot) count += 1خروجیA B A B A B A Brepeat(val, num):این متد val را به تعداد num بار تکرار می کند. خروجی این متد یک لیست است.import itertoolsprint (&quotPrinting the numbers repeatedly : &quot) print (list(itertools.repeat(25, 4)))خروجیPrinting the numbers repeatedly : [25, 25, 25, 25]