python كتاب - بناء بيثون إيتراتور الأساسية




4 Answers

تتطابق الأجسام التكرارية في بيثون مع بروتوكول التكرار ، والذي يعني بشكل أساسي أنها توفر طريقتين: __iter__() و next() . __iter__ بإرجاع كائن __iter__ ويتم استدعائه ضمنيًا في بداية الحلقات. الأسلوب next() إرجاع القيمة التالية ويتم استدعاؤه ضمنيًا في كل زيادة حلقة. next() يثير استثناء StopIteration عندما لا توجد قيمة أخرى للعودة ، والتي يتم التقاطها ضمنيًا بواسطة بنيات looping لإيقاف التكرار.

إليك مثال بسيط على عداد:

class Counter:
    def __init__(self, low, high):
        self.current = low
        self.high = high

    def __iter__(self):
        return self

    def next(self): # Python 3: def __next__(self)
        if self.current > self.high:
            raise StopIteration
        else:
            self.current += 1
            return self.current - 1


for c in Counter(3, 8):
    print c

هذا سوف يطبع:

3
4
5
6
7
8

هذا أسهل في الكتابة باستخدام مولد ، كما هو موضح في إجابة سابقة:

def counter(low, high):
    current = low
    while current <= high:
        yield current
        current += 1

for c in counter(3, 8):
    print c

سيكون الإخراج المطبوع هو نفسه. تحت غطاء المحرك ، يدعم كائن المولد بروتوكول التكرار ويقوم بشيء مماثل تقريبًا لعنصر الفئة.

تعتبر مقالة ديفيد ميرتز ، ومحاور ومولدات بسيطة ، مقدمة جيدة.

شرح ما

كيف يمكن إنشاء وظيفة تكرارية (أو كائن مكرر) في python؟




أولا وقبل كل شيء وحدة itertools مفيد بشكل لا يصدق بالنسبة لجميع أنواع الحالات التي سيكون فيها مكرر مفيد ، ولكن هنا كل ما تحتاجه لإنشاء مكرر في بيثون:

يخضع أو يستسلم

أليس هذا رائع؟ يمكن استخدام العائد ليحل محل العائد الطبيعي في الوظيفة. تقوم بإرجاع الكائن بنفس الطريقة فقط ، ولكن بدلاً من تدمير الحالة والخروج ، فإنها تحفظ الحالة عندما تريد تنفيذ التكرار التالي. هنا مثال على ذلك في العمل سحبت مباشرة من قائمة وظيفة itertools :

 def count(n=0):
     while True:
         yield n
         n += 1

كما هو مذكور في وصف الدالات (وهي الدالة count () من الوحدة النمطية itertools ...) ، فإنها تقوم بإنتاج أداة تكرار تقوم بإرجاع أعداد صحيحة متتالية تبدأ بـ n.

تعبيرات المولدات هي علبة أخرى من الديدان (الديدان الرائعة!). يمكن استخدامها بدلاً من الفهم بالقائمة لتوفير الذاكرة (تقوم قائمة الفواصل بإنشاء قائمة في الذاكرة يتم إتلافها بعد الاستخدام إذا لم يتم تعيينها لمتغير ، لكن تعبيرات المولد يمكن أن تنشئ كائن مولد ... وهي طريقة رائعة يقول Iterator). هذا مثال على تعريف تعبير المولد:

gen = (n for n in xrange(0,11))

وهذا يشبه إلى حد كبير تعريفنا الخاص بالتكرار أعلاه ، باستثناء أن النطاق الكامل محدد سلفًا ليكون بين 0 و 10.

لقد وجدت للتو xrange () (مندهش لم أراه من قبل ...) وأضفته إلى المثال أعلاه. يعد xrange () إصدارًا متكررًا من النطاق () الذي يتمتع بميزة عدم إنشاء القائمة مسبقًا. سيكون من المفيد للغاية إذا كان لديك مجموعة كبيرة من البيانات لتكرارها ولم يكن لديك سوى ذاكرة كبيرة للقيام بها.




هذا السؤال يتعلق بالأشياء المتكرّرة ، وليس حول التكرارات. في بيثون ، التسلسلات قابلة للتكرار أيضًا ، لذا فإن إحدى الطرق لإنشاء فئة متكررة هي جعلها تتصرف مثل تسلسل ، بمعنى أن تقدم لها __getitem__ و __len__ . لقد اختبرت هذا على بايثون 2 و 3.

class CustomRange:

    def __init__(self, low, high):
        self.low = low
        self.high = high

    def __getitem__(self, item):
        if item >= len(self):
            raise IndexError("CustomRange index out of range")
        return self.low + item

    def __len__(self):
        return self.high - self.low


cr = CustomRange(0, 10)
for i in cr:
    print(i)



إذا كنت تبحث عن شيء قصير وبسيط ، فربما يكون ذلك كافيًا بالنسبة لك:

class A(object):
    def __init__(self, l):
        self.data = l

    def __iter__(self):
        return iter(self.data)

مثال على الاستخدام:

In [3]: a = A([2,3,4])

In [4]: [i for i in a]
Out[4]: [2, 3, 4]



Related

python object iterator