سطح مقدماتی (Beginner Level)
در پایتون، بسیاری از اوقات ما روی لیستها یا رشتهها حلقه میزنیم، اما تا به حال فکر کردهاید که این فرآیند دقیقاً چگونه کار میکند؟ مفاهیم Iterator (تکرارگر) و Generator (تولیدکننده) پاسخ این سوال هستند و به شما کمک میکنند کدهای بهینهتر و تمیزتری بنویسید.
۱. تفاوت Iterable و Iterator
برای درک این موضوع باید دو مفهوم را از هم جدا کنیم:
- Iterable (قابل تکرار): هر چیزی که بتوان روی آن حلقه
forزد (مثل لیست، رشته، تاپل). - Iterator (تکرارگر): شیئی که وظیفه دارد دادهها را یکییکی به ما تحویل دهد و موقعیت فعلی را به یاد داشته باشد.
زمانی که شما یک حلقه for مینویسید، پایتون در پشت صحنه آن شیء را به یک Iterator تبدیل میکند.

مثال ۱: تبدیل لیست به ایتراتور
ما میتوانیم با تابع iter() یک لیست را به ایتراتور تبدیل کنیم و با next() مقادیر را یکییکی بگیریم.
# ساختار کلی (بدون اجرا)
# وقتی روی شیء next() صدا زده میشود، مقدار بعدی برگردانده میشود
iterator = iter(some_collection)
item = next(iterator)
۲. معرفی جنریتورها (Generators) و دستور yield
جنریتورها روشی سادهتر برای ساختن ایتراتورها هستند. به جای اینکه تمام مقادیر را در یک لیست ذخیره کنیم (که حافظه رم را اشغال میکند)، یک تابع مینویسیم که هر بار یک مقدار را تولید (yield) میکند و سپس متوقف میشود تا دوباره صدا زده شود.
تفاوت کلیدی: return تابع را کلاً تمام میکند، اما yield تابع را موقتاً متوقف میکند و وضعیت آن را حفظ میکند.
مثال ۲: ساخت اولین جنریتور
در اینجا تابعی داریم که اعداد ۱ تا ۳ را تولید میکند.
مثال ۳: تولید اعداد زوج
فرض کنید میخواهیم اعداد زوج را تولید کنیم. با جنریتور نیازی نیست لیست بسازیم.
سطح پیشرفته (Professional Level)
در سطح حرفهای، استفاده از ایتراتورها و جنریتورها مستقیماً روی پرفورمنس (Performance) و مدیریت حافظه (Memory Management) تاثیر میگذارد. همچنین ساخت ایتراتورهای سفارشی با کلاسها برای کنترل دقیق رفتار پیمایش ضروری است.
۱. ساخت کلاس Iterator سفارشی
برای اینکه یک کلاس قابلیت استفاده در حلقه for را داشته باشد، باید دو متد جادویی (Dunder Methods) را پیادهسازی کند:
__iter__: خود شیء را برمیگرداند.__next__: مقدار بعدی را برمیگرداند و اگر داده تمام شد، خطایStopIterationرا ایجاد میکند.
مثال ۴: کلاس توانهای عدد ۲
این کلاس رفتاری شبیه به range دارد اما توانهای ۲ را برمیگرداند.
# ساختار کلی کلاس ایتراتور (Snippet)
class CustomIterator:
def __iter__(self):
return self
def __next__(self):
# منطق تولید داده
pass
۲. مقایسه مصرف حافظه (List vs Generator)
یکی از مهمترین دلایل استفاده از جنریتورها در پروژههای بزرگ (Big Data)، مصرف بهینه حافظه است.
- List: تمام اعداد را همزمان در رم بارگذاری میکند.
- Generator: در هر لحظه فقط یک عدد را در رم نگه میدارد.

مثال ۵: Generator Expressions
شبیه به List Comprehension است اما با پرانتز () ساخته میشود و یک جنریتور برمیگرداند نه لیست.
۳. دنبالههای بینهایت (Infinite Sequences)
چون جنریتورها دادهها را "بهصورت تنبل" (Lazily) تولید میکنند، میتوانیم دنبالههایی بسازیم که هیچوقت تمام نمیشوند (مثل سنسوری که مدام داده میفرستد) بدون اینکه حافظه پر شود.
مثال ۶: فیبوناچی بینهایت
این تابع تا ابد عدد فیبوناچی تولید میکند. ما باید خودمان شرط توقف بگذاریم.
۴. استفاده از yield from
زمانی که میخواهید از درون یک جنریتور، یک جنریتور دیگر را صدا بزنید، به جای حلقه زدن روی آن، از yield from استفاده کنید. این کار کد را تمیزتر میکند و ارتباط مستقیم بین caller و sub-generator برقرار میکند.