من خلال بحثي ماعرفته عن yield انها مثل return
لكن لو سمحتم اريد مثال شامل يوضح معناها
واذا كانت مثل return هل تستخدم خارج الدالة؟
def a(): for i in range(10): yield i
في هذا المثال مالفائدة اذا كان استخدامها بهذه الطريقة فقط
for i in a(): print(i)
من خلال بحثي ماعرفته عن yield انها مثل return
لكن لو سمحتم اريد مثال شامل يوضح معناها
واذا كانت مثل return هل تستخدم خارج الدالة؟
def a(): for i in range(10): yield i
في هذا المثال مالفائدة اذا كان استخدامها بهذه الطريقة فقط
for i in a(): print(i)
بدونها ربما ستكتب شيء مثل:
>>> def a(): ... lst = [] ... for i in range(10): ... lst.append(i) ... return lst ... >>> >>> a() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>>
هناك حالات قد لايريد فيها المستخدم أن تعيد له list، يريدها مثلاً لـtuple، أو قد لايستخدم كامل عناصرها، مضيعة للذاكرة لكن يبقى أنك تحتاج وسيط يحمل هذه العناصر فالدالة لن تعيد إلا قيمة واحدة.
الحل الوسط أن تعيد له مولد لهذه العناصر والمستخدم يستخدمه لما يناسبه، ففي النهاية المهم هي العناصر وليس القالب الذي يحويها.
yield تجعل الدالة كما قلت تعيد كائن مولد generator (نوع من أنواع المكررات iterators) يولد هذه الأرقام على رقم رقم:
>>> def a(): ... for i in range(10): ... yield i ... >>> >>> a() <generator object a at 0x01ECF6E8> >>>
يمكن استخدام الوظيفة __next__ في هذا الكائن المعاد لتويد الرقم التالي او استخدام الدالة next (تستدعي __next__ داخلياً):
>>> a() <generator object a at 0x01ECF6E8> >>> >>> g = a() >>> next(g) # or g.__next__() 0 >>> next(g) # or g.__next__() 1 >>> next(g) # or g.__next__() 2 ... 8 >>> next(g) # or g.__next__() 9 >>> next(g) # or g.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
عند الإنتهاء من توليد آخر قيمة سنتج استثناء StopIteration.
الآن لاحاجة لتويد كل الأرقام كما في الدالة الأولى وتخزينها في list ثم تحويلها لـtuple، تعيد مولد والمستخدم يحولها لما يريد (الدوال التي كانت تعيد list في بايثون 2 أصبحت تعيد generators في بايثون 3 لهذا السبب):
>>> list(a()) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> tuple(a()) (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) >>>
ولسنا مضظرين لتوليد كل العناصر كي نحصل فقط على أول خمسة أرقام:
>>> g = a() >>> n = 0 >>> while n < 5: ... print(next(g)) ... n += 1 ... 0 1 2 3 4 >>>
الـgenerator طريقة من طرق إنشاء المكررات iterators، ربما تقرأ عنها أولاً.
شكرا لك على الشرح وجارى الإطلاع عليه :) :)
حتى تفهم الامرyield جيدا ، يجب ان تفهم الفرق بينه وبين return المستخدم في ارجاع قيم الدوال
عند تنفيذ دالة ما . فان بايثون يقوم بحجز مساحة في الذاكرة namespace ليضع فيها المتغيرات المحلية local variables الخاصة بالدالة.
تم تعديل هذه المشاركة بواسطة med reda في 12 يوليو 2014 في 05:10