Iterator در پایتون چیست؟ آموزش iter و next

در این آموزش با مفهوم Iterator در پایتون آشنا می‌شویم و یاد می‌گیریم چگونه با استفاده از iter() و next() داده‌ها را یکی‌یکی پیمایش کنیم و Iterator سفارشی بسازیم.

Iterator در پایتون چیست؟

Iterator یا «پیمایشگر» شیئی در پایتون است که به ما اجازه می‌دهد عناصر یک مجموعه را یکی‌یکی دریافت و پردازش کنیم.

بسیاری از اشیایی که قبلاً با آن‌ها کار کرده‌ایم، مانند List، Tuple، String و Dictionary، قابلیت پیمایش دارند.

برای مثال:

numbers = [10, 20, 30]

for number in numbers:
    print(number)

حلقه for در پشت صحنه از مکانیزم Iterator برای پیمایش عناصر استفاده می‌کند.

Iterable چیست؟

به شیئی که بتوان عناصر آن را یکی‌یکی پیمایش کرد، Iterable یا «قابل پیمایش» گفته می‌شود.

نمونه‌هایی از Iterable در پایتون:

  • List
  • Tuple
  • String
  • Dictionary
  • Set
  • بسیاری از اشیای قابل پیمایش دیگر
text = "Python"

for letter in text:
    print(letter)

رشته text یک Iterable است، زیرا می‌توان حروف آن را یکی‌یکی پیمایش کرد.

تفاوت Iterable و Iterator

این دو مفهوم به یکدیگر مرتبط هستند، اما دقیقاً یک چیز نیستند.

Iterable شیئی است که می‌توان از آن یک Iterator ایجاد کرد. Iterator شیئی است که وضعیت پیمایش را نگه می‌دارد و می‌تواند مقدار بعدی را ارائه کند.

به زبان ساده:

  • Iterable: چیزی که قابلیت پیمایش دارد.
  • Iterator: چیزی که مرحله فعلی پیمایش را نگه می‌دارد.

تابع iter() در پایتون

با استفاده از تابع iter() می‌توانیم از یک Iterable یک Iterator ایجاد کنیم.

numbers = [10, 20, 30]

iterator = iter(numbers)

print(iterator)

حالا متغیر iterator یک Iterator است.

تابع next() در پایتون

برای دریافت عنصر بعدی از Iterator از تابع next() استفاده می‌کنیم.

numbers = [10, 20, 30]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))

خروجی:

10
20
30

هر بار که next() اجرا می‌شود، Iterator به عنصر بعدی می‌رود.

StopIteration چیست؟

وقتی تمام عناصر Iterator مصرف شوند، دیگر عنصر دیگری وجود ندارد. در این حالت اگر دوباره next() را اجرا کنیم، پایتون استثنای StopIteration ایجاد می‌کند.

numbers = [10, 20]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))

در فراخوانی سوم، تمام عناصر مصرف شده‌اند و StopIteration ایجاد می‌شود.

حلقه for چگونه از Iterator استفاده می‌کند؟

یکی از نکات جالب پایتون این است که حلقه for در پشت صحنه از Iterator استفاده می‌کند.

برای مثال:

numbers = [10, 20, 30]

for number in numbers:
    print(number)

به صورت ساده می‌توان تصور کرد که پایتون ابتدا از Iterable یک Iterator می‌سازد و سپس با دریافت مقدار بعدی، عناصر را یکی‌یکی پردازش می‌کند تا به StopIteration برسد.

ساخت Iterator سفارشی

می‌توانیم در پایتون Iterator مخصوص خودمان را نیز ایجاد کنیم. برای این کار معمولاً از دو متد ویژه استفاده می‌کنیم:

  • __iter__()
  • __next__()

یک مثال ساده:

class Counter:

    def __init__(self, maximum):
        self.current = 1
        self.maximum = maximum

    def __iter__(self):
        return self

    def __next__(self):

        if self.current <= self.maximum:
            number = self.current
            self.current += 1
            return number

        raise StopIteration


counter = Counter(5)

for number in counter:
    print(number)

خروجی:

1
2
3
4
5

متد __iter__ چیست؟

متد __iter__() وظیفه ایجاد یا برگرداندن Iterator را بر عهده دارد.

در بسیاری از Iteratorهای ساده، خود شیء Iterator در متد __iter__() برگردانده می‌شود.

def __iter__(self):
    return self

متد __next__ چیست؟

متد __next__() مقدار بعدی Iterator را برمی‌گرداند.

اگر مقدار دیگری وجود نداشته باشد، باید StopIteration ایجاد شود.

def __next__(self):

    if self.current <= self.maximum:
        value = self.current
        self.current += 1
        return value

    raise StopIteration

تفاوت Iterator و Generator

Generator در واقع راه ساده‌تری برای ساخت بسیاری از Iteratorهاست. در Generator معمولاً نیازی نیست متدهای __iter__() و __next__() را به صورت دستی پیاده‌سازی کنیم.

ویژگی Iterator Generator
ساخت معمولاً با iter و متدهای ویژه با yield یا Generator Expression
پیاده‌سازی می‌تواند پیچیده‌تر باشد معمولاً ساده‌تر است
next() پشتیبانی می‌کند پشتیبانی می‌کند
StopIteration بخشی از مکانیزم پایان پیمایش به صورت خودکار مدیریت می‌شود

مثال کاربردی: شمارنده

فرض کنید می‌خواهیم یک شمارنده بسازیم که اعداد ۱ تا ۱۰ را یکی‌یکی در اختیار برنامه قرار دهد.

class NumberCounter:

    def __init__(self, limit):
        self.number = 1
        self.limit = limit

    def __iter__(self):
        return self

    def __next__(self):

        if self.number <= self.limit:
            value = self.number
            self.number += 1
            return value

        raise StopIteration


counter = NumberCounter(10)

for number in counter:
    print(number)

این مثال نشان می‌دهد که چگونه می‌توان رفتار یک شیء قابل پیمایش را خودمان تعریف کنیم.

Iteratorهای داخلی پایتون

بسیاری از توابع و ساختارهای داخلی پایتون با Iteratorها کار می‌کنند.

برای مثال:

numbers = [1, 2, 3]

iterator = iter(numbers)

print(next(iterator))
print(next(iterator))
print(next(iterator))

همچنین توابعی مانند enumerate()، zip() و بسیاری از ابزارهای پایتون از مفهوم پیمایش مرحله‌ای استفاده می‌کنند.

Iterator و مصرف حافظه

Iteratorها می‌توانند به پردازش مرحله‌ای داده‌ها کمک کنند. این ویژگی زمانی اهمیت بیشتری پیدا می‌کند که با مجموعه‌های بزرگ داده روبه‌رو هستیم.

به جای اینکه همیشه تمام داده‌ها را یکجا پردازش کنیم، می‌توانیم داده‌ها را در مراحل مختلف دریافت و پردازش کنیم.

Generatorها نیز از همین ایده برای تولید مرحله‌ای داده‌ها استفاده می‌کنند.

تمرین‌های Iterator در پایتون

تمرین ۱

یک List شامل اعداد ۱۰، ۲۰، ۳۰ و ۴۰ بسازید و با استفاده از iter() و next() عناصر آن را یکی‌یکی چاپ کنید.

تمرین ۲

یک Iterator بسازید که اعداد ۱ تا ۵ را تولید کند.

تمرین ۳

Iterator سفارشی‌ای ایجاد کنید که اعداد زوج بین ۲ تا ۲۰ را تولید کند.

تمرین ۴

مثال تمرین قبل را با Generator و yield پیاده‌سازی کنید و تفاوت کدها را بررسی کنید.

سوالات متداول

Iterator در پایتون چیست؟

Iterator شیئی است که می‌تواند عناصر یک مجموعه یا منبع داده را به صورت مرحله‌ای و یکی‌یکی ارائه کند.

Iterable چیست؟

Iterable شیئی است که می‌توان آن را پیمایش کرد و معمولاً می‌توان با استفاده از iter() از آن یک Iterator ساخت.

iter() چه کاری انجام می‌دهد؟

تابع iter() از یک Iterable یک Iterator ایجاد می‌کند.

next() چه کاری انجام می‌دهد؟

تابع next() مقدار بعدی Iterator را برمی‌گرداند.

StopIteration چیست؟

وقتی Iterator دیگر مقدار جدیدی برای ارائه نداشته باشد، StopIteration نشان‌دهنده پایان پیمایش است.

آیا Generator همان Iterator است؟

Generator نوعی Iterator است و می‌تواند به روشی ساده‌تر رفتار پیمایش مرحله‌ای را پیاده‌سازی کند.