المكرِّرات Iterators في بايثون

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

لعلّك لاحظت أن بالإمكان المرور على عناصر معظم الكائنات الحاوية (container objects) (مثل القوائم والقواميس والسلاسل النصية وغيرها...) باستخدام عبارة for:

for element in [1, 2, 3]:
    print(element)
for element in (1, 2, 3):
    print(element)
for key in {'one':1, 'two':2}:
    print(key)
for char in "123":
    print(char)
for line in open("myfile.txt"):
    print(line, end='')

تستدعي عبارة for خلف الكواليس الدالة iter()‎ على الكائن الحاوي، فتعيد الدالة كائن تكرار (iterator object) يعرّف التابع ‎__next__‎()‎ الذي يستطيع الوصول إلى عنصر واحد في الكائن الحاوي كلّ مرة. عند انتهاء العناصر يطلق التابع ‎__next__()‎ الاستثناء StopIteration والذي يوقف عمل حلقة for. يمكن استدعاء التابع ‎__next__()‎ باستخدام الدالة الداخلية next()، والمثال التالي يوضح العملية برمّتها:

>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    next(it)
StopIteration

من السهل تعديل آلية عمل المكرّرات في الأصناف التي يعرّفها المستخدم، فغاية ما في الأمر هو تعريف تابع ‎__iter__()‎ الذي يعيد كائنًا مع تابع ‎__next__()‎. إن عَرَّفَ الصنف التابع ‎__next__()‎ فيمكن للتابع ‎__iter__()‎ حينئذ أن يعيد القيمة self:

class Reverse:
"""مكرِّر يمرّ على عناصر التسلسل عكسيًا"""
    def __init__(self, data):
        self.data = data
        self.index = len(data)
    def __iter__(self):
        return self
    def __next__(self):
        if self.index == 0:
            raise StopIteration
        self.index = self.index - 1
        return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
...     print(char)
...
m
a
p
s

مصادر

  • صفحة Classes في توثيق بايثون الرسمي.