{ "cells": [ { "cell_type": "raw", "metadata": { "vscode": { "languageId": "raw" } }, "source": [ "---\n", "title: \"توالي الأوامر\"\n", "og:title: control_flow\n", "toc: true\n", "format:\n", " html: default\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[تحميل الدفتر](https://raw.githubusercontent.com/HassanAlgoz/python/main/book/chapters/ch2-control-flow/lesson_2.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "يُرى **التدفق** (Flow) المستمر في النظام الميكانيكي للسيارة ليبقيها سائرة بفعل الوقود. كما يُرى في حركة الطاحونة المائية حيث يدفعها جريان النهر فيحركها معه. ويُرى أيضًا في شراع السفينة حيث تضرب فيه الرياح.\n", "والكهرباء مثلها تيار يسري في أنبوبة المصباح ليبقيه منيرًا، أو في نظام التكييف ليبقي الجو باردًا.\n", "\n", "وأصل **المنطق الرقمي** (Digital Logic) تيارات كهربائية لها تردد ينبض بسرعة فائقة لما تلتقطه عين الإنسان. فإذا نظرت للإشارة علمت أننا تحكمنا في سرعة هذا التردد بحيث تصبح ألوان الإشارة تتبدل وتنطفئ وتُشعَل بتوقيتٍ مضبوط. لكنها مع ذلك ليسَت خوارزميَّة. لأنها أشبَهُ بالكُرة التي تُدفعُ من أعلى مُنحَدَرٍ فتتدحرجُ بفعل الجاذبية. إذْ تعملُ الإشارة بوتيرة معلومة وتدور وتدور مادامت الكهرباء تنبض فيها.\n", "\n", "ولا يكاد يخلو برنامج مفيد من اتخاذ قرارات مغايرة بناءً على اختلاف الظروف المكانية والزمانية والواقعية. فلو كان نظام التحكُّم في التقاطُع المروري يراعي حركة السيْر بحيث يُقدِّم ويؤخِّر في توقيت فتح إشاراته لتحقيق أعلى كم من العبور للسيارات؛ فإننا نسميها إشارة ذكيَّة (Smart). وهذه خوارزمية.\n", "\n", "ومن أمثلة ذلك:\n", "\n", "- مراعاة المكان: جعل السيارة الآلية تتقيَّد بالسرعة القانونية للشارع الذي هي فيه\n", "- مراعاة الزمان: توقيت إيقاف المكيِّف حتى تستيقظ في الصباح الباكر\n", "- مراعاة الواقع: إضاءة المصباح عند استشعار حساس الحركة بدخول شخصٍ إلى الغرفة\n", "\n", "ويتم ذلك **بأوامر التحكم في سير الأوامر** (Control-flow) وهي جُمَل شرطيَّة ينبني عليها اختيار الأمر التالي. فإن الأوامِر في المنطق الرقمي تنتظم في ثلاثة صوَر:\n", "\n", "1. **تتابع** (Sequence): وهو الأصل؛ حيث يكون الانتقال من الأمر إلى الأمر الذي يليه مباشرة\n", "2. **اختيار** (Selection): حيث يكون الانتقال مشروطًا (لاحظ في الصورة أن تنفيذ `A` مشروط)\n", "3. **تكرار** (Iteration): وهو نوعٌ من الاختيار، يكون فيه الانتقال إلى الوراء؛ ويتم لنا بذلك الإعادة\n", "\n", "![أنماط توالي الأوامر](assets/control-flow.png){width=\"100%\"}\n", "\n", "وإذا استُعمِلَت هذه لتحقيق غاية محددة بعدد محدود من الخطوات، صار اسمها **خوارزمية** (Algorithm).\n", "\n", "فإن جملة التعيين التالية تكتُب قيمة `20` في نفس المحلّ الذي كتبت عليه جملة التعيين الأولى `10`. لذا ظهرت النتيجة: `20`.\n", "\n", ":::: {.columns}\n", "::: {.column width=\"35%\"}\n", "\n", "```{mermaid}\n", "flowchart TD\n", " A[x = 10] --> B[x = 20] --> C[\"print(x)\"]\n", "```\n", ":::\n", "::: {.column width=\"65%\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 10\n", "x = 20\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ":::\n", "::::\n", "\n", "## القيمة المنطقية\n", "\n", "ويتم اختيار أحد طريقين في سيْر الأوامِر بحسب ناتج تعبير منطقي (`bool`)؛ وهي أحد اثنين:\n", "\n", "1. **نعم**: `True`؛ ويقال أيضًا: صحيح أو مطابق أو ثابت\n", "2. **لا**: `False`؛ ويقال أيضًا خاطئ أو مخالف أو منتفي\n", "\n", "ومن العبارات المنطقية في بايثون، حاصل عوامل المقارنة كما في المثال:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 10\n", "b = 5\n", "\n", "print(a == b) # يساوي\n", "print(a != b) # لا يساوي\n", "print(a > b) # أكبر من\n", "print(a < b) # أصغر من \n", "print(a >= b) # أكبر من أو يساوي\n", "print(a <= b) # أصغر من أو يساوي" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "تذكر: أن **لكل قيمة نوعًا**.\n", "فإذا وضعت المتغير في دالة `type(x)` لمعرفة النوع، فإنك ستعرف أن مثل هذه التعبيرات نوعها منطقي (`bool`).\n", "مثال:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(type(8 == 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ويمكن المقارنة بين النصوص كذلك، ونتيجة ذلك قيمة من النوع المنطقي أيضًا؛ لأن المقارنة تعبير منطقي:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Hello\" == \"Hello\") # يجب أن تتطابق جميع الحروف\n", "print(\"a\" == \"A\") # حالة الحرف مهمة" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ولاحظ أن النص والعدد -لاختلاف نوعيهما- يكون حاصل المساواة بينهما **لا** (`False`):" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(10 == \"10\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "لكن بايثون تتجوَّز في المساواة بين الأنواع المختلفة التي من صنف العدد،\n", "فالمطابقة بين العدد الصحيح (`int`) وذي الفاصلة العائمة (`float`) جائزة في بايثون:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(10 == 10.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## التخيير\n", "\n", "يتم التخيير المذكور آنفًا بالجملة الشرطية:\n", "\n", "```python\n", "if :\n", " \n", "```\n", "\n", "- فتبدأ الجملة الشرطية بكلمة `if` (**إذا**) ويليها التعبير المنطقي (كما سبق بيانه)\n", "\t- فيكون ما يندرج تحتها (بالمسافة) الأوامر المتعلقة بنفاذ الشرط (`True`).\n", " فإن انتفى الشرط (`False`) فإن بايثون تتخطى هذه الأوامر وتقفز لما بعدها.\n", "\n", "وبالمثال يتضح المقال:\n", "\n", ":::: {.columns}\n", "::: {.column width=\"35%\"}\n", "```{mermaid}\n", "flowchart TD\n", " IF{{if cond}} -- False --> X[\"Outside\"]\n", " IF -- True --> Y[\"Inside\"] --> X[\"Outside\"]\n", "\n", " style IF fill:#82aeff, stroke:#333, stroke-width:2px;\n", " linkStyle 0 color:red;\n", "```\n", "\n", ":::\n", "::: {.column width=\"65%\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "cond = False\n", "if cond:\n", " print('Inside')\n", "print('Outside')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ":::\n", "::::\n", "\n", "لاحظ أن الشرط منتفٍ، لذلك كان حاصل النص السابق تخطي ما بداخل الجملة الشرطية، وطباعة `Outside` فقط.\n", "\n", "### تنبيه: محاذاة المسافات\n", "\n", "لاحظ أن **المسافة البادئة** (Indentation) (أي: المسافات من بداية السطر حتى يُدرج الكلام أسفل كلمة `if`) في القطعة البرمجية أعلاه ليست لمجرد تسهيل القراءة، بل تُفسَّرُ الجُملةُ أنها في الداخل أو الخارج بناءً على وجودها وعدمها. فهي التي تضع الحدود حول المشروط. ويجب أن تكون محاذية فإذا كان مقدارها 4 مسافات أو 2 أو أكثر، فوجب أن تكون جميع الجُمَل بنفس المقدار. وهذا ما نسميه المحاذاة.\n", "\n", "لاحظ: أن خلو الشرط من جُمَل مشروطة به يُفرِز تنبيهًا للمبرمج عند تفسير النص البرمجي:\n", "\n", ":::: {.columns}\n", "::: {.column width=\"35%\"}\n", "\n", "```{mermaid}\n", "flowchart TD\n", " IF{{if True}}\n", " Y[\"Inside\"] --> X[\"Outside\"]\n", " style IF fill:#fc0000, stroke:#333, stroke-width:2px;\n", "```\n", "\n", ":::\n", "::: {.column width=\"65%\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#| error: true\n", "#| \n", "if True:\n", "print('Inside')\n", "print('Outside')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ":::\n", "::::\n", "\n", "\n", "إذا قمت بزيادة المحاذاة لكل من جملتي `print()`، فسوف يعمل النص البرمجي بتدفِّقٍ غيرِ الذي قصدناه ابتداءً. أي أنه سيطبع `Outside` عندما يكون في الواقع داخل اللَّبِنَة الشرطية.\n", "\n", ":::: {.columns}\n", "::: {.column width=\"35%\"}\n", "\n", "```{mermaid}\n", "flowchart TD\n", " IF{{if True}}\n", " IF -- True --> Y[\"Inside\"] --> X[\"Outside\"]\n", " \n", " style IF fill:#82aeff, stroke:#333, stroke-width:2px;\n", "```\n", "\n", ":::\n", "::: {.column width=\"65%\"}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if True:\n", " print('Inside')\n", " print('Outside')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ":::\n", "::::\n", "\n", "يؤدي النص البرمجي السابق إلى **خطأ منطقي** (لا نحوي) لن يظهر أبدًا كخطأ ولن يوقف البرنامج!\n", "\n", "::: {.callout-note}\n", "لا تنسَ أن المحاذاة في بايثون هي أساسية لتفسير النص البرمجي.\n", ":::\n", "\n", "### التخيير الحصري\n", "\n", "لجعل التخيير بين أمرين بحيث لو حصل أحدهما لا يحصل الآخر، فإننا نتبع الشرط الأوَّل بكلمة **وإلا** (`else`)،\n", "على النحو التالي:\n", "\n", "```python\n", "if :\n", " \n", "else:\n", " \n", "```\n", "\n", "مثلاً، تريد أن تظهر رسالة خطأ لو لم تطابق كلمة المرور:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "input_password = hash(\"abc123\")\n", "stored_password = hash(\"fuda$(#*(lm\")\n", "\n", "is_match = input_password == stored_password\n", "\n", "if is_match:\n", " msg = \"Welcome\"\n", "else:\n", " msg = \"Try Again\"\n", "\n", "print(msg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "وهذه الشجرة توضح تسلسل التنفيذ الإجرائي لها:\n", "\n", "```{mermaid}\n", "flowchart TD\n", " IF{{if is_match}}\n", " IF -- False --> D[\"msg = 'Try Again'\"]\n", " IF -- True --> C[\"msg = 'Welcome'\"]\n", " D --> E[\"print(msg)\"]\n", " C --> E[\"print(msg)\"]\n", "\n", " style IF fill:#82aeff, stroke:#333;\n", " linkStyle 0 color:red;\n", "```\n", "\n", "\n", "ولاحظ أن `print(msg)` غير مشروطة، لذلك فإنها مع نفوذ الشرط أو عدمه يتم تنفيذها.\n", "\n", "## الجبر المنطقي\n", "\n", "والنوع الثنائي (`bool`) الذي ينحصر في قيمتين فقط هو أصل المنطق الرقمي المعروف بالأصفار والآحاد.\n", "حيث نشأ علم **الجبر المنطقي** (Algebraic Logic) من قبل عالم الرياضيات [جورج بول](https://ar.wikipedia.org/wiki/%D8%AC%D9%88%D8%B1%D8%AC_%D8%A8%D9%88%D9%84) الذي وضع أسسه في كتابه: \"قوانين الفكر\" ([The Laws of Thought](https://en.wikipedia.org/wiki/The_Laws_of_Thought)) في عام 1854.\n", "\n", "\n", "::: {.callout-note}\n", "ومن بديع صنع الله سبحانه وتعالى، أن هذه العمليات الثلاثة بها تتكون جميع المعالجات التي تصير في كل جهاز حاسب بلا استثناء!\n", ":::\n", "\n", "\n", "وإذا كان جبر الأعداد يكون بالمعادلات التي هي مقابلات تمثل قيَم عددية،\n", "وبينها عوامل الجمع والضرب والقسمة والطرح والأس ونحو ذلك؛\n", "فإن الجبر المنطقي يكون بمعادلات تمثل مقابلات لقيم منطقية (صفر أو واحد)،\n", "بينها العوامل الأساسية الثلاثة التالية (ويمثل الصفر المنطقي بكلمة `False` والواحد المنطقي بكلمة `True`):\n", "\n", "العامل الأول: **العكس** (`not`). مثاله:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 10 > 5 # تعيين لحاصل تعبير منطقي للمتغير\n", "b = not a # عكس القيمة المنطقية التي في المتغير الأول\n", "print(b) # طباعة" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "العامل الثاني: **الجمع** (`and`). مثاله:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = True\n", "b = False\n", "print(a and b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "العامل الثالث: **الخيار** (`or`). مثاله:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = True\n", "b = False\n", "print(a or b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "وقد وضعت الجمع والخيار في جدولٍ واحد فيه جميع الاحتمالات بينهما ليسهل استيعابه:\n", "\n", "\n", "
\n", "\n", "\n", "| `a` | `b` | `a and b` | `a or b` |\n", "|----------|----------|----------|----------|\n", "| 0 | 0 | 0 | 0 |\n", "| 0 | 1 | 0 | 1 |\n", "| 1 | 0 | 0 | 1 |\n", "| 1 | 1 | 1 | 1 |\n", "\n", "
\n", "\n", "### مآل العبارات المنطقية في الجملة الشرطية\n", "\n", "على سبيل المثال:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "age = 20\n", "weight = 50\n", "\n", "if age > 18 and weight > 45:\n", " print(\"You are eligible to donate blood\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "يؤول طرفا العامل `and` لقيمة منطقية هكذا:\n", "\n", "- `age > 18` تؤول إلى `True` لأن `age=20` وهو أكبر من `18`\n", "- `weight > 45` تؤول إلى `True` لأن `weight=50` وهو أكبر من `45`\n", "- فتكون الجملة إذًا: `True and True` وهي تؤول إلى `True`\n", "\n", "وهذه الشجرة تمثل تسلسل تفسير العبارات المنطقية في الجملة الشرطية، لتؤول إلى نعم أو لا (`True` أو `False`):\n", "\n", "
\n", "\n", "```{mermaid}\n", "graph BT\n", " RESULT((if))\n", " ROOT{and} -- True --> RESULT\n", " middle_left{\">\"} -- True --> ROOT\n", " middle_right{\">\"} -- True --> ROOT\n", " left_left[age] -- \"20\" --> middle_left\n", " left_right[18] -- \"18\" --> middle_left\n", " right_left[weight] -- \"50\" --> middle_right\n", " right_right[45] -- \"45\" --> middle_right\n", "\n", "```\n", "\n", "
\n", "\n", "تستعمل الأقواس (`()`) لتجميع الشروط لإيقاع الترتيب المنطقي المراد:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "age = 16\n", "temperature = 15\n", "is_wearing_coat = True\n", "\n", "if age < 16 or (temperature < 20 and not is_wearing_coat):\n", " print(\"I suggest you don't go outside\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- `age < 16` تؤول إلى `False` لأن `age=16` ليست أصغر من `16`\n", "- `temperature < 20` تؤول إلى `True` لأن `temperature=15` أصغر من `20` فعلاً\n", "- `not is_wearing_coat` تؤول إلى `False` لأن `is_wearing_coat=True` وهي عكسها\n", "- إذًا الجملة بين القوسين `(temperature < 20 and not is_wearing_coat)` تؤول إلى `True and False` وهي تؤول إلى `False`\n", "- إذًا الجملة `age < 16 or (False)` تؤول إلى `False or False` وهي تؤول إلى `False`\n", "\n", "وهذه الشجرة تمثل تسلسل تفسير العبارات المنطقية في الجملة الشرطية:\n", "\n", "
\n", "\n", "```{mermaid}\n", "graph BT\n", " RESULT((if))\n", " ROOT{or} -- False --> RESULT\n", " middle_left{\"<\"} -- False --> ROOT\n", " middle_right{and} -- False --> ROOT\n", " left_left[age] -- \"16\" --> middle_left\n", " left_right[16] -- \"16\" --> middle_left\n", " right_middle{\"<\"} -- True --> middle_right\n", " right_not{not} -- False --> middle_right\n", " right_temp[temperature] -- \"15\" --> right_middle\n", " right_val[20] -- \"20\" --> right_middle\n", " right_coat[is_wearing_coat] -- True --> right_not\n", "```\n", "\n", "
\n", "\n", "### تسمية العبارات المنطقية\n", "\n", "ويجوز تسمية العباراة المنطقية وتعيين قيمتها لمتغيرات لبيان موقعها في سياق الجملة الشرطية:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "is_minor = age < 16\n", "is_cold = temperature < 20\n", "\n", "if is_minor or (is_cold and not is_wearing_coat):\n", " print(\"I suggest you don't go outside\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ومن فوائد تعيين العبارة المنطقية لمتغير: إمكانية استعماله في أكثر من موضع.\n", "\n", "### تسلسل المقارنات\n", "\n", "وتفهم بايثون المقارنات المتسلسلة. فعبارة `x < y <= z` تكافئ `x < y and y <= z`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "low = 10\n", "high = 20\n", "x = 15\n", "\n", "(low < x < high) == (low < x and x < high)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## الجملة الشرطية المتكاملة\n", "\n", "الصيغة المتكاملة للجملة الشرطية:\n", "\n", "```python\n", "if :\n", " \n", "elif :\n", " \n", "elif :\n", " \n", "else:\n", " \n", "```\n", "\n", "- أما جملة **إذا** (`if`) فقد سبق بيانها\n", "- وأما جملة **وإلا فإن** (`elif`) فلا يتم تنفيذها إلا عند تخلُّف الشرط السابق لها. وقد تتعدد (كما في المثال)\n", "- وأما جملة **وإلا** الأخيرة (`else`) فلا يتم تنفيذها إلا عند تخلف جميع الشروط السابقة لها.\n", "\n", "ونؤكد أن الجمل الشرطية اللاحقة بعد **إذا** (`if`) الأولى؛ كل واحدة منها مرتبطة بانتفاء ما قبلها.\n", "وهذا ما يوضحه الرسم الشجري التالي:\n", "\n", "```{mermaid}\n", "flowchart TD\n", " IF1{{if}}\n", " IF1 -- False --> ELIF1{{elif}}\n", " IF1 -- True --> code_1\n", " ELIF1 -- False --> ELIF2{{elif}}\n", " ELIF1 -- True --> code_2\n", " ELIF2 -- False --> ELSE{{else}}\n", " ELIF2 -- True --> code_3\n", " ELSE --> code_4\n", "\n", " style IF1 fill:#82aeff, stroke:#333, stroke-width:2px;\n", " style ELIF1 fill:#82aeff, stroke:#333, stroke-width:2px;\n", " style ELIF2 fill:#82aeff, stroke:#333, stroke-width:2px;\n", " style ELSE fill:#82aeff, stroke:#333, stroke-width:2px;\n", " linkStyle 0,2,4 color:red;\n", "```\n", "\n", "#### جرب\n", "\n", "استكشف المنطق التالي بتغيير قيمة `x` كل مرة للتبع ما يحصل في كل مرة:\n", "\n", "- `x = -5`\n", "- `x = 0`\n", "- `x = 1`\n", "- `x = 5`" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set to zero\n", "Always: 0\n" ] } ], "source": [ "x = -5\n", "\n", "if x < 0:\n", " x = 0\n", " print('Set to zero')\n", "elif x == 0:\n", " print('Zero')\n", "elif x == 1:\n", " print('Single')\n", "else:\n", " print('More')\n", "\n", "print(\"Always:\", x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "وهذه الشجرة توضح تسلسل التنفيذ الإجرائي لها:\n", "\n", "```{mermaid}\n", "flowchart TD\n", " IF{{if x < 0}}\n", " IF -- False --> ELIF{{elif x == 0}}\n", " IF -- True --> S1[x = 0] --> S2[\"Set to zero\"]\n", " ELIF -- False --> ELSE{{else}}\n", " ELIF -- True --> S3[x = 1] --> S4[\"Single\"]\n", " ELSE --> S5[\"More\"]\n", "\n", " Always[Always: x]\n", " S2 --> Always\n", " S4 --> Always\n", " S5 --> Always\n", "\n", " style IF fill:#82aeff, stroke:#333, stroke-width:2px;\n", " style ELIF fill:#82aeff, stroke:#333, stroke-width:2px;\n", " style ELSE fill:#82aeff, stroke:#333, stroke-width:2px;\n", " linkStyle 0,3 color:red;\n", "```\n", "\n", "\n", "وهذا تصوير لسير الإجراءات لنفس النص البرمجي. ملاحظة: اضغط على الزر `Prev` أو `Next` للتنقل بين خطوات التنفيذ الإجراءية:\n", "\n", "\n", "\n", "لاحظ أن العبارة الأخيرة خارج كل اللَّبِنات الشرطية لذا يتم تنفيذها دائمًا.\n", "\n", "للمزيد تابع [الجملة الشرطية المتكاملة](#الجملة-الشرطية-المتكاملة)." ] } ], "metadata": { "kernelspec": { "display_name": "pythonia (3.12.8)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.8" } }, "nbformat": 4, "nbformat_minor": 4 }