Python Iterators

ساختار های تکرار شونده (Iterators)

یک object که حاوی مقادیر قابل شمارش باشد (iterator) نام دارد.

یک iterator شیء است که می‌توان روی مقادیر موجود درآن پیمایش کرد.

object هایی که این ویژگی را دارند از پروتکل iterator پشتیبانی می‌کنند به این معنی که در کلاس خود حاوی متد های ()__iter__ و ()__next__ هستند.

لیست ها تاپل ها مجموعه ها و دیکشنری ها (List, Tuple, Set, Dictionary) از این نوع object ها هستند.

همه این object ها دارای متد ()iter هستند که محتوای موجود در آن ها را قابل پیمایش می‌کند و متد ()next برای رفتن به مقدار بعدی استفاده می‌شود.

mytuple = ("apple", "banana", "cherry")
myit = iter(mytuple)
print(next(myit))
print(next(myit))
print(next(myit))

یک رشته تنها هم قابل پیمایش است.

mystr = "banana"
myit = iter(mystr)

print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))
print(next(myit))

 

حلقه زدن روی iterator ها

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

mytuple = ("apple", "banana", "cherry")

for x in mytuple:
  print(x)

 

mystr = "banana"

for x in mystr:
  print(x)

حلقه for درواقع متد ()next را روی شیئ مورد نظر تکرار می‌کند.

ایجاد یک شیئ با ویژگی iterator

برای ایجاد کلاس یا شیئ با ویژگی iterator باید متد ()__iter__ و ()__next__ را در شیئ مورد نظر قرار دهیم.

مثال: یک شیئ ایجاد می‌کنیم که از 1 شمارش می‌کند و هربار یکی به آن می‌افزاید.

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    x = self.a
    self.a += 1
    return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))

توقف پیمایش StopIteration

در مثال قبلی هربار که متد ()next فراخوانی شود یک بار اجرا می‌شود و اگر این شیئ را درون حلقه بیندازیم تا همیشه ادامه پیدا خواهد کرد و محدودیتی برای توقف ندارد.

برای جلوگیری از ساختن اشیاء با قابلیت تکرار نامحدود می‌توان از قابلیت StopIteration استفاده کرد.

مثال قبلی را به 20 بار تکرار محدود می‌کنیم.

class MyNumbers:
  def __iter__(self):
    self.a = 1
    return self

  def __next__(self):
    if self.a <= 20:
      x = self.a
      self.a += 1
      return x
    else:
      raise StopIteration

myclass = MyNumbers()
myiter = iter(myclass)

for x in myiter:
  print(x)