بروتوكول المكرّر
افهم __iter__ و__next__
بروتوكول المكرّر درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.
ما المقصود بالتكرار؟
كلما كتبتم حلقة for على قائمة أو سلسلة نصية أو قاموس، استخدمت Python بروتوكول المكرّر من وراء الكواليس.
يُسمى الكائن الذي يمكنكم التكرار عليه كائنًا قابلًا للتكرار. أما الشيء الذي ينتج القيم فعليًا واحدةً تلو الأخرى فيُسمى مكرّرًا.
for ch in 'abc':
print(ch)iter() وnext()
تدير عمليتي التكرار دالتان مضمنتان:
- تطلب
iter(obj)من الكائن القابل للتكرار تكراره. - تطلب
next(it)من المكرّر القيمة التالية.
عند عدم وجود قيم أخرى، ترفع next() الاستثناء StopIteration.
it = iter([10, 20, 30])
print(next(it))
print(next(it))
print(next(it))StopIteration
يؤدي استدعاء next() مرة واحدة أكثر من اللازم إلى رفع الاستثناء StopIteration. وتلتقط حلقة for هذا الاستثناء تلقائيًا وتتوقف بسلاسة.
it = iter([1])
print(next(it))
try:
next(it)
except StopIteration:
print('No more items')طريقتا Dunder
لإنشاء مكرّر خاص بكم، تنفذون طريقتين:
- تُرجع
__iter__كائن المكرّر نفسه. - تُرجع
__next__القيمة التالية أو ترفع الاستثناءStopIteration.
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
for x in Count(3):
print(x)القابل للتكرار مقابل المكرّر
لا يحتاج الكائن القابل للتكرار إلا إلى __iter__. أما المكرّر فيحتاج إلى كل من __iter__ و__next__.
القوائم قابلة للتكرار لكنها ليست مكرّرات: إذ يمنح كل استدعاء لـ iter() مكرّرًا جديدًا.
nums = [1, 2, 3]
print(iter(nums) is iter(nums))
it = iter(nums)
print(it is iter(it))يُستنفد المكرّر مرة واحدة
لا يمكن استهلاك المكرّر إلا مرة واحدة. وبعد الوصول إلى النهاية، يظل فارغًا. وللتكرار مجددًا، أنشئوا مكرّرًا جديدًا.
it = iter([1, 2])
print(list(it))
print(list(it))مكرّر شبيه بـ Range
لنبنِ مكرّرًا مخصصًا يتصرف مثل عداد بسيط. لاحظوا أن الحالة موجودة في النسخة.
class EvenUpTo:
def __init__(self, limit):
self.cur = 0
self.limit = limit
def __iter__(self):
return self
def __next__(self):
if self.cur > self.limit:
raise StopIteration
value = self.cur
self.cur += 2
return value
print(list(EvenUpTo(8)))فصل الكائن القابل للتكرار عن المكرّر
يحافظ التصميم الأنظف على فصل الحاوية عن المكرّر، بحيث يمكن تكرار الحاوية مرات عديدة.
class Bag:
def __init__(self, items):
self.items = items
def __iter__(self):
return BagIterator(self.items)
class BagIterator:
def __init__(self, items):
self.items = items
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i >= len(self.items):
raise StopIteration
v = self.items[self.i]
self.i += 1
return v
b = Bag(['x', 'y'])
print(list(b))
print(list(b))استخدام next() مع قيمة افتراضية
تُرجع next(it, default) القيمة الافتراضية بدلًا من رفع StopIteration عندما يكون المكرّر فارغًا. وهذا مفيد للتحقق الآمن من القيمة التالية.
it = iter([42])
print(next(it, 'done'))
print(next(it, 'done'))المكرّرات موفرة للذاكرة
تنتج المكرّرات عنصرًا واحدًا في كل مرة، ولذلك لا تحتاج إلى الاحتفاظ بالتسلسل بأكمله في الذاكرة. ولهذا السبب تتعامل مع تدفقات ضخمة أو حتى لا نهائية.
class Naturals:
def __init__(self):
self.n = 0
def __iter__(self):
return self
def __next__(self):
self.n += 1
return self.n
it = iter(Naturals())
print(next(it), next(it), next(it))الدوال المضمّنة التي تستهلك المكرّرات
تقبل كثير من الدوال المضمّنة أي مكرّر، مثل: sum وmax وmin وsorted وlist وtuple. وتسحب القيم حتى تصل إلى StopIteration.
class Count:
def __init__(self, n):
self.i = 0
self.n = n
def __iter__(self):
return self
def __next__(self):
if self.i >= self.n:
raise StopIteration
self.i += 1
return self.i
print(sum(Count(5)))
print(max(Count(5)))اختبار سريع
اختبروا مدى فهمكم لبروتوكول المكرّر.
مراجعة
لقد تعلمتم بروتوكول المكرّر:
- تحصل
iter()على مكرّر، وتسحبnext()القيم. - تشير
StopIterationإلى النهاية، وتتولىforمعالجتها. - تطبّق المكرّرات المخصّصة
__iter__و__next__. - المكرّرات أحادية الاستخدام وموفّرة للذاكرة.
بعد ذلك، ستدع Python تكتب المكرّرات نيابةً عنكم باستخدام yield.
الأسئلة الشائعة
هل درس «بروتوكول المكرّر» مجاني؟
نعم — نص درس «بروتوكول المكرّر» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.
ماذا ستتعلم في «بروتوكول المكرّر»؟
افهم __iter__ و__next__ تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟
لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «بروتوكول المكرّر»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟
نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- بروتوكول المكرّر
- دوال المُولّد
- تعبيرات المُولّد
- yield from والتفويض