شمارشگرها یا iteratorها در پایتون
آبجکت یا شیئی که شامل مجموعهای از دادههای قابل شمارش باشد iterator یا شمارشگر میگویند.
آبجکت یا شیئی که بتوان دادههای آن را به طور مرتب پردازش کرد، itarator میگویند.
مفهوم دادههای قابل شمارش در پایتون از ریاضیات گرفته شده است. مثلا مجموعهای از اعداد صحیح قابل شمارش است.
شیئی که پروتکل iterator ها در آن پیاده سازی شده باشد در پایتون به آن iterator میگویند. به عبارت ساده تر برای اینکه یک شی در پایتون iterator باشد باید دو متد __iter__() و __nextــ() در آن پیاده سازی گردد.
تفاوت قابل شمارشiterable و iterator در پایتون
لیستها چندتایی های مرتب، دیکشنریها و مجموعهها و رشته ها در پایتون دادههای قابل شمارش هستند. با استفاده از تابع iter میتوان یک itarator از دادههای یاد شده ساخت. به مثال زیر که در ترمینال خودم اجرا کردم دقت نمائید
[amir@arch ~]$ python
Python 3.9.6 (default, Jun 30 2021, 10:22:16)
[GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> mytuple = ('apple', 'bannana', 'cherry')
>>> myit = iter(mytuple)
>>> print(next(myit))
apple
>>> print(next(myit))
bannana
>>> print(next(myit))
cherry
>>> print(next(myit))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
KeyboardInterrupt
>>>
در حقیقت تابع iter یک اشارهگر به چندتایی مرتب ایجاد میکند که با استفاده از تابع next میتوان عنصر بعدی را به دست آورد که به اولین فراخوانی تابع next به اولین عنصر چندتایی مرتب اشاره میکند. اگر بعد از رسیدن اشارهگر به آخرین عنصر تابع next دوباره فراخوانی شد مفسر پایتون یک خطا برمیگرداند.
iterable یک نوع داده است ولی iterator یک اشارهگر است که به این نوع داده(دادههای قابل شمارش) اشاره میکند.
ایجاد حلقه روی یک شمارنده یا iterator در پایتون
با استفاه از حلقهی for
میتوانید یک دادهی قابل شمارش را پیمایش کنید. به مثال زیر که در ترمینالم اچرا شده است دقت نمائید
>>> mytuple = ('apple', 'banna', 'cherry')
>>> for x in mytuple:
... print(x)
...
apple
banna
cherry
پیمایش کاراکترهای یک رشته با استفاه از حلقه for در پایتون
>>> mystr = 'bannana'
>>> for x in mystr:
... print(x)
...
b
a
n
n
a
n
a
در حقیقت حلقه for در پایتون طوری پیاده سازی شده است که یک اشارهگر به دادهی قابل شمارش ایجاد کرده و در هر گذر تابع next() را روی آن اشارهگر فراخوانی میکند.
ایجاد iterator در پایتون
برای ایجاد یک شی یا کلاس از نوع قابل شمارش در پایتون باید توابع __next__()
و __next__()
را در کلاس مورد ایجاد نمائید.
در مقالهی کلاس یا اشیا در پایتون نحوهی ایجاد کلاس را یاد گرفتیم. تمامی کلاسهای تعریف شده در پایتون یک تابع سازنده به نام__init__()
دارند برای مقدار دهی اولیه اشیا دارد.
تابع __iter__()
در اشیا قابل شمارش به عنوان سازندهی این نوع اشیا عمل میکند و حتما باید خود شی را برگرداند.
تابع __next__()
نیز باید عنصر بعدی را برگرداند. به مثال زیر توجه نمائید:
>>> 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))
۵
>>> print(next(myiter))
۶
>>> print(next(myiter))
۷
توقف شمارش در پایتون
مثال قبل یک شی قابل شمارش بدون توقف بود و با فراخوانی تابع next میتواند تا ابد و گنجایش حافظه کامپیوتر ادمه یابد. اگر بخواهیم این نوع دادههای قابل شمارش را با استفاده از حلقهی for پیمایش کنیم یک حلقهی بینهایت ایجاد خواهد شد لذا این نوع دادههای قابل شمارش با استفاده از حلقه for قابل پیمایش نخواهد بود.
برای جلوگیری از ایجاده دادههای بینهایت و به تبع آن حلقههای بی نهایت میتوان از کلمه کلیدی StopIteration استفاده کرد.
با استفاده از یک شرط در تابع __next__() که یک خط ارسال می کند میتوانید از به وجود آمدن دادههای قابل شمارش بینهایت جلوگیری نمائید.
>>> 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
...
>>> mynum = MyNumbers()
>>> for x in mynum:
... print(x)
...
۱
۲
۳
۴
۵
۶
۷
۸
۹
۱۰
۱۱
۱۲
۱۳
۱۴
۱۵
۱۶
۱۷
۱۸
۱۹
۲۰
منبع: w3schools
سلام خسته نباشید.
ببخشید من میخواستم تعداد کلیک هاست که در برنامه گرافیکی که با tkinter هست رو بشمارم.میشه بگید که چجوری میتونم این کار رو انجام بدم؟