المولدات Generators في بايثون
المولّدات هي أداة بسيطة وقوية لإنشاء المكرِّرات. تأخذ المولِّدات صيغة الدوال العادية ولكنّها تستخدم عبارة yield
عند إعادة البيانات. في كلّ مرة تستدعى فيها الدالة next()
على المولّدات تعود الأخيرة إلى المكان الذي تركته (تتذكر المولّدات جميع القيم والعبارات التي نفّذت أخيرًا). يوضح المثال التالي كيفية إنشاء المولّدات وآلية عملها:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>>
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
يمكن إنجاز كل ما تقوم به المولّدات باستخدام مكرِّرات صنفية (class-based iterators) كما هو موضّح في قسم المكرِّرات. ولكن ما يجعل المولّدات مختصرة بهذه الشاكلة هو أنّ اللغة تنشئ التابعين __iter__()
و __next__()
بصورة تلقائية.
من الميزات المهمّة أيضًا أنّ المتغيرّات المحلية (local variables) وحالة التنفيذ (execution state) تُحفظان بصورة تلقائية بين عمليات الاستدعاء المتعاقبة، ممّا يسهل كتابة الدوال ويجعلها أكثر وضوحًا مقارنة بالأسلوب الذي يعتمد على متغيرات النسخ مثل self.index
و self.data
.
وإلى جانب إنشاء التوابع بصورة تلقائية وحفظ حالة البرنامج، تطلق المولِّدات عند انتهاء عملها وبصورة تلقائية الخطأ StopIteration
. كلّ ما سبق يجعل عملية إنشاء المكرِّرات بنفس سهولة إنشاء الدوال الاعتيادية.
تعابير المولّدات Generator Expressions
يمكن إنشاء بعض المولّدات البسيطة باستخدام تعابير وصياغات مختصرة شبيهة بصياغة list comprehensions ولكن باستخدام الأقواس الهلالية بدلًا من الأقواس المربعة. صمّمت هذه التعابير للاستفادة منها في الحالات التي يكون فيها المولّد محاطًا بدالّة أخرى. تكون تعابير المولّدات أكثر اختصارًا ولكن استخداماتها محدودة مقارنة بطريقة التعريف الكاملة للمولدات، وتميل هذه التعابير لأن تكون أقل استهلاكًا للذاكرة مقارنة بـ list comprehensions المقابلة.
إليك فيما يلي بعض الأمثلة:
>>> sum(i*i for i in range(10)) # مجموع مربّعات الأرقام
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # الجداء النقطي
260
>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
>>> unique_words = set(word for line in page for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']
مصادر
- صفحة Classes في توثيق بايثون الرسمي.