فاطـمہ آدم | Fatma Adam
فاطـمہ آدم | Fatma Adam

@_fatmaadam

24 تغريدة 15 قراءة Jan 28, 2020
GENERATORS IN PYTHON
مرحبا مجددًا مجتمع #بايثون?
#missxpy
يعتبر مفهوم #generators أحد المفاهيم البايثونية في بايثون رغم سهولتها إلا أن هناك بعض الصعوبات في فهمها للوهلة الاولى وخلال هذا الثريد بإذن الله سنحاول معًا هزم هذا الجدار المخيف للاستمتاع بمميزات generators الرائعة!
المحاور :
⚪️#Iterables , #iterators and #iteration
⚪️ ماهية generators
⚪️#Generators_expression
⚪️#Generators_functions
⚪️#Recursive_Generators functions
?ملاحظة : لفهم محتوى هذا الثريد لابد الإلمام باساسيات بايثون !
بدأنا?
⚪️#Iterables , #iterators and #iteration
قبل المضي قدمًا هناك مصطلحات معينة يجب في بادىء الأمر أن نتأكد من مدى استيعابنا لها :
Iterables , iterators , iteration
إذا كانت هذه المرة الأولى التي تسمع بها هذه المصطلحات لا داعي للذعر! فانت تتعامل دومًا معاها وما بقي علينا فقط وضع النقاط على الحروف لفهم الأحجية ?
فرضًا لو أردنا عمل برنامج يقوم بطباعة عناصر قائمة ما عنصر تلو الآخر فأول ما تفكر به التالي :
السؤال الآن ما الذي تقوم به #for تحديدًا خلف الستار ؟
تتبع for loop نهج يطلق عليه #iterator_protocol
وإذا اختصرنا هذا النهج هو عبارة عن أي كائن يدعم دالتي __iter__ and ()__next__()
حيث ان for loop تتبع هذا النهج بشكل افتراضي !
فلو أردنا تفصيل ماتقوم به for loop بالمثال السابق يكون كالتالي :
1- يتم تحديد العنصر وتعريفه لدالة __iter__() وماتقوم به هذه الدالة إرجاع كائن من نوع #iterables
2- تقوم for باستدعاء دالة .__next__() تلقائيًا للحصول على القيمة الأولى من قيم الكائن الذي تم تعريفه مسبقًا
3- تستمر باستدعاء الدالة إلى ان يتم تفريغ جميع القيم وتتوقف for عن التكرار في حال واجهت خطأ #StopIteration والذي يدل على تفريغ كافة قيم الكائن
?#Iterables
يعبر iterable عن أي كائن يحتوي على عناصر أخرى يمكن فهرستها ومثال على ذلك :
#lists , #tuples , #strings ...etc
ولمعرفة إذا كان نوع البيانات يعتبر #Iterable ام لا عن طريق دالة
iter(object)
مثال :
?#Iterators
العناصر بداخل iterable يطلق عليها Iterators ولمعرفة Iterators او العناصر لكل كائن يمكن استخدام دالة
next(iterable)
?ملاحظة : في حال انتهاء العناصر الدالة next تعطي خطأ #StopIteration
مثال :
?iteration
التكرار أو العملية التي من خلالها نحصل على عناصر iterable
غالبًا مايقصد بها for loop
?ملاحظة : هناك أنواع عديدة في بايثون يطلق عليها iterable سواء عناصر مبنية في بايثون او مكتبات معينة او حتى يمكن بناء iterable خاص بك عن طريق الكلاسات واضافة دالتي
__iter__() and __next__ ()
ويمكن جعل كل كائن في بايثون iterable
⚪️ ماهية generators
بعدالتعرف على المصطلحات المهمةننوه الى أن:
Generators تعتبر iterables.
وماتقوم به باختصارانها لاتعطي جميع القيم مرة واحدة بل قيمة تل الاخرى في حال طلبها لابأس إن لم يكون التعريف واضحا سيتضح مع الامثلة!
اشكالها:
1⃣ generator expression
2⃣ generator function
⚪️#Generators_expression
في ثريد سابق تحدثت عن list comprehension بالتفصيل و generator expression ليست بعيدة تمامًا عنه بل هي طبق الأصل ولكن بدل من استخدام اقواس #lists [] سنستخدم اقواس #tuples ()
مثال :
⚪️#Generators_functions
وهي تمامًا لاتختلف عن الدوال الاعتيادية في بايثون ولكن بدل استخدام return سنستخدم مايطلق عليه yield
حيث تعتبر yield كلمة محجوزة في بايثون تعبر عن استخدام
Generators functions
مثال :
الفرق بين yield و return ان return تقوم بإعادة جميع العناصر ومايتم كتابته بعد سطر return بالدالة لايتم التعرف به
على عكس yield يمكن كتابة اكثر من yield في الدالة وماتقوم به باختصار انها تعطي قيمة واحدة من القيم كل ماتم استدعاء الدالة وتنهي تلك القيم فور طلبها
بينما الفرق بين list comprehension و generator expression كما لاحظنا سابقًا إن list comprehension تقوم بشكل مباشر حفظ الناتج في قائمة جديدة عكس generator expression لانحصل على القيم الا حين طلبها
وهنا تكمن فائدة generators القصوى بصفة عامة في الحفاظ على الذاكرة خصوصًا في البيانات الضخمة او الكبيرة نوعًا ما حيث أن generators بمختلف انواعها لاتحتفظ القيم بالذاكرة ولاتعطي القيمة الا حين طلبها وفي حال تم الانتهاء منها لا يكون وجود لتلك القيم إطلاقًا
وهذا مثال يوضح الفرق في استهلاك الذاكرة مابين list comprehension و generator expression
? ملاحظة :في حال كان الهدف الحفاظ ع استهلاك الذاكرة وليس السرعة فان generator هي الانسب ولكن إن كان الهدف الاساسي السرعة فان list comprehension هي الأفضل
والآن سيتبادر الى ذهنك إذا كيف ساقوم بطلب القيم من generators ؟
هناك عدة طرق للقيام بذلك منها :
? استخدام دالة next() كما ذكر سابقًا عند تعريف iterables
ولكن هذه الطريقة ليست عمليًا بتاتًا
? استخدام دالة list ()
كما نعلم ان list () احد الدوال المبنية في بايثون والتي تقوم بتحويل اي iterable الى قائمة
لكن حين استخدام دالة list اننا سنفقد الفائدة والمزايا التي تقدمها لنا generators وهي الحفاظ على اداء الذاكرة !
? استخدام for loop
حل الامثلة السابقة بالطريقتين :
list ()
for loop
? ملاحظة : في حال تعريف generator لمتغير وتم طلب قيمها ستختفي تلك القيم تلقائيًا ولن تستطيع طلب تلك القيم مرة اخرى !
⚪️#Recursive_Generators functions
تعبر recursive function بالعادة على الدالة التي تستدعي نفسها فهل يمكن ايضَا استدعاء generators functions لنفسه ؟
نعم يمكن عمل ذلك
مثال :
وفي الختام اتمنى ان تكون الصورة اتضحت لديكم الآن عالم generators جميل جدًا استخدموه في برامجكم بما تروه مناسبًا شاركونا تجاربكم مع generators وكيف استفدتم منها .
دمتم بود ?️

جاري تحميل الاقتراحات...