مهدی نظری
مهدی نظری
خواندن ۴ دقیقه·۳ سال پیش

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 30

cycle(iterable):

این متد عبارات داخل پرانتز را به صورت چرخه تکرار شونده بر می گرداند

import itertools
count = 0
for i in itertools.cycle('AB'): if count > 7: break else: print(i, end = &quot &quot) count += 1

خروجی

A B A B A B A B

repeat(val, num):

این متد val را به تعداد num بار تکرار می کند. خروجی این متد یک لیست است.

import itertools
print (&quotPrinting the numbers repeatedly : &quot) print (list(itertools.repeat(25, 4)))

خروجی

Printing the numbers repeatedly : [25, 25, 25, 25]


iterator ها در پایتونiterator چیستتفاوت iterator و iterable
یک دولوپر خسته که پایتون را دوست می دارد.
شاید از این پست‌ها خوشتان بیاید