أحمد حايس
الرئيسيةمن أناالدوراتالمدونةالعروض
أحمد حايس

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

المنصة مبنية على الوضوح، التطبيق، والنتيجة النافعة: شرح مرتب يساعدك تفهم الأدوات، تكتب كودًا أفضل، وتستخدم الذكاء الاصطناعي بوعي داخل العمل الحقيقي.

تعلم أسرعوصول مباشر للدورات والمسارات من الموبايل.
تنقل أوضحالروابط الأساسية والدعم في مكان واحد بدون تشتيت.

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • العروض
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع
محتاج مسار سريع؟
ابدأ من الدوراتتواصل معناالأسئلة الشائعة

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالعروضالمدونةالدخول

Python match/case: امتى يستحق إنه يستبدل if/elif في كودك

📅 ١٩ أبريل ٢٠٢٦⏱ 5 دقائق قراءة
Python match/case: امتى يستحق إنه يستبدل if/elif في كودك
Python match/case: امتى يستحق إنه يستبدل if/elif في كودك

Python 3.10 ضاف match/case من 4 سنين تقريبًا، ولحد دلوقتي أغلب الكود العربي اللي بنشوفه في GitHub لسه بيكتب سلاسل if/elif في حالات match فيها بيوفّر 30 سطر فعلًا. المقال يديك بالظبط امتى تستخدمه، وامتى يبقى مبالغة، بكود webhook حقيقي.

المشكلة باختصار

الـ if/elif في Python كويس لما عندك شرطين أو ثلاثة. المشكلة بتبدأ لما تيجي تـ parse استجابة API بشكل dict متشعّب، أو لما عندك 8 حالات لـ event types مختلفة. الكود بيبقى صعب القراءة، وبتنسى تتعامل مع حالة. match/case في Python 3.10+ بيحلّ ده، لكنه مش مجرد switch من C — الفرق الجوهري إنه structural، يعني بيقدر يفكّك (destructure) القيم وقت المطابقة نفسها.

شاشة كود بايثون توضح بنية match/case مع pattern destructuring لـ dict

الفرق الجوهري عن if/elif

match/case بيعمل حاجتين في نفس الوقت: مطابقة الشكل، واستخراج القيم. if/elif بيعمل المطابقة بس، الاستخراج بتعمله بإيدك في الجوّا. المثال ده على كائن webhook بيجي من Stripe بيوضح الفرق:

Python
event = {"type": "payment.succeeded", "data": {"amount": 5000, "currency": "usd"}}

# الطريقة بـ if/elif (10 سطور وفيها تكرار get)
if event.get("type") == "payment.succeeded":
    amount = event.get("data", {}).get("amount")
    currency = event.get("data", {}).get("currency")
    if isinstance(amount, int) and isinstance(currency, str):
        process_payment(amount, currency)
elif event.get("type") == "payment.failed":
    reason = event.get("data", {}).get("reason", "unknown")
    log_failure(reason)

# الطريقة بـ match/case (5 سطور)
match event:
    case {"type": "payment.succeeded", "data": {"amount": int(amount), "currency": str(currency)}}:
        process_payment(amount, currency)
    case {"type": "payment.failed", "data": {"reason": reason}}:
        log_failure(reason)
    case _:
        log_unknown(event)

الفرق هنا مش جمالي. الـ pattern match بيتحقق من النوع (int, str) وبيستخرج القيمة في خطوة واحدة. لو الـ amount جاي string من webhook غلط، الـ case ده ما بيتطابقش، وبتنزل تلقائيًا للـ case _. الكود ده مش هيعمل crash بـ TypeError زي الـ if/elif.

أربعة أنماط هتستخدمها فعلًا

  1. Literal patterns — قيم ثابتة. case 200:
  2. Sequence patterns — قوائم وtuples مع unpacking. case [first, *rest]:
  3. Mapping patterns — dicts. case {"status": "ok", "data": data}:
  4. Class patterns — instances مع dataclasses أو NamedTuple. case Point(x=0, y=y):

الـ guards بتضيف شرط فوق المطابقة:

Python
match request:
    case {"method": "POST", "path": path} if path.startswith("/api/"):
        handle_api(path)
    case {"method": "GET", "path": "/health"}:
        return {"ok": True}
محرر كود يعرض refactor من سلسلة if/elif طويلة إلى match/case أقصر

سيناريو واقعي بأرقام

في خدمة بتعالج 50 ألف webhook في اليوم من 7 مصادر مختلفة (Stripe, GitHub, Slack, Shopify…)، قبل التحويل كان عندنا 280 سطر if/elif موزّعة على 4 ملفات. بعد إعادة الكتابة بـ match بقت 120 سطر في ملف واحد، يعني وفّرنا 57% من السطور. الـ benchmark على Python 3.12 بـ pytest-benchmark أظهر إن match أبطأ 3% بس من if/elif في الحالات البسيطة، وأسرع 12% في الحالات اللي فيها dict deeply nested — لأن CPython بيـ optimize الـ subject مرة واحدة بدل ما يقيّمه في كل فرع.

الافتراض هنا: عندك 4 حالات أو أكثر، وكل حالة بتعمل destructuring لـ dict أو object. لو الحالات أقل من 3 وبسيطة (مجرد مقارنة قيمة)، الفرق هيبقى مش محسوس وممكن يكون if/elif أوضح.

trade-offs لازم تعرفها

المكسب: كود أقصر، تحقق من النوع مع الاستخراج في خطوة واحدة، وضوح بصري لكل الحالات في مكان واحد، أقل bugs بسبب نسيان get() أو isinstance().

الثمن: Python 3.10+ فقط — لو فريقك لسه على 3.9 في production، النقاش هيتأجل لحد ما تعمل upgrade. الـ name binding في الـ patterns ممكن يلخبط مبتدئ: في case Point(x=0, y=y) الـ y هنا اسم متغير جديد بيتعمله bind للقيمة، مش مقارنة بمتغير y موجود في الـ scope. ده بيسبب bugs خفية أول ما تشتغل بيه؛ Python بترمي SyntaxError لو حاولت تحط dotted name case Point(x=0, y=other.y) عشان تجبرك على التفريق.

كمان الـ static analyzers (mypy, pyright) كانت ضعيفة في تحليل match لحد 2024، دلوقتي بقت معقولة لكن لسه مش زي if/elif في تتبع الأنواع داخل كل فرع.

غلطة شائعة: capture vs constant

أكتر بَج بنشوفه في كود الناس اللي لسه بتتعلم match:

Python
STATUS_OK = 200

match response.status:
    case STATUS_OK:        # ❌ ده مش بيقارن بـ 200
        handle_ok()        # ده بيـ rebind الاسم STATUS_OK لقيمة status

الحل: استخدم dotted name (case http.STATUS_OK:) أو قارن صراحة (case 200:). ده مذكور حرفيًا في PEP 634 تحت "Capture Patterns".

متى لا تستخدم match/case

  • عندك حالتين فقط — if/else أوضح وأقصر.
  • الشروط منطقية مركبة مش مرتبطة بشكل البيانات (مثلاً x > 5 and user.is_admin and not throttled) — استخدم if.
  • لازم تدعم Python أقل من 3.10 — match/case هيرمي SyntaxError في وقت الـ import.
  • الفريق ما يعرفش الـ syntax — كلّفهم نص ساعة قراءة PEP 636 الأول، أحسن من PR هييجي مليان debate.
  • بتعمل dispatch على نوع واحد بس مع شوية لوجيك — dict mapping من string لـ function أوضح وأسرع.

الخطوة التالية

افتح أطول if/elif في الكود بتاعك دلوقتي. لو فيه 4 فروع أو أكثر وأي منهم بيعمل data.get(...) أو isinstance()، حوّله لـ match/case في PR صغير وقارن سطور الكود قبل/بعد. لو وفّرت 30% أو أكثر، عمّمها على الباقي. لو لأ، رجّع التغيير وما تخسرش وقت الفريق في review.

مصادر

  • PEP 634 — Structural Pattern Matching: Specification
  • PEP 636 — Structural Pattern Matching: Tutorial
  • Python 3.10 What's New — match statement
  • Python Language Reference — The match statement
  • PEP 635 — Structural Pattern Matching: Motivation and Rationale
]]>

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة