{"id":"l-pda-1-4","courseId":"python-data-analysis","lang":"ar","kind":"lesson","summary":"عالج كل صف في مجموعة بيانات باستخدام حلقات for، واتخذ القرارات بـ if و elif و else، واحسب العدد بالقواميس، واكتب المنطق نفسه بإيجاز على هيئة comprehensions.","html":"<p>لديك ستة صفوف من ملف Cartwheel الفوضوي في قائمة من القواميس. تريد قيمتها الإجمالية، وكم جاء من كل قناة بيع، وأيّ الطلبات كانت كبيرة. كتابة سطر لكل صف تنجح مع ستة صفوف وتنهار مع ستة آلاف. حلقة التكرار (loop) تكتب المنطق مرة واحدة، وتكرّره Python لكل صف.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">حلقة for</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"0\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2574</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">65.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2069</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">18.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1200</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">33.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1809</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">35.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"web\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1434</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">72.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">None</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2089</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">58.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"marketplace\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">grand_total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> order </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    grand_total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> order[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(grand_total)</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>اقرأها هكذا: “لكل طلب في orders، شغّل الأسطر المُزاحة”. في كل دورة يشير الاسم <code dir=\"ltr\">order</code> إلى القاموس التالي. والسطر <code dir=\"ltr\">grand_total += order[&quot;total&quot;]</code> اختصار لـ <code dir=\"ltr\">grand_total = grand_total + order[&quot;total&quot;]</code>.</p>\n<p>الإزاحة (indentation) في Python ليست زينة: الأسطر المُزاحة (أربع مسافات بحسب العُرف) هي جسم الحلقة، وأول سطر يعود إلى الهامش الأيسر يعمل بعد انتهاء الحلقة. لهذا تقع <code dir=\"ltr\">print</code> خارجها: أنت تريد نتيجة واحدة، لا ستًا.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>تصفير المتغيّر التراكمي داخل الحلقة</span></p>\n<p>إذا انتقل <code dir=\"ltr\">grand_total = 0</code> إلى داخل الحلقة، فسيُمسح في كل دورة ولن تحصل إلا على مجموع الطلب الأخير. لا خطأ يظهر، لكن الإجابة خاطئة. المتغيّرات التراكمية (accumulators)، من مجاميع وعدّادات وقوائم فارغة ستضيف إليها، تُنشأ دائمًا <strong>قبل</strong> الحلقة.</p>\n</aside>\n<h2 id=\"sec-2\" tabindex=\"-1\">اتخاذ القرارات بـ if و elif و else</h2>\n<p>الشروط تتيح لكل صف أن يسلك مسارًا مختلفًا. فريق العمليات في Cartwheel يصنّف الطلبات بحسب حجمها:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"1\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">totals </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">65.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">18.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">33.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">35.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">72.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">58.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">329.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> totals:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x3C;</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        size </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"small\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    elif</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x3C;</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 150</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        size </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"medium\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    else</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        size </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"large\"</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(t, size)</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>تختبر Python الشروط من الأعلى إلى الأسفل ولا تشغّل إلا أول فرع صحيح. الترتيب مهم: لو جاء اختبار الـ 150 أولًا، لصُنّف كل طلب صغير على أنه متوسط أيضًا، لأن 18 أقل من 150 كذلك. ضع الشرط الأضيق أولًا، أو اجعل الشروط غير متداخلة.</p>\n<p>تستطيع دمج الشروط بـ <code dir=\"ltr\">and</code> و<code dir=\"ltr\">or</code> و<code dir=\"ltr\">not</code>. وتتيح لك Python أيضًا تسلسل المقارنات كما تكتبها في الرياضيات، وهذا مفيد مع النطاقات:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"2\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 89.0</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">channel </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"web\"</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 50</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> and</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> channel </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"web\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># both must be true</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">50</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x3C;</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 150</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)                  </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># chained: at least 50 and below 150</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">not</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> channel </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">==</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"marketplace\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># flips True and False</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p>وحين تحتاج أيضًا موقع كل عنصر، لقائمة مرتّبة أو لرسالة مثل “الصف 3 معطوب”، غلّف القائمة بـ <code dir=\"ltr\">enumerate()</code>، التي تعطيك الموقع والعنصر معًا: <code dir=\"ltr\">for position, t in enumerate(totals, start=1):</code>. فضّلها على عدّ المواقع بيدك في متغيّر منفصل.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">العدّ والجمع بحسب المجموعة</h2>\n<p>أكثر أنماط الحلقات فائدة في التحليل هو “لكل فئة، اجمع شيئًا”. يحتفظ القاموس بمجموع متراكم لكل مفتاح:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"3\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2574</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">65.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2069</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">18.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1200</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">33.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"mobile app\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1809</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">35.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"web\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1434</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">72.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">None</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2089</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">58.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"marketplace\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">},</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">revenue_by_channel </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {}</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> order </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    channel </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> order[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"channel\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">or</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"unknown\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    revenue_by_channel[channel] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> revenue_by_channel.get(channel, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> order[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"total\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> channel, revenue </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> revenue_by_channel.items():</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(channel, revenue)</span></span></code></pre><div class=\"run-output\" data-run-output=\"3\" hidden></div></div>\n<p>تفصيلان يحملان هذا الكود. <code dir=\"ltr\">revenue_by_channel.get(channel, 0)</code> تعيد المجموع المتراكم حتى الآن، أو 0 في أول مرة تظهر فيها القناة. و<code dir=\"ltr\">order[&quot;channel&quot;] or &quot;unknown&quot;</code> تستبدل <code dir=\"ltr\">None</code> بتسمية مقروءة، لأن <code dir=\"ltr\">None</code> تُعامَل كقيمة خاطئة، و<code dir=\"ltr\">or</code> تعيد الطرف الأيمن حين يكون الأيسر خاطئًا.</p>\n<p>هذا <code dir=\"ltr\">groupby</code> مكتوب باليد. في الدرس 4.1 تنجزه pandas في سطر واحد، وأنت الآن تعرف ما يفعله ذلك السطر في الخلفية: المرور على الصفوف، ومعرفة مجموعة كل صف، وتحديث مجموع تلك المجموعة.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">الـ comprehensions: بناء القوائم في سطر واحد</h2>\n<p>كثيرًا ما توجد الحلقة فقط لتبني قائمة جديدة. والـ <strong>list comprehension</strong> تقول ذلك مباشرة:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"4\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">totals </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">65.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">18.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">33.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">35.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">72.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">58.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">329.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">with_rise </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1.05</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> totals]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">large </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> totals </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">if</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">>=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 60</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(with_rise)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(large, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">len</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(large))</span></span></code></pre><div class=\"run-output\" data-run-output=\"4\" hidden></div></div>\n<p>اقرأ <code dir=\"ltr\">[t for t in totals if t &gt;= 60]</code> هكذا: “t، لكل t في totals، إذا كانت t ‏60 على الأقل”. الجزء الذي قبل <code dir=\"ltr\">for</code> هو ما يدخل القائمة، والـ <code dir=\"ltr\">if</code> في النهاية تصفّي. والـ dictionary comprehension تعمل بالطريقة نفسها مع زوج <code dir=\"ltr\">key: value</code>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"5\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"5\" aria-label=\"شغّل هذا المثال\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">countries </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Canada\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"united kingdom\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"UNITED KINGDOM\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Saudi Arabia\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">clean </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [c.strip().title() </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> c </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> countries]</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(clean)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">sorted</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">set</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(clean)))            </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># unique values, sorted</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">({c: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">len</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(c) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> c </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> set</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(clean)})</span></span></code></pre><div class=\"run-output\" data-run-output=\"5\" hidden></div></div>\n<p>الـ <code dir=\"ltr\">set</code> لا يحتفظ إلا بالقيم الفريدة، فيدمج <code dir=\"ltr\">set(clean)</code> الكتابتين المختلفتين للمملكة المتحدة في واحدة بعد تنظيفهما. ستطبّق الإصلاح نفسه على عمود كامل باستخدام pandas في الدرس 3.2.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>متى تتوقّف عن الاختصار</span></p>\n<p>الـ comprehension ممتازة ما دامت تتّسع لسطر واحد وتُقرأ كجملة. إذا احتجت شروطًا متداخلة أو عدة خطوات لكل عنصر، فاكتب حلقة عادية: الكود الأوضح أفضل من الكود الأقصر، وأنت في المستقبل من سيضطر إلى تتبّع أخطائه.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">الحلقات مقابل pandas</h2>\n<p>في pandas لن تكتب حلقة على الصفوف تقريبًا أبدًا. <code dir=\"ltr\">orders[&quot;total&quot;].sum()</code> تقوم بحلقة الجمع، و<code dir=\"ltr\">orders.groupby(&quot;channel&quot;)[&quot;total&quot;].sum()</code> تقوم بنمط القاموس السابق، وكلاهما بكود مُترجَم سريع. فلماذا تتعلّم الحلقات؟ لأنها طريقتك للتحقّق من فهمك لما تفعله عملية pandas، ولأن كثيرًا من العمل الحقيقي (المرور على ملفات، أو على أشهر، أو على قائمة دول لبناء تقرير) يبقى حلقة تحيط بكود pandas.</p>\n<p>في التمرين تلخّص اثني عشر صفًا بحسب الدولة. ثم تغلّف منطقًا كهذا في دوال قابلة لإعادة الاستخدام، وتتعلّم قراءة رسائل الخطأ التي تعرضها Python.</p>\n","toc":[{"id":"sec-1","text":"حلقة for","level":2},{"id":"sec-2","text":"اتخاذ القرارات بـ if و elif و else","level":2},{"id":"sec-3","text":"العدّ والجمع بحسب المجموعة","level":2},{"id":"sec-4","text":"الـ comprehensions: بناء القوائم في سطر واحد","level":2},{"id":"sec-5","text":"الحلقات مقابل pandas","level":2}],"takeaways":["حلقة <code dir=\"ltr\">for</code> تشغّل جسمها المُزاح (indented) مرة لكل عنصر؛ أنشئ المتغيّرات التراكمية مثل <code dir=\"ltr\">total = 0</code> قبل الحلقة، لا داخلها.","سلسلة <code dir=\"ltr\">if</code> / <code dir=\"ltr\">elif</code> / <code dir=\"ltr\">else</code> تفحص الشروط من الأعلى إلى الأسفل، ولا تشغّل إلا أول فرع يكون شرطه صحيحًا.","النمط <code dir=\"ltr\">counts[key] = counts.get(key, 0) + 1</code> هو الطريقة المعتادة للعدّ أو الجمع بحسب المجموعة باستخدام قاموس.","الـ list comprehension بالشكل <code dir=\"ltr\">[expr for x in items if condition]</code> تبني قائمة جديدة في سطر واحد مقروء.","في pandas نادرًا ما تكتب حلقات، لأن العمليات على الأعمدة تقوم بالتكرار نيابةً عنك؛ لكن الحلقات تبقى طريقتك لفهم ما تفعله تلك العمليات."],"further":[{"title":"More Control Flow Tools (if, for, range)","url":"https://docs.python.org/3/tutorial/controlflow.html"},{"title":"List Comprehensions","url":"https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions"}],"quiz":[{"q":"<p>ماذا يطبع هذا الكود؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">totals </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">65</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">18</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">33</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> totals:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    running </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    running </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> t</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(running)</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">116</code>","why":"هذا يتطلّب أن يكون <code dir=\"ltr\">running = 0</code> قبل الحلقة. أما هنا فيُعاد تصفيره في كل دورة."},{"text":"<code dir=\"ltr\">33</code>","why":"صحيح. يُعاد المتغيّر التراكمي إلى 0 في بداية كل دورة، فلا تبقى إلا القيمة الأخيرة."},{"text":"<code dir=\"ltr\">0</code>","why":"التصفير يحدث قبل الجمع في كل دورة، فتضيف الدورة الأخيرة 33 رغم ذلك."},{"text":"خطأ <code dir=\"ltr\">NameError</code>","why":"يُنشأ <code dir=\"ltr\">running</code> داخل الحلقة في الدورة الأولى، فيكون موجودًا حين تعمل <code dir=\"ltr\">print</code>."}],"answer":1},{"q":"<p>طلب مجموعه 150 يمرّ عبر <code dir=\"ltr\">if t &lt; 50: &quot;small&quot;</code> ثم <code dir=\"ltr\">elif t &lt; 150: &quot;medium&quot;</code> ثم <code dir=\"ltr\">else: &quot;large&quot;</code>. أيّ تصنيف يحصل عليه؟</p>","options":[{"text":"<code dir=\"ltr\">&quot;medium&quot;</code>","why":"المقارنة <code dir=\"ltr\">150 &lt; 150</code> تساوي <code dir=\"ltr\">False</code>، فلا يعمل فرع الـ <code dir=\"ltr\">elif</code>."},{"text":"<code dir=\"ltr\">&quot;large&quot;</code>","why":"صحيح. الشرطان كلاهما خاطئان مع 150، فيعمل فرع الـ <code dir=\"ltr\">else</code>."},{"text":"التصنيفان <code dir=\"ltr\">&quot;medium&quot;</code> و <code dir=\"ltr\">&quot;large&quot;</code> معًا","why":"سلسلة <code dir=\"ltr\">if</code>/<code dir=\"ltr\">elif</code>/<code dir=\"ltr\">else</code> تشغّل فرعًا واحدًا على الأكثر، وهو أول فرع يكون شرطه صحيحًا."}],"answer":1},{"q":"<p>أيّ comprehension تحتفظ بمجاميع طلبات الويب فقط من قائمة قواميس الطلبات؟</p>","options":[{"text":"<code dir=\"ltr\">[o[&quot;total&quot;] for o in orders if o[&quot;channel&quot;] == &quot;web&quot;]</code>","why":"صحيح. التعبير الذي قبل <code dir=\"ltr\">for</code> هو ما يدخل القائمة الجديدة، والـ <code dir=\"ltr\">if</code> في النهاية تصفّي العناصر التي تصل إليها."},{"text":"<code dir=\"ltr\">[o for o in orders if o[&quot;channel&quot;] == &quot;web&quot;][&quot;total&quot;]</code>","why":"هذا يبني قائمة من القواميس ثم يحاول الوصول إلى عنصر في القائمة بنص، وهذا يسبّب <code dir=\"ltr\">TypeError</code>."},{"text":"<code dir=\"ltr\">[o[&quot;total&quot;] if o[&quot;channel&quot;] == &quot;web&quot; for o in orders]</code>","why":"شرط التصفية يأتي بعد الـ <code dir=\"ltr\">for</code>. والـ <code dir=\"ltr\">if</code> التي تأتي قبل الـ <code dir=\"ltr\">for</code> لا بد لها من <code dir=\"ltr\">else</code>، لذا هذا خطأ في الصياغة."}],"answer":0}],"exercise":{"kind":"python","files":[],"starter":"orders = [\n    {\"order_id\": 2574, \"total\": 65.0, \"channel\": \"mobile app\", \"country\": \"Canada\"},\n    {\"order_id\": 2069, \"total\": 18.0, \"channel\": \"mobile app\", \"country\": \"United States\"},\n    {\"order_id\": 1200, \"total\": 33.0, \"channel\": \"mobile app\", \"country\": \"united kingdom\"},\n    {\"order_id\": 1809, \"total\": 35.0, \"channel\": \"web\", \"country\": \"United States\"},\n    {\"order_id\": 1434, \"total\": 72.0, \"channel\": None, \"country\": \"Saudi Arabia\"},\n    {\"order_id\": 2089, \"total\": 58.0, \"channel\": \"marketplace\", \"country\": \"UNITED KINGDOM\"},\n    {\"order_id\": 2490, \"total\": 89.0, \"channel\": \"web\", \"country\": \"United Arab Emirates\"},\n    {\"order_id\": 2985, \"total\": 24.0, \"channel\": \"web\", \"country\": \"United Kingdom\"},\n    {\"order_id\": 2544, \"total\": 58.0, \"channel\": \"mobile app\", \"country\": \"Jordan\"},\n    {\"order_id\": 2375, \"total\": 329.0, \"channel\": \"mobile app\", \"country\": \"United Kingdom\"},\n    {\"order_id\": 1129, \"total\": 29.0, \"channel\": \"web\", \"country\": \"United States\"},\n    {\"order_id\": 1176, \"total\": 44.0, \"channel\": \"web\", \"country\": \"United States\"},\n]\n# 1. Revenue per country, with country names cleaned by .strip().title()\nrevenue_by_country = {}\n\n# 2. order_id of every order with a total of 60 or more, in the original order\nlarge_ids = []\n\n# 3. How many orders came through the \"web\" channel\nweb_count = 0\n","solution":"orders = [\n    {\"order_id\": 2574, \"total\": 65.0, \"channel\": \"mobile app\", \"country\": \"Canada\"},\n    {\"order_id\": 2069, \"total\": 18.0, \"channel\": \"mobile app\", \"country\": \"United States\"},\n    {\"order_id\": 1200, \"total\": 33.0, \"channel\": \"mobile app\", \"country\": \"united kingdom\"},\n    {\"order_id\": 1809, \"total\": 35.0, \"channel\": \"web\", \"country\": \"United States\"},\n    {\"order_id\": 1434, \"total\": 72.0, \"channel\": None, \"country\": \"Saudi Arabia\"},\n    {\"order_id\": 2089, \"total\": 58.0, \"channel\": \"marketplace\", \"country\": \"UNITED KINGDOM\"},\n    {\"order_id\": 2490, \"total\": 89.0, \"channel\": \"web\", \"country\": \"United Arab Emirates\"},\n    {\"order_id\": 2985, \"total\": 24.0, \"channel\": \"web\", \"country\": \"United Kingdom\"},\n    {\"order_id\": 2544, \"total\": 58.0, \"channel\": \"mobile app\", \"country\": \"Jordan\"},\n    {\"order_id\": 2375, \"total\": 329.0, \"channel\": \"mobile app\", \"country\": \"United Kingdom\"},\n    {\"order_id\": 1129, \"total\": 29.0, \"channel\": \"web\", \"country\": \"United States\"},\n    {\"order_id\": 1176, \"total\": 44.0, \"channel\": \"web\", \"country\": \"United States\"},\n]\nrevenue_by_country = {}\nfor order in orders:\n    country = order[\"country\"].strip().title()\n    revenue_by_country[country] = revenue_by_country.get(country, 0) + order[\"total\"]\nlarge_ids = [o[\"order_id\"] for o in orders if o[\"total\"] >= 60]\nweb_count = 0\nfor o in orders:\n    if o[\"channel\"] == \"web\":\n        web_count += 1\n","checks":[{"id":"countries-clean","test":"sorted(revenue_by_country) == ['Canada', 'Jordan', 'Saudi Arabia', 'United Arab Emirates', 'United Kingdom', 'United States']"},{"id":"uk-total","test":"round(revenue_by_country.get('United Kingdom', 0), 2) == 444.0"},{"id":"all-revenue","test":"round(sum(revenue_by_country.values()), 2) == 854.0"},{"id":"large-ids","test":"list(large_ids) == [2574, 1434, 2490, 2375]"},{"id":"web-count","test":"web_count == 5"}],"title":"لخّص اثني عشر طلبًا بحسب الدولة","prompt":"<p>تحتوي <code dir=\"ltr\">orders</code> على اثني عشر صفًا من الملف الفوضوي، وأسماء الدول مكتوبة بأحرف كبيرة وصغيرة غير متّسقة. ابنِ <code dir=\"ltr\">revenue_by_country</code>، قاموسًا من اسم الدولة بعد تنظيفه (استخدم <code dir=\"ltr\">.strip().title()</code>) إلى مجموع <code dir=\"ltr\">total</code>. وابنِ <code dir=\"ltr\">large_ids</code>، قائمة بأرقام <code dir=\"ltr\">order_id</code> للطلبات التي مجموعها 60 أو أكثر، بترتيبها الأصلي. واجعل <code dir=\"ltr\">web_count</code> عدد الطلبات التي قناتها <code dir=\"ltr\">&quot;web&quot;</code> بالضبط.</p>\n","hints":["مرّ على <code dir=\"ltr\">orders</code> مرة واحدة لبناء القاموس: نظّف الدولة في متغيّر أولًا، ثم حدّث المجموع لذلك المفتاح.","<code dir=\"ltr\">revenue_by_country[country] = revenue_by_country.get(country, 0) + order[&quot;total&quot;]</code> تضيف إلى مجموع موجود أو تبدأ مجموعًا جديدًا.","<code dir=\"ltr\">large_ids = [o[&quot;order_id&quot;] for o in orders if o[&quot;total&quot;] &gt;= 60]</code>. ولـ <code dir=\"ltr\">web_count</code>، يعمل <code dir=\"ltr\">sum(1 for o in orders if o[&quot;channel&quot;] == &quot;web&quot;)</code> أو حلقة فيها <code dir=\"ltr\">+= 1</code>."],"explanation":"<p>تنظيف المفتاح قبل استخدامه هو ما يجعل <code dir=\"ltr\">&quot;united kingdom&quot;</code> و<code dir=\"ltr\">&quot;UNITED KINGDOM&quot;</code> و<code dir=\"ltr\">&quot;United Kingdom&quot;</code> تقع في الخانة نفسها؛ بدونه ستحصل على ثلاثة مدخلات للمملكة المتحدة ومجموع موزّع على ثلاثة. النمط <code dir=\"ltr\">.get(key, 0)</code> يتعامل مع أول ظهور لكل دولة. والـ comprehension تحافظ على الترتيب الأصلي لأنها تمرّ على <code dir=\"ltr\">orders</code> من البداية إلى النهاية. المجموع الكلي عبر الدول يبقى 854.0، وهذه طريقة سريعة للتأكّد من أن التجميع لم يُضِع صفًا ولم يحسبه مرتين: تحقّق دائمًا من أن الأجزاء مجموعها يساوي الكل.</p>\n","checkLabels":{"countries-clean":"ستة أسماء دول منظّفة بالضبط، دون اختلافات في حالة الأحرف","uk-total":"مجموع United Kingdom يساوي 444.0","all-revenue":"مجاميع الدول تساوي 854.0، وهو مجموع الطلبات الاثني عشر كلها","large-ids":"<code dir=\"ltr\">large_ids</code> تساوي <code dir=\"ltr\">[2574, 1434, 2490, 2375]</code>","web-count":"<code dir=\"ltr\">web_count</code> يساوي 5"}},"words":621,"readMinutes":4}