بروتوكول __enter__ و__exit__
أنشئ مديري سياق باستخدام بروتوكول dunder
بروتوكول __enter__ و__exit__ درس مجاني في Python Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Python Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Python Academy 4 دروس في المجموع.
بروتوكول مدير السياق
أي كائن يعرّف __enter__ و__exit__ هو مدير سياق، ويمكن استخدامه مع with.
class Managed:
def __enter__(self):
print("entering")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("exiting")
return False
with Managed() as m:
print("inside")القيمة المُرجعة من __enter__
يُستدعى __enter__ عند بداية كتلة with. وتُربط القيمة التي يُرجعها بالمتغير الذي يأتي بعد as.
class Resource:
def __enter__(self):
self.value = 42
return self # bound to 'r'
def __exit__(self, *args):
self.value = None
return False
with Resource() as r:
print(r.value) # 42وسائط __exit__
يستقبل __exit__(exc_type, exc_val, exc_tb) معلومات الاستثناء إذا وقع خطأ. وإذا لم يقع استثناء، تكون القيم الثلاث كلها None.
class Safe:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is ValueError:
print(f"Suppressed ValueError: {exc_val}")
return True # suppress the exception
return False # re-raise anything else
with Safe():
raise ValueError("oops") # suppressedإخفاء الاستثناءات
أرجع True من __exit__ لإخفاء الاستثناء. وأرجع False أو لا تُرجع شيئًا للسماح بانتقاله.
class Ignore:
def __enter__(self): return self
def __exit__(self, *args): return True # swallow all exceptions
with Ignore():
1 / 0
print("continues here")مثال على اتصال بقاعدة بيانات
حالة استخدام كلاسيكية: الحصول على اتصال عند الدخول، ثم تثبيت التغييرات أو التراجع عنها وإغلاق الاتصال عند الخروج.
class DBConn:
def __enter__(self):
self.conn = connect_db()
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
self.conn.rollback()
else:
self.conn.commit()
self.conn.close()
return Falseمدير سياق لمؤقت
قِس الوقت المنقضي عبر تسجيل وقت البدء في __enter__ وحساب الفرق في __exit__.
import time
class Timer:
def __enter__(self):
self.start = time.perf_counter()
return self
def __exit__(self, *args):
self.elapsed = time.perf_counter() - self.start
print(f"Elapsed: {self.elapsed:.3f}s")
return False
with Timer():
sum(range(1_000_000))تداخل مديري السياق
يمكن دمج عدة مديري سياق في سطر with واحد.
with open("in.txt") as src, open("out.txt", "w") as dst:
dst.write(src.read())مديرو السياق القابلون لإعادة الاستخدام مقابل المستخدمين مرة واحدة
مديرو السياق الذين يخصّص __enter__ لديهم موردًا جديدًا في كل مرة قابلون لإعادة الاستخدام. أما الذين يستنفدون حالة داخلية، مثل قفل لا يُمسك إلا مرة واحدة، فقد لا يكونون كذلك.
class Reusable:
def __enter__(self):
return []
def __exit__(self, *a):
return False
for _ in range(3):
with Reusable() as lst:
lst.append(1)
print(lst) # [1] each time__aenter__ و__aexit__ (غير متزامن)
بالنسبة إلى مديري السياق غير المتزامنين، عرّف الدالتين غير المتزامنتين __aenter__ و__aexit__، واستخدم async with.
class AsyncDB:
async def __aenter__(self):
self.conn = await connect()
return self.conn
async def __aexit__(self, *args):
await self.conn.close()
# async with AsyncDB() as conn:
# ...تغليف كائنات الملفات
تنفذ كائنات الملفات في Python بروتوكول مدير السياق مسبقًا، لذا لا تستدعِ f.close() يدويًا أبدًا.
with open("data.txt", "r") as f:
data = f.read()
# file is closed here automatically
print(f.closed) # Trueتنفيذ قفل
أقفال مؤشرات الترابط هي مديرو سياق: يستحوذ __enter__ على القفل، ويحرره __exit__.
import threading
lock = threading.Lock()
def update_shared():
with lock:
# critical section
passتحقق سريع
ما الذي يجب أن تُعيده __exit__ لكبت استثناء؟
مراجعة
نفّذ __enter__ و__exit__ لإنشاء مديري سياق. أعد المورد من __enter__، وتولَّ التنظيف وكبت الاستثناءات في __exit__.
الأسئلة الشائعة
هل درس «بروتوكول __enter__ و__exit__» مجاني؟
نعم — نص درس «بروتوكول __enter__ و__exit__» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Python Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Python Academy 4 دروس في المجموع.
ماذا ستتعلم في «بروتوكول __enter__ و__exit__»؟
أنشئ مديري سياق باستخدام بروتوكول dunder تتمرن على Python Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Python Academy؟
لا تُشترط خبرة سابقة. Python Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «بروتوكول __enter__ و__exit__»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Python Academy هذا؟
نعم. كل درس في Python Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- عبارة with بالتفصيل
- بروتوكول __enter__ و__exit__
- contextlib: @contextmanager
- أنماط مديري السياق العملية