{
  "assessmentTests": {
    "python_test": {
      "name": "اختبار بايثون",
      "desc": "30 سؤال سيناريو حول بناء الجملة والدوال وهياكل البيانات والسلوك الكائني — تحقق ما إذا كان فهمك لبايثون يطابق ما تقصده إعلانات الوظائف بمصطلح الكفاءة في بايثون.",
      "recommendation": "ملف ملخص مهاراتك في بايثون",
      "results": {
        "beginner": {
          "name": "مبتدئ",
          "desc": "يمكنك متابعة سكريبت قصير وتغيير القيم فيه، لكن الأسئلة التي فشلت بها تتجمع حول سلوك اللغة الخاص بدلاً من المنطق العام — عامل افتراضي يُبنى مرة واحدة ويُستخدم مجدداً، is مقابل == على قائمتين متطابقتين الشكل، متغير يصبح محلياً في اللحظة التي تسند قيمة له في أي مكان داخل دالة. لا يتعلق أي من هذا بكون البرمجة سيئة؛ هذه قواعد خاصة ببايثون تربك الأشخاص القادمين من لغات أخرى تماماً كما تربك المبتدئين. تأتي أهميتها في العمل لأن كل واحدة منها هي المكان الذي تختبئ فيه خطأ في كود يبدو صحيحاً من النظرة الأولى.",
          "recommendation": "ابدأ بثلاثة أشياء، بهذا الترتيب: العوامل الافتراضية القابلة للتغيير (لماذا basket=[] خطيرة)، الفرق بين is و ==، وكيفية عمل نطاق المتغيرات داخل دالة. البرنامج التعليمي الرسمي لبايثون على docs.python.org يغطي جميعها بشكل مباشر، والبحث عن \"Python gotchas\" يعطيك أمثلة عملية على كل منها."
        },
        "intermediate": {
          "name": "متوسط",
          "desc": "تتعامل مع السكريبتات اليومية بارتياح — هياكل البيانات وتدفق التحكم والدوال المباشرة — ولن تبطأ من قبل أعمال الصيانة الروتينية أو ميزة صغيرة في قاعدة بيانات موجودة. الفجوة بين هنا والمتقدم تتعلق بشكل أساسي بما يحدث عندما تتفاعل ميزات راحة بايثون مع بعضها: نسخ سطحية تترك البيانات المتداخلة مشتركة عندما كنت تتوقع تكرارها، قيمة عودة المولد لا تصبح بصمت جزءاً من مخرجاته، ديكوريتورز مكدسة بترتيب يسهل الخلط فيه. هذه هي أنواع الأخطاء التي يحددها المراجع الأول في عشر ثواني والجميع الآخرين ينفقون ساعة في البحث عنها.",
          "recommendation": "ركز على جوهريات الكائنات والتكرار: النسخة السطحية مقابل النسخة العميقة، ما الذي يفعله المولد فعلاً مع return، وكيفية عمل ترتيب تكديس الديكوريتورز. ثم أساسيات الفئات التي تتجاوزها معظم البرامج التعليمية — المساواة الافتراضية بدون __eq__، ولماذا سمة فئة قابلة للتغيير مشتركة بين كل مثيل."
        },
        "advanced": {
          "name": "متقدم",
          "desc": "هذا هو المستوى الذي تعنيه معظم إعلانات الوظائف بـ \"بايثون قوي\". تصل إلى الأداة المناسبة بدون البحث عنها، وتعرف لماذا تغيرت حالة مشتركة بدلاً من معرفة أنها تغيرت فقط، ويمكنك قراءة دالة شخص آخر والتنبؤ بمخرجاتها بشكل صحيح. ما يميز هذا المستوى عن الأعلى هو الجانب الدفاعي من العمل: معرفة أي من النهجين الصحيحين سيسوء بمجرد وجود سمة فئة أو عامل كلمة دالية حصرية أو تسلسل هرمي لاستثناء.",
          "recommendation": "اختر الأجزاء التي تحمي قاعدة بيانات يلمسها الآخرون أيضاً: العوامل ذات الكلمات الدالية الحصرية كخيار تصميم API بدلاً من فضول بناء جملة، تسلسل الاستثناء الهرمي (بحيث تلتقط جملات except العائلة الصحيحة من الخطأ، وليس فقط فئة واحدة)، ومديري السياق كالطريقة القياسية لضمان التنظيف. مقالات Real Python الخاصة بالغوص العميق تعتبر محطة جيدة التالية لجميع الثلاثة."
        },
        "expert": {
          "name": "خبير",
          "desc": "حققت نتيجة في أعلى كل قسم — بناء الجملة الأساسي والدوال والنطاق وهياكل البيانات والأشكال الكائنية التوجه. عملياً، هذا يعني أنه يمكنك تسليمك ملف غريب والتعبير عن لماذا ينتج المخرجات التي ينتجها، وليس فقط ما يجب أن يفعله البناء، وهي المهارة الأصعب والأكثر قيمة. على هذا المستوى، اللغة الخام نادراً ما تكون عامل التحديد في عملك؛ عادة ما يكون الحد الأقصى هو حجم أو شكل النظام حول الكود.",
          "recommendation": "العائدات الآن في الأدوات والمراجعة: التحقق من النوع الثابت مع mypy أو pyright، تحديد الأداء قبل التحسين بدلاً من التخمين، وقراءة pull requests الآخرين لهذا بالذات نوع الخطأ — تلك التي تمر في كل الاختبارات وتفعل الشيء الخاطئ تحت إدخال معين. إذا كنت تخضع لفحص لدور، صِف خطأ مثل هذا الذي وجدته بدلاً من تسمية ميزات اللغة — هذا يوضح التفكير وليس فقط المفردات."
        }
      },
      "questions": [
        {
          "question": "تكتب def add_item(item, basket=[]): basket.append(item); return basket، ثم تستدعي add_item('a') و add_item('b')، كلاهما يترك basket غير محدد. ماذا يعيد الاستدعاء الثاني؟",
          "options": [
            {
              "icon": "",
              "label": "['b'] — كل استدعاء يحصل على قائمة فارغة جديدة بشكل افتراضي"
            },
            {
              "icon": "",
              "label": "TypeError — يجب عليك توفير وسيط basket"
            },
            {
              "icon": "",
              "label": "['a', 'b'] — يتم إنشاء القائمة الافتراضية مرة واحدة وإعادة استخدامها عبر الاستدعاءات"
            },
            {
              "icon": "",
              "label": "['a'] ثم ['b'] كقائمتين مستقلتين بعنصر واحد"
            }
          ]
        },
        {
          "question": "a = [1, 2, 3] و b = [1, 2, 3]. ماذا يعيد a == b، وماذا يعيد a is b؟",
          "options": [
            {
              "icon": "",
              "label": "True لكليهما — القوائم المتطابقة هي دائماً نفس الكائن"
            },
            {
              "icon": "",
              "label": "True بـ ==، False بـ is — محتويات متساوية لكن كائنات مختلفة في الذاكرة"
            },
            {
              "icon": "",
              "label": "False لكليهما — المعاملات المنفصلة لا تكون متساوية أبداً في بايثون"
            },
            {
              "icon": "",
              "label": "True بـ is، False بـ == — is يفحص المساواة بالقيمة للقوائم"
            }
          ]
        },
        {
          "question": "في بايثون 3، ماذا يقيّم 7 / 2، وماذا يقيّم 7 // 2؟",
          "options": [
            {
              "icon": "",
              "label": "3.5، ثم 3 — / يعيد دائماً عدداً عشرياً، // يأخذ الحد الأدنى من النتيجة"
            },
            {
              "icon": "",
              "label": "3، ثم 3.5 — / يقتطع و // يعيد عدداً عشرياً"
            },
            {
              "icon": "",
              "label": "3.5، ثم 3.5 — كلا المعاملين يعيدان عدداً عشرياً في بايثون 3"
            },
            {
              "icon": "",
              "label": "3، ثم 3 — كلا المعاملين يأخذان الحد الأدنى من النتيجة في بايثون 3"
            }
          ]
        },
        {
          "question": "s = 'hello'، ثم تشغل s[0] = 'H'. ماذا يحدث؟",
          "options": [
            {
              "icon": "",
              "label": "s تصبح 'Hello'"
            },
            {
              "icon": "",
              "label": "s تصبح 'Hhello' لأن الحرف يُدرج وليس يُستبدل"
            },
            {
              "icon": "",
              "label": "TypeError — النصوص غير قابلة للتغيير ولا تدعم إسناد العنصر"
            },
            {
              "icon": "",
              "label": "لا شيء — الإسناد يُتجاهل بصمت و s تبقى 'hello'"
            }
          ]
        },
        {
          "question": "x = [10, 20, 30, 40, 50]. ماذا يعيد x[1:4]؟",
          "options": [
            {
              "icon": "",
              "label": "[20, 30, 40, 50]"
            },
            {
              "icon": "",
              "label": "[10, 20, 30, 40]"
            },
            {
              "icon": "",
              "label": "[20, 30, 40]"
            },
            {
              "icon": "",
              "label": "[30, 40]"
            }
          ]
        },
        {
          "question": "name = 'Ana' و age = 30. ماذا ينتج f'{name} is {age}'؟",
          "options": [
            {
              "icon": "",
              "label": "{name} is {age}"
            },
            {
              "icon": "",
              "label": "Ana is 30"
            },
            {
              "icon": "",
              "label": "name is age"
            },
            {
              "icon": "",
              "label": "TypeError، لأن f-strings تتطلب طريقة format()"
            }
          ]
        },
        {
          "question": "ماذا يقيّم 1 < 2 < 3؟",
          "options": [
            {
              "icon": "",
              "label": "True — بايثون يسلسل المقارنات كـ (1 < 2) and (2 < 3)"
            },
            {
              "icon": "",
              "label": "False — المقارنات المسلسلة تُقيّم من اليسار لليمين بدون قطع قصير، مما يعطي 1 < 2 < 3 -> 1 < True -> False"
            },
            {
              "icon": "",
              "label": "SyntaxError — لا يمكن تسلسل المقارنات"
            },
            {
              "icon": "",
              "label": "3 — بايثون يعيد آخر قيمة في السلسلة"
            }
          ]
        },
        {
          "question": "ماذا يعيد bool([])، وماذا يعيد bool([0])؟",
          "options": [
            {
              "icon": "",
              "label": "False، ثم False — أي قائمة تحتوي على قيم falsy فقط تكون falsy"
            },
            {
              "icon": "",
              "label": "False، ثم True — قائمة فارغة تكون falsy، قائمة تحتوي على عنصر واحد (حتى 0) تكون truthy"
            },
            {
              "icon": "",
              "label": "True، ثم True — الكائنات غير None تكون دائماً truthy"
            },
            {
              "icon": "",
              "label": "True، ثم False — القائمة تكون truthy فقط عندما تكون فارغة"
            }
          ]
        },
        {
          "question": "موجود count = 0 على مستوى الوحدة. داخل def increment(): count += 1; return count، تستدعي increment(). ماذا يحدث؟",
          "options": [
            {
              "icon": "",
              "label": "UnboundLocalError — الإسناد لـ count في أي مكان في الدالة يجعلها محلية، لذا count += 1 تحاول قراءة متغير محلي قبل إسناد قيمة له"
            },
            {
              "icon": "",
              "label": "تعيد 1 وتزيد count على مستوى الوحدة إلى 1"
            },
            {
              "icon": "",
              "label": "تعيد 1 لكن تترك count على مستوى الوحدة عند 0"
            },
            {
              "icon": "",
              "label": "ترفع NameError لأن count لم تُعرّف أبداً داخل الدالة"
            }
          ]
        },
        {
          "question": "def f(*args, **kwargs): return args, kwargs. ماذا يعيد f(1, 2, x=3)؟",
          "options": [
            {
              "icon": "",
              "label": "([1, 2], {'x': 3})"
            },
            {
              "icon": "",
              "label": "((1, 2), {'x': 3})"
            },
            {
              "icon": "",
              "label": "(1, 2, {'x': 3})"
            },
            {
              "icon": "",
              "label": "TypeError — الوسائط الموضعية ووسائط الكلمات الدالية لا يمكن مزجها في استدعاء واحد"
            }
          ]
        },
        {
          "question": "تبني funcs = [lambda: i for i in range(3)] في حلقة. ماذا يعيد [f() for f in funcs]؟",
          "options": [
            {
              "icon": "",
              "label": "[2, 2, 2] — كل lambda تبحث عن i عند الاستدعاء، وبحلول ذلك الوقت انتهت الحلقة مع i تساوي 2"
            },
            {
              "icon": "",
              "label": "[0, 1, 2] — كل lambda تلتقط قيمة i في الوقت الذي تم إنشاؤها فيه"
            },
            {
              "icon": "",
              "label": "[0, 0, 0] — lambdas تلتقط دائماً أول قيمة تُسند لمتغير"
            },
            {
              "icon": "",
              "label": "NameError، لأن i لا توجد بعد انتهاء الحلقة"
            }
          ]
        },
        {
          "question": "دالة معرّفة مع @a مباشرة فوق @b، التي تجلس مباشرة فوق def f(): pass. بأي ترتيب يتم تطبيق الديكوريتورز على f؟",
          "options": [
            {
              "icon": "",
              "label": "b تغلف f أولاً، ثم a تغلف نتيجة b — الديكوريتور الأقرب للدالة يعمل أولاً"
            },
            {
              "icon": "",
              "label": "a تغلف f أولاً، ثم b تغلف النتيجة — الديكوريتورز تُطبق من الأعلى للأسفل"
            },
            {
              "icon": "",
              "label": "كلا الديكوريتورز تغلفان f بشكل مستقل وفقط الآخر المعرّف له تأثير"
            },
            {
              "icon": "",
              "label": "يعتمد على ترتيب استيراد الديكوريتورز، وليس موقعهم في الكود"
            }
          ]
        },
        {
          "question": "def f(a, *, b): return a + b. أي من هذه الاستدعاءات يعمل؟",
          "options": [
            {
              "icon": "",
              "label": "f(1, b=2) — b يجب أن تُمرر بالكلمة الدالية لأنها تأتي بعد * الفارغة في التوقيع"
            },
            {
              "icon": "",
              "label": "f(1, 2) — الوسائط الموضعية تملأ الوسائط من اليسار لليمين بغض النظر عن *"
            },
            {
              "icon": "",
              "label": "f(a=1, 2) — وسائط الكلمات الدالية يجب أن تأتي أولاً"
            },
            {
              "icon": "",
              "label": "f(1) — b اختيارية لأنها تتبع *"
            }
          ]
        },
        {
          "question": "دالة المولد تُرجع yield 1، ثم yields 2، ثم تفعل return 99. ماذا يحتوي list(the_generator())، وماذا يحدث للـ 99؟",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 99] — return داخل المولد يتصرف مثل yield واحد أكثر"
            },
            {
              "icon": "",
              "label": "[99] — return يتجاوز على الفور أي قيم تم استدعاؤها بالفعل"
            },
            {
              "icon": "",
              "label": "[1, 2] — قيمة عودة المولد تصبح القيمة المرفقة بـ StopIteration الذي يرفعه، لا تُستدعى"
            },
            {
              "icon": "",
              "label": "RuntimeError، لأن المولدات لا يمكن أن تحتوي على جملة return"
            }
          ]
        },
        {
          "question": "في دالة outer()، x = 1 مضبوطة، ثم nested inner() تفعل nonlocal x; x += 1، و outer() تستدعي inner() قبل إعادة x. ماذا تعيد outer()؟",
          "options": [
            {
              "icon": "",
              "label": "1 — inner() تعمل على نسختها المحلية الخاصة من x، لذا التغيير لا يستمر"
            },
            {
              "icon": "",
              "label": "UnboundLocalError، لأن x لم تُعرّف داخل inner() قبل جملة nonlocal"
            },
            {
              "icon": "",
              "label": "SyntaxError — nonlocal يمكن استخدامه فقط داخل الفئات"
            },
            {
              "icon": "",
              "label": "2 — nonlocal تدع inner() تعدّل x للدالة الخارجية بدلاً من إنشاء متغير محلي جديد"
            }
          ]
        },
        {
          "question": "d = {'a': 1, 'b': 2}. ماذا يعيد d.get('c', 0)، وهل يضيف 'c' إلى القاموس؟",
          "options": [
            {
              "icon": "",
              "label": "0، ولا — get() يعيد الافتراضي بدون إدراج المفتاح"
            },
            {
              "icon": "",
              "label": "0، نعم — get() يُدرج المفتاح مع القيمة الافتراضية"
            },
            {
              "icon": "",
              "label": "KeyError، لأن 'c' لا توجد"
            },
            {
              "icon": "",
              "label": "None، نعم — get() يضيف دائماً المفاتيح المفقودة بقيمة None"
            }
          ]
        },
        {
          "question": "t = (1, 2, [3, 4]). هل يمكنك تشغيل t[2].append(5)، وهل يمكنك تشغيل t[0] = 10؟",
          "options": [
            {
              "icon": "",
              "label": "كلاهما يعمل — إدراج قائمة داخل tuple يجعل tuple كله قابلاً للتغيير"
            },
            {
              "icon": "",
              "label": "كلاهما يرفع TypeError — لا شيء داخل tuple يمكن تغييره أبداً"
            },
            {
              "icon": "",
              "label": "t[2].append(5) يرفع TypeError، لكن t[0] = 10 يعمل لأن tuples تسمح بإعادة إسناد عنصرها الأول"
            },
            {
              "icon": "",
              "label": "t[2].append(5) يعمل لأن القائمة بداخلها قابلة للتغيير؛ t[0] = 10 يرفع TypeError لأن tuple نفسها غير قابلة للتغيير"
            }
          ]
        },
        {
          "question": "أي من هذه يعيد مكرراً يحسب القيم بكسل (بكسل بكسل) بدلاً من بناء التسلسل الكامل في الذاكرة مرة واحدة: [x*x for x in range(1000000)] أم (x*x for x in range(1000000))؟",
          "options": [
            {
              "icon": "",
              "label": "الذي بأقواس، (x*x for x in range(1000000)) — ذلك تعبير مولد"
            },
            {
              "icon": "",
              "label": "الذي بأقواس مربعة — list comprehensions دائماً كسل في بايثون 3"
            },
            {
              "icon": "",
              "label": "كلاهما كسل — الفرق الوحيد هو النوع المعاد في النهاية"
            },
            {
              "icon": "",
              "label": "لا أحد — كلاهما يبني التسلسل الكامل في الذاكرة على الفور"
            }
          ]
        },
        {
          "question": "كتلة try تقسم على صفر، وجملة except ZeroDivisionError تطبع 'a'، وجملة finally تطبع 'b'. ماذا يطبع، وبأي ترتيب؟",
          "options": [
            {
              "icon": "",
              "label": "b ثم a — finally تعمل دائماً قبل أي جملة except"
            },
            {
              "icon": "",
              "label": "a ثم b — جملة except المطابقة تعمل أولاً، و finally تعمل دائماً بعد ذلك بغض النظر"
            },
            {
              "icon": "",
              "label": "فقط b — الاستثناء لم يتم التقاطه فعلاً، لذا 'a' لا تطبع أبداً"
            },
            {
              "icon": "",
              "label": "فقط a — finally تُتجاوز مرة يتم التعامل مع الاستثناء بالفعل"
            }
          ]
        },
        {
          "question": "import copy; a = [[1, 2], [3, 4]]; b = copy.copy(a); b[0].append(99). هل يتغير a[0] أيضاً؟",
          "options": [
            {
              "icon": "",
              "label": "لا — copy.copy() يكرر دائماً الكائنات المتداخلة أيضاً"
            },
            {
              "icon": "",
              "label": "لا — إضافة للعنصر b[0] تنشئ قائمة جديدة تماماً لـ b[0] فقط"
            },
            {
              "icon": "",
              "label": "نعم، لكن فقط لأن copy.copy() تم استدعاؤها بدون عامل deepcopy"
            },
            {
              "icon": "",
              "label": "نعم — copy.copy() تنسخ سطحياً، لذا القوائم المتداخلة لا تزال مشتركة بين a و b"
            }
          ]
        },
        {
          "question": "d = {'x': 1, 'y': 2}. ماذا يفحص 'x' in d — المفاتيح، أم القيم، أم كليهما؟",
          "options": [
            {
              "icon": "",
              "label": "القيم — `in` يفحص ما إذا كان 1 أو 2 تساوي 'x'"
            },
            {
              "icon": "",
              "label": "يتم فحص كل المفاتيح والقيم"
            },
            {
              "icon": "",
              "label": "لا أحد — `in` في dict يرفع دائماً TypeError"
            },
            {
              "icon": "",
              "label": "المفاتيح — `in` في قاموس يختبر الانتماء بين مفاتيحه، وليس قيمه"
            }
          ]
        },
        {
          "question": "names = ['Al', 'Bo'] و scores = [10, 20]. ماذا يعيد list(zip(names, scores))؟",
          "options": [
            {
              "icon": "",
              "label": "[('Al', 'Bo'), (10, 20)]"
            },
            {
              "icon": "",
              "label": "['Al', 10, 'Bo', 20]"
            },
            {
              "icon": "",
              "label": "[('Al', 10), ('Bo', 20)]"
            },
            {
              "icon": "",
              "label": "ValueError، لأن zip تتطلب ثلاث وسائط أو أكثر"
            }
          ]
        },
        {
          "question": "class Dog: tricks = [] تحتوي على قائمة على مستوى الفئة، و add_trick تضيف إلى self.tricks. d1 = Dog() و d2 = Dog() تم إنشاؤهما، ثم d1.add_trick('sit') يعمل. ماذا يحتوي d2.tricks؟",
          "options": [
            {
              "icon": "",
              "label": "[] — كل مثيل يحصل على نسختها المستقلة الخاصة من tricks"
            },
            {
              "icon": "",
              "label": "['sit'] — tricks قائمة على مستوى الفئة مشتركة من قبل كل مثيل، لذا تغيير d1 مرئي على d2 أيضاً"
            },
            {
              "icon": "",
              "label": "TypeError — المثيلات لا يمكنها إضافة إلى سمة فئة"
            },
            {
              "icon": "",
              "label": "['sit'] فقط بعد إعادة تشغيل d2 = Dog()"
            }
          ]
        },
        {
          "question": "class A لديها def greet(self): return 'A'. class B(A) لديها def greet(self): return 'B' + super().greet(). ماذا يعيد B().greet()؟",
          "options": [
            {
              "icon": "",
              "label": "'AB' — super() تعمل دائماً قبل الكود الخاص بالفئة الفرعية"
            },
            {
              "icon": "",
              "label": "'B' — super().greet() يُتجاهل لأن B بالفعل تستبدل greet"
            },
            {
              "icon": "",
              "label": "'BA' — super().greet() تستدعي طريقة A ونتيجتها تُضاف إلى 'B'"
            },
            {
              "icon": "",
              "label": "AttributeError، لأن A لا لديها greet مرئية لـ B"
            }
          ]
        },
        {
          "question": "class Point تخزن self.x في __init__ وتُعرّف بدون طرق أخرى. p1 = Point(1) و p2 = Point(1). ماذا يعيد p1 == p2 بشكل افتراضي؟",
          "options": [
            {
              "icon": "",
              "label": "True — بايثون تقارن جميع السمات المطابقة بشكل افتراضي"
            },
            {
              "icon": "",
              "label": "False — بدون __eq__ مخصص، == يعود إلى مقارنة الهوية، و p1 و p2 كائنات مختلفة"
            },
            {
              "icon": "",
              "label": "True، لكن فقط لأن كلا الكائنين تم إنشاؤهما بنفس الوسيط"
            },
            {
              "icon": "",
              "label": "TypeError، لأن Point لا تعرّف __eq__"
            }
          ]
        },
        {
          "question": "أي جملة except أدناه ستلتقط أيضاً ZeroDivisionError: except ArithmeticError، أم except ValueError، أم except KeyError؟",
          "options": [
            {
              "icon": "",
              "label": "except ValueError — أخطاء القسمة تُعتبر قيم غير صالحة"
            },
            {
              "icon": "",
              "label": "except KeyError — أي خطأ وقت تشغيل غير مرتبط بنوع معين يعود لـ KeyError"
            },
            {
              "icon": "",
              "label": "لا أحد منهم — فقط except ZeroDivisionError نفسه يمكنه التقاطه"
            },
            {
              "icon": "",
              "label": "except ArithmeticError — ZeroDivisionError هي فئة فرعية من ArithmeticError"
            }
          ]
        },
        {
          "question": "تفتح ملف مع open('data.txt') as f: واستثناء يُرفع أثناء القراءة داخل الكتلة. هل الملف لا يزال يُغلق؟",
          "options": [
            {
              "icon": "",
              "label": "لا — الملف يبقى مفتوحاً لأن الكتلة لم تنته بشكل طبيعي"
            },
            {
              "icon": "",
              "label": "فقط إذا أضفت أيضاً جملة finally حول جملة with"
            },
            {
              "icon": "",
              "label": "نعم — جملة with تستدعي طريقة __exit__ الملف، التي تغلقه، حتى لو حدث استثناء داخل الكتلة"
            },
            {
              "icon": "",
              "label": "يعتمد على نوع الاستثناء — فقط الاستثناءات التي يتم التقاطها في مكان آخر تؤدي للتنظيف"
            }
          ]
        },
        {
          "question": "x = [3, 1, 2] و y = x.sort(). ماذا يحتوي y؟",
          "options": [
            {
              "icon": "",
              "label": "[1, 2, 3] — sort() تعيد القائمة المُرتبة حديثاً"
            },
            {
              "icon": "",
              "label": "None — list.sort() تُرتب في الموقع وتعيد None؛ x نفسها تصبح [1, 2, 3]"
            },
            {
              "icon": "",
              "label": "[3, 1, 2] — sort() تعيد القائمة غير المُرتبة الأصلية وفقط تغيير ترتيب x الداخلي"
            },
            {
              "icon": "",
              "label": "TypeError، لأن sort() لا يمكن إسنادها لمتغير"
            }
          ]
        },
        {
          "question": "ماذا يحدث عندما تشغل 'Score: ' + 42؟",
          "options": [
            {
              "icon": "",
              "label": "'Score: 42' — بايثون تحول الرقم تلقائياً داخل تعبير +"
            },
            {
              "icon": "",
              "label": "'Score: ' — الرقم يُتجاهل صامتاً"
            },
            {
              "icon": "",
              "label": "42 — النص يُكره لرقم ويُضاف"
            },
            {
              "icon": "",
              "label": "TypeError — لا يمكنك دمج str و int مباشرة، 42 يجب أن يُحول مع str() أولاً"
            }
          ]
        },
        {
          "question": "تحتاج للتحقق ما إذا كانت قائمة تسمى results فارغة. أي هي الطريقة الحقيقية لبايثون: if results == []، أم if len(results) == 0، أم if not results؟",
          "options": [
            {
              "icon": "",
              "label": "if results == []: — هذه الطريقة الوحيدة الموثوقة للكشف عن قائمة فارغة"
            },
            {
              "icon": "",
              "label": "if len(results) == 0: — هذا مطلوب لأن القوائم الفارغة تكون truthy في بايثون"
            },
            {
              "icon": "",
              "label": "جميع الثلاثة لا تُستخدم أبداً عملياً؛ النهج القياسي هو if results is None:"
            },
            {
              "icon": "",
              "label": "if not results: — حقيقة بايثون تعتمد على الحقيقية، وقائمة فارغة هي falsy"
            }
          ]
        }
      ],
      "optionOrderVersion": "92945565db6c55da"
    }
  }
}
