الدرس 10 من 10
التنظيف المضمون
- 15 دقيقة
- 6 فحوص
- 3 تلميحات
- إلى المطلوب
هدف الدرس
جملة with تضمن التنظيف مهما حدث
الشرح
الكود الحالي يأخذ القفل ثم يحرّره، وبينهما سطر قد يقع فيه خطأ، فإن وقع لم يصل التنفيذ إلى release، وبقي القفل مأخوذًا إلى الأبد، وفشل كل استدعاء بعده. شغّل الكود وانظر بنفسك.
أما with فيضمن التنظيف، فهو يستدعي __enter__ عند الدخول، ويضع ما تُرجعه في المتغيّر الذي بعد as، ثم يستدعي __exit__ عند الخروج أيًّا كان سببه، سواء انتهى الكود طبيعيًّا أو وقع استثناء. وهكذا يعمل with open(...)، فتكتب التنظيف مرّة واحدة في الصنف بدل أن تكتب try/finally في كل مكان يُستعمل فيه.
والفخّ أن __exit__ تستقبل تفاصيل الاستثناء، وإذا أرجعت True أخفته كأنه لم يقع، لذلك لا تُرجع منها شيئًا ليكمل الخطأ طريقه إلى من يعالجه. وإذا أردت أن تكتب دالة بدل صنف فهناك طريقة أقصر، وهي @contextlib.contextmanager مع yield داخل try/finally، ومن ينسى finally فيها يرجع إلى المشكلة نفسها.
المطلوب
أضف إلى Lock دالة __enter__ تأخذ القفل وتُرجع self، ودالة __exit__ تحرّره دائمًا ولا تُخفي الخطأ، ثم أعد كتابة update باستعمال with lock:.
الفحوص
6 فحوص- القفل مأخوذ داخل with
- الكلمة as تعطي القفل نفسه
- القفل يُحرَّر عند الخروج الطبيعي
- القفل يُحرَّر حتى لو وقع خطأ داخله
- الدالة __exit__ لا تُخفي الخطأ
- الدالة update تحرّر القفل رغم الخطأ