8.11. المكررات غير المتزامنة#
المكرِّر غير المتزامن هو نسخة asyncio من المكرِّر. قدّمت نظرة عامة على Python بروتوكول المكرِّر المتزامن -- __iter__ و __next__ -- وحلقة for التي تقوده. تضيف المكررات غير المتزامنة await إلى كل خطوة، فيتمكّن المكرِّر من الانتظار بين القيم دون حجب حلقة الأحداث.
8.11.1. البروتوكول#
يكون الصنف مكرِّرًا غير متزامن عندما يطبّق
__aiter__(self)-- يعيد كائن المكرِّر، وعادةً ما يكونself.
async def __anext__(self)-- يعيد القيمة التالية، أو يطلقStopAsyncIterationعندما لا يتبقى المزيد.
بنية الحلقة المقابلة هي async for
import asyncio
class FrameCounter:
"""Yield N integers, one per frame period."""
def __init__(self, n, period_ms):
self._n = n
self._period_ms = period_ms
self._i = 0
def __aiter__(self):
return self
async def __anext__(self):
if self._i >= self._n:
raise StopAsyncIteration
await asyncio.sleep_ms(self._period_ms)
self._i += 1
return self._i
async def main():
async for n in FrameCounter(5, 200):
print(n)
تنتظر حلقة async for كل استدعاء لـ __anext__، فتتنازل الكوروتين التي تشغّل الحلقة عن التحكم لحلقة الأحداث بين القيم تمامًا مثل أي await آخر.
8.11.2. متى تلجأ إليه#
كلما كان للتطبيق مصدر بيانات تصل بمرور الوقت وكان على المستهلك أن يكررها بكسل. مستشعر ينتج عينة لكل فترة، أو مقبس شبكة يسلّم رسائل، أو مولّد إطارات -- في أي مكان يناسبه الشكل while True: x = await source.next(); process(x)، يكون async for x in source هو الصياغة الأنظف.
بالنسبة للمصادر التي تبثّ حتى شرط نهاية محدّد، يطلق المكرِّر StopAsyncIteration وتخرج async for بشكل طبيعي. أما المصادر التي لا تنتهي أبدًا -- تدفق مستشعر مستمر، أو اشتراك طويل الأمد -- فتعمل الحلقة حتى يتم إلغاء الكوروتين التي تعيش فيها أو هدم مهمتها.