1. المقدمة
بايثون هي لغة برمجة محبوبة بفضل بساطة تركيبها وقوة ميزاتها. من بين هذه الميزات، تُعتبر الكلمة المفتاحية yield
أداة مهمة جدًا لتحسين كفاءة الذاكرة والأداء. باستخدام yield
، يمكنك إيقاف واستئناف التكرار أثناء معالجة البيانات، وهو ما يجعلها مثالية للتعامل مع البيانات الضخمة أو تدفقات البيانات.
في هذا المقال، سنشرح خطوة بخطوة كيفية استخدام yield
في بايثون، بدءًا من الأساسيات وحتى الاستخدامات المتقدمة. المقال موجه للمبتدئين والمبرمجين من المستوى المتوسط، وسيوفر لك معلومات عملية تساعدك على الاستفادة من هذه الميزة بشكل كامل.
2. أساسيات الدوال المولدة و yield
2.1 ما هي yield
؟
yield
هي كلمة مفتاحية تُستخدم داخل الدوال المولدة (Generator Functions)، حيث تقوم بإرجاع قيمة مؤقتًا وإيقاف تنفيذ الدالة. عند استدعاء الدالة مرة أخرى، تستأنف العملية من حيث توقفت. هذا يسمح بمعالجة البيانات بشكل جزئي بدلاً من معالجتها بالكامل دفعة واحدة.
def count_up_to(max_value):
count = 1
while count <= max_value:
yield count
count += 1
هذه الدالة تقوم بالعد حتى القيمة القصوى المحددة، وتُرجع قيمة واحدة في كل مرة يتم استدعاؤها.
2.2 الفرق بين return
و yield
بينما return
تُنهي تنفيذ الدالة وتُرجع النتيجة، فإن yield
توقف التنفيذ مؤقتًا فقط وتستأنف عند الاستدعاء التالي. هذا يعني أنه يمكنك الحصول على القيم عند الحاجة فقط، دون تحميل كل البيانات دفعة واحدة في الذاكرة.
def simple_return():
return [1, 2, 3]
في هذا المثال باستخدام return
، يتم إرجاع القائمة كاملة دفعة واحدة، مما قد يزيد من استهلاك الذاكرة.

3. العلاقة بين المولدات (Generators) والكائنات المكررة (Iterators)
3.1 أساسيات الـ Iterator
الكائن المكرر (Iterator) هو كائن يُعيد البيانات عنصرًا تلو الآخر، ويجب أن يُنفّذ الدالتين __iter__
و __next__
. هذا يسمح بمعالجة البيانات بشكل تسلسلي باستخدام الحلقات. المولد (Generator) هو نوع خاص من الـ Iterator يتم إنشاؤه بسهولة باستخدام yield
.
def custom_generator(start, end):
while start < end:
yield start
start += 1
باستخدام yield
، يمكننا تجنّب كتابة الكثير من الأكواد اليدوية لإنشاء Iterator، وجعل المعالجة أبسط وأكثر وضوحًا.
3.2 الفرق بين Iterator و Generator
المولد (Generator) يُنشئ Iterator تلقائيًا باستخدام yield
. بينما في الـ Iterator التقليدي، تحتاج إلى تنفيذ __iter__
و __next__
يدويًا، يمكن اختصار ذلك بشكل كبير عند استخدام Generators. هذا يُبسّط الكود ويُسهّل صيانته.
4. فوائد استخدام yield
وأمثلة عملية
4.1 تحسين كفاءة الذاكرة
من أبرز فوائد yield
أنها تُحسن استخدام الذاكرة. في الدوال العادية، يجب إرجاع كل البيانات دفعة واحدة، بينما yield
تُرجع البيانات عنصرًا عنصرًا، مما يقلل استهلاك الذاكرة. هذا مفيد جدًا عند التعامل مع مجموعات بيانات ضخمة أو تسلسلات لا نهائية.
على سبيل المثال:
def large_data_generator(data):
for item in data:
yield item
هذه الدالة لا تعالج كل البيانات دفعة واحدة، بل تُعالجها عند الحاجة، مما يُحسن الأداء بشكل ملحوظ.
4.2 سيناريوهات عملية
- معالجة ملفات السجلات (Logs): عند قراءة ملف ضخم سطرًا بسطر، يمكنك استخدام
yield
لتجنّب تحميل الملف كاملًا في الذاكرة. - استخلاص البيانات من الويب (Web Scraping): يمكن استخدام
yield
لمعالجة البيانات المستخرجة عنصرًا تلو الآخر، مما يجعل التعامل مع كميات كبيرة من البيانات أكثر كفاءة.

5. التعامل مع المولدات الفرعية باستخدام yield from
5.1 ما هو yield from
؟
yield from
يُستخدم لإرجاع القيم مباشرةً من مولد أو Iterator آخر. هذا يُسهّل دمج عدة مولدات في دالة واحدة ويحسن من قابلية قراءة الكود.
def sub_generator():
yield 1
yield 2
yield 3
def main_generator():
yield from sub_generator()
yield 4
في هذا المثال، main_generator
يُرجع القيم من sub_generator
مباشرة، ثم يُرجع أيضًا القيمة 4
.
5.2 مثال عملي
على سبيل المثال، عند التعامل مع بيانات من مصادر متعددة، يمكن دمج المولدات المختلفة باستخدام yield from
لتسهيل المعالجة وزيادة مرونة الكود.
6. استخدامات متقدمة لأنماط الاستجابة في الدوال المولدة
6.1 ما هو نمط الاستجابة؟
يمكن للدوال المولدة أن تستقبل بيانات من الخارج وتُعدل سلوكها بناءً على هذه المدخلات، وهو ما يُعرف بـ “نمط الاستجابة”. باستخدام yield
، يمكن للدالة إرجاع قيمة وأيضًا استقبال قيمة من الاستدعاء التالي، مما يتيح التواصل ثنائي الاتجاه.
def responder():
response = None
while True:
query = yield response
if query == "Hello":
response = "Hi!"
else:
response = "I don't understand."
6.2 أمثلة عملية
- روبوتات الدردشة (Chatbots): يمكن استخدام Generators لإنشاء روبوت يرد على مدخلات المستخدم بشكل تفاعلي.
- آلات الحالات (State Machines): يمكن استخدام
yield
لتغيير السلوك حسب الحالة الحالية، مما يجعل تصميم الآلة أكثر مرونة.
7. الخلاصة والخطوات القادمة للتعلم
في هذا المقال، قمنا بشرح yield
في بايثون من الأساسيات وحتى الاستخدامات المتقدمة. تُعد yield
أداة قوية لتحسين كفاءة الذاكرة وزيادة الأداء، وهي مفيدة بشكل خاص عند التعامل مع البيانات الضخمة أو البرامج التفاعلية.
كخطوة تالية، يُنصح بدراسة yield from
ومعالجة المهام غير المتزامنة باستخدام async
/ await
لتوسيع مهاراتك في بايثون. هذا سيمكنك من بناء برامج أكثر قوة ومرونة. ننصحك بقراءة التوثيق الرسمي وتجربة مشاريع عملية لاكتساب فهم أعمق وتطبيق عملي لهذه المفاهيم.