{"id":"l-pda-1-5","courseId":"python-data-analysis","lang":"ar","kind":"lesson","summary":"غلّف المنطق المتكرّر في دوال لها مُدخلات وقيم مُعادة، ونسّق الأرقام للتقارير باستخدام f-strings، واقرأ الـ traceback في Python لتجد المشكلة الحقيقية وتصلحها.","html":"<p>حتى الآن نظّفت السعر <code dir=\"ltr\">&quot; $129.00&quot;</code> مرة، وحسبت إيراد بند واحد مرة، وطبعت بضعة أرقام. لدى Cartwheel ‏3,991 بندًا في الطلبات. لا تريد نسخ كود التنظيف إلى كل مكان يحتاجه، ثم إصلاح خطأ واحد في سبع نسخ. الدوال تتيح لك كتابة المنطق مرة واحدة، ومنحه اسمًا، واستدعاءه حيثما احتجته.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">تعريف دالة</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:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> line_revenue</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(quantity, unit_price, discount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">):</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">    \"\"\"Revenue of one order line: quantity x price, minus the discount.\"\"\"</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(quantity </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> unit_price </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> discount), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(line_revenue(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">129.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.15</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># 219.3</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(line_revenue(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">39.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))          </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># discount defaults to 0.0</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(line_revenue(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">quantity</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">unit_price</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">24.0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">discount</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0.25</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>الأجزاء هي: <code dir=\"ltr\">def</code>، ثم اسم الدالة، ثم المُعامِلات بين قوسين، ثم نقطتان رأسيتان، ثم جسم مُزاح. و<code dir=\"ltr\">discount=0.0</code> قيمة <strong>افتراضية</strong> تُستخدم حين يتركها المستدعي. والسطر المحاط بثلاث علامات تنصيص تحت <code dir=\"ltr\">def</code> هو docstring، يوثّق ما تفعله الدالة؛ وتعرضه المحرّرات حين تمرّر المؤشر فوق الاسم.</p>\n<p>ترسل <code dir=\"ltr\">return</code> قيمة إلى المستدعي، فيصبح الاستدعاء <code dir=\"ltr\">line_revenue(2, 129.0, 0.15)</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\">print(total)</code> تعرض الرقم ثم تعيد <code dir=\"ltr\">None</code>. لاحقًا يفشل <code dir=\"ltr\">line_revenue(...) * 2</code> بالخطأ <code dir=\"ltr\">TypeError: unsupported operand type(s) for *: 'NoneType' and 'int'</code>. الدوال التي تحسب يجب أن تستخدم <code dir=\"ltr\">return</code>؛ ودع المستدعي يقرّر هل يطبع.</p>\n</aside>\n<h2 id=\"sec-2\" tabindex=\"-1\">دوال التنظيف</h2>\n<p>هذه أداة تنظيف المبالغ من الدرس 1.2 وقد أصبحت قابلة لإعادة الاستخدام. تتعامل مع علامة الدولار والمسافات الزائدة وفواصل الآلاف:</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:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> parse_money</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(text):</span></span>\n<span class=\"line\"><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">    \"\"\"Turn strings like ' $1,234.50' into the float 1234.5.\"\"\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    cleaned </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> text.strip().replace(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"$\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).replace(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\",\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> float</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cleaned)</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\"> raw </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\" $129.00\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"18.00\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"$1,234.50\"</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\">(raw, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"->\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, parse_money(raw))</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>امنح الدوال أسماء أفعال تقول ما تعيده (<code dir=\"ltr\">parse_money</code> و<code dir=\"ltr\">line_revenue</code> و<code dir=\"ltr\">clean_country</code>)، واجعل لكل منها مهمة واحدة؛ الدوال الصغيرة سهلة الاختبار ببضعة استدعاءات لـ <code dir=\"ltr\">print</code> مثل الحلقة السابقة. الآن يستطيع كل مجموع فوضوي في الملف المُصدَّر أن يمرّ عبر دالة واحدة مُختبَرة. وإذا اكتشفت صيغة جديدة الشهر القادم (لنقل <code dir=\"ltr\">USD</code> في نهاية النص)، فتصلحها في مكان واحد.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">الـ f-strings: أرقام يستطيع الناس قراءتها</h2>\n<p>تقرير يقول <code dir=\"ltr\">146825.4412</code> يجعل القرّاء يضيّقون أعينهم. الـ <strong>f-string</strong>، أي نص يسبق علامة تنصيصه الأولى حرف <code dir=\"ltr\">f</code>، تتيح لك وضع القيم داخل النص بين <code dir=\"ltr\">{}</code> وتنسيقها بمواصفة بعد نقطتين رأسيتين:</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\">revenue </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 146825.4412</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 642</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">share </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.4493</span></span>\n<span class=\"line\"></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\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Q4 2025 revenue: $</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">revenue</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:,.2f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)       </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># thousands separator, 2 decimals</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\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Orders: </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">, average </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">revenue </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:.2f}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> per order\"</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\">(</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Share of the year: </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">share</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:.1%}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)          </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># percent with 1 decimal</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\">f</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"|</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">'Egypt'</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:&#x3C;12}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">|</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">{</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">:>6}</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">|\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)             </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\"># left- and right-aligned columns</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p>المواصفات التي ستستخدمها أكثر من غيرها: <code dir=\"ltr\">,.2f</code> للمبالغ المالية، و<code dir=\"ltr\">.1%</code> للنِّسَب (تضرب في 100 نيابةً عنك)، و<code dir=\"ltr\">,.0f</code> للأعداد الصحيحة الكبيرة، و<code dir=\"ltr\">&lt;</code>/<code dir=\"ltr\">&gt;</code> مع عرض محدّد لمحاذاة النص. وأي تعبير يعمل داخل الأقواس المعقوفة، بما في ذلك عمليات حسابية مثل <code dir=\"ltr\">revenue / orders</code>.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">قراءة الأخطاء دون ذعر</h2>\n<p>حين لا تستطيع Python المتابعة، تُطلق <strong>استثناءً (exception)</strong> وتطبع traceback (تتبّع الخطأ). المبتدئون يقرؤونه من الأعلى فيتوهون. اقرأه من <strong>الأسفل</strong>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Text</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>Traceback (most recent call last):\n  File &quot;report.py&quot;, line 9, in &lt;module&gt;\n    total = parse_money(row[&quot;Total&quot;])\n                        ~~~^^^^^^^^^\nKeyError: 'Total'</code></pre></div>\n<p>السطر الأخير هو نوع الخطأ ورسالته: طُلب من قاموس المفتاح <code dir=\"ltr\">'Total'</code> وهو غير موجود فيه. وفوقه بسطر الكود الذي فشل، مع علامات تحت التعبير بالضبط، وفوق ذلك الملف ورقم السطر. والإصلاح هنا هو الاسم الحقيقي للعمود، <code dir=\"ltr\">'total'</code>.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 200\" role=\"img\" aria-labelledby=\"l-pda-1-5-t1\"><defs><marker id=\"arrow-l-pda-1-5-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-pda-1-5-t1\">traceback من ثلاث طبقات. في الأسفل: نوع الخطأ ورسالته، وتُقرأ أولًا. في الوسط: سطر الكود الذي فشل مع العلامات. في الأعلى: الملف ورقم السطر، وتستخدمهما لتجد المكان في كودك.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"20\" width=\"430\" height=\"44\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"36\" y=\"47\">File \"report.py\", line 9</text>\n  <rect class=\"d-box\" x=\"20\" y=\"76\" width=\"430\" height=\"44\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"36\" y=\"103\">total = parse_money(row[\"Total\"])</text>\n  <rect class=\"d-box-warn\" x=\"20\" y=\"132\" width=\"430\" height=\"44\" rx=\"8\"/>\n  <text class=\"d-code\" x=\"36\" y=\"159\">KeyError: 'Total'</text>\n  <text class=\"d-label-strong\" x=\"480\" y=\"159\">1. ما الخطأ</text>\n  <text class=\"d-label\" x=\"480\" y=\"103\">2. أيّ تعبير</text>\n  <text class=\"d-label-muted\" x=\"480\" y=\"47\">3. أين تبحث</text>\n  <path class=\"d-arrow\" d=\"M680 150 L680 58\" marker-end=\"url(#arrow-l-pda-1-5-1)\"/>\n</svg><figcaption>اقرأ الـ traceback من الأسفل إلى الأعلى</figcaption></figure>\n<p>الأخطاء التي ستقابلها أكثر من غيرها، وما تعنيه في أغلب الأحيان:</p>\n<div class=\"table-wrap\" role=\"region\" aria-label=\"جدول قابل للتمرير\" tabindex=\"0\"><table><thead>\n<tr>\n<th>الخطأ</th>\n<th>السبب المعتاد</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code dir=\"ltr\">NameError</code></td>\n<td>خطأ كتابي في اسم متغيّر، أو استخدامه قبل إسناد قيمة له</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">KeyError</code></td>\n<td>مفتاح قاموس أو عمود DataFrame غير موجود (افحص الكتابة وحالة الأحرف)</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">TypeError</code></td>\n<td>خلط بين الأنواع، مثل نص زائد رقم، أو استدعاء دالة بوسائط خاطئة</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">ValueError</code></td>\n<td>النوع صحيح لكن المحتوى ليس كذلك، مثل <code dir=\"ltr\">float(&quot;$65.00&quot;)</code></td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">IndexError</code></td>\n<td>موقع في القائمة بعد نهايتها</td>\n</tr>\n<tr>\n<td><code dir=\"ltr\">AttributeError</code></td>\n<td>استدعاء method لا تملكها القيمة، وكثيرًا ما يحدث مع <code dir=\"ltr\">None</code></td>\n</tr>\n</tbody>\n</table></div><h3 id=\"sec-5\" tabindex=\"-1\">التعامل مع خطأ تتوقّعه</h3>\n<p>بعض حالات الفشل جزء من البيانات، لا أخطاء في الكود. مجموع فوضوي مثل <code dir=\"ltr\">&quot;N/A&quot;</code> لن يصبح رقمًا أبدًا. تتيح لك <code dir=\"ltr\">try</code> / <code dir=\"ltr\">except</code> أن تقرّر ما يحدث بدلًا من ذلك:</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:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> parse_money_or_none</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(text):</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    try</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> float</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(text.strip().replace(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"$\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).replace(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\",\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    except</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> ValueError</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">:</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> None</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(parse_money_or_none(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"$65.00\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), parse_money_or_none(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"N/A\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"4\" hidden></div></div>\n<p>التقط الاستثناء المحدّد الذي تتوقّعه (<code dir=\"ltr\">ValueError</code> هنا) ولا شيء غيره. أما <code dir=\"ltr\">except:</code> المجرّدة فستبتلع أيضًا خطأً كتابيًا في كودك أنت، وستحصل على <code dir=\"ltr\">None</code> في كل مكان دون أي فكرة عن السبب.</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>حين تكون رسالة الخطأ جديدة عليك، انسخ سطرها الأخير، بعد حذف أسماء متغيّراتك، إلى محرّك بحث. شخص ما واجهها قبلك، وأول إجابة تشرحها عادةً في فقرة.</p>\n</aside>\n<p>بهذا تكتمل عُدّتك من Python. القسم 2 يضعها في العمل على نطاق واسع: pandas، حيث يعمل سطر واحد على كل صفوف الجدول.</p>\n","toc":[{"id":"sec-1","text":"تعريف دالة","level":2},{"id":"sec-2","text":"دوال التنظيف","level":2},{"id":"sec-3","text":"الـ f-strings: أرقام يستطيع الناس قراءتها","level":2},{"id":"sec-4","text":"قراءة الأخطاء دون ذعر","level":2},{"id":"sec-5","text":"التعامل مع خطأ تتوقّعه","level":3}],"takeaways":["الدالة تمنح جزءًا من المنطق اسمًا؛ المُعامِلات (parameters) هي مُدخلاتها، و<code dir=\"ltr\">return</code> تعيد مُخرجها.","الدالة التي تطبع بدلًا من أن تُعيد تعطيك <code dir=\"ltr\">None</code>، فلا يمكن استخدام نتيجتها في حسابات لاحقة.","الـ f-strings تنسّق القيم داخل النص: <code dir=\"ltr\">f&quot;{revenue:,.2f}&quot;</code> تعطي <code dir=\"ltr\">1,234.50</code>، و<code dir=\"ltr\">f&quot;{share:.1%}&quot;</code> تعطي <code dir=\"ltr\">12.5%</code>.","اقرأ الـ traceback من الأسفل - السطر الأخير يسمّي نوع الخطأ ورسالته، والأسطر التي فوقه تبيّن أين حدث.","استخدم <code dir=\"ltr\">try</code> / <code dir=\"ltr\">except</code> للتعامل مع خطأ تتوقّعه، مثل نص لا يمكن أن يصبح رقمًا؛ ولا تستخدمها أبدًا لإخفاء أخطاء لا تفهمها."],"further":[{"title":"Defining Functions","url":"https://docs.python.org/3/tutorial/controlflow.html#defining-functions"},{"title":"Formatted String Literals (f-strings)","url":"https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals"},{"title":"Errors and Exceptions","url":"https://docs.python.org/3/tutorial/errors.html"},{"title":"Format Specification Mini-Language","url":"https://docs.python.org/3/library/string.html#format-specification-mini-language"}],"quiz":[{"q":"<p>ما قيمة <code dir=\"ltr\">result</code> بعد تشغيل هذا الكود؟</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:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> add_tax</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(amount):</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">    print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(amount </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1.2</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\">result </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> add_tax(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">120.0</code>","why":"الدالة تعرض 120.0، لكن العرض ليس إعادة. بدون <code dir=\"ltr\">return</code> لا يعود إلى المستدعي شيء."},{"text":"<code dir=\"ltr\">None</code>","why":"صحيح. الدالة التي ليس فيها <code dir=\"ltr\">return</code> تعيد <code dir=\"ltr\">None</code>، أيًّا كان ما طبعته في طريقها."},{"text":"النص <code dir=\"ltr\">&quot;120.0&quot;</code>","why":"الدالة <code dir=\"ltr\">print</code> تكتب النص في المخرجات، ولا تعيده إلى المستدعي."}],"answer":1},{"q":"<p>أيّ f-string تطبع <code dir=\"ltr\">Revenue: $146,825.44</code> حين تكون <code dir=\"ltr\">revenue = 146825.4412</code>؟</p>","options":[{"text":"<code dir=\"ltr\">f&quot;Revenue: ${revenue:.2f}&quot;</code>","why":"هذه تعطي <code dir=\"ltr\">$146825.44</code> بلا فاصل للآلاف. الفاصلة في مواصفة التنسيق هي التي تضيفه."},{"text":"<code dir=\"ltr\">f&quot;Revenue: ${revenue:,}&quot;</code>","why":"الفاصلة تضيف فواصل الآلاف، لكن لا توجد دقة محدّدة، فتحصل على كل المنازل العشرية للعدد."},{"text":"<code dir=\"ltr\">f&quot;Revenue: ${revenue:,.2f}&quot;</code>","why":"صحيح. <code dir=\"ltr\">,</code> تضيف فواصل الآلاف و<code dir=\"ltr\">.2f</code> تثبّت منزلتين عشريتين، فتقرّب القيمة عند العرض."},{"text":"<code dir=\"ltr\">f&quot;Revenue: {round(revenue)}&quot;</code>","why":"هذه تُسقط السنتات وعلامة الدولار تمامًا."}],"answer":2},{"q":"<p>السطر الأخير من الـ traceback يقول:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"text\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Text</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>KeyError: 'Total'</code></pre></div>\n<p>ما السبب الأرجح؟</p>\n","options":[{"text":"الكود يطلب من قاموس (أو DataFrame) مفتاحًا اسمه <code dir=\"ltr\">'Total'</code> غير موجود؛ والمفتاح الحقيقي غالبًا <code dir=\"ltr\">'total'</code>.","why":"صحيح. الخطأ <code dir=\"ltr\">KeyError</code> يسمّي دائمًا المفتاح المفقود. والمفاتيح حسّاسة لحالة الأحرف، فقارن الكتابة بالمفاتيح الفعلية."},{"text":"قيمة <code dir=\"ltr\">total</code> لا يمكن تحويلها إلى رقم.","why":"فشل التحويل يسبّب <code dir=\"ltr\">ValueError</code>، لا <code dir=\"ltr\">KeyError</code>."},{"text":"المتغيّر <code dir=\"ltr\">Total</code> لم يُعرَّف أبدًا.","why":"المتغيّر غير المعرَّف يسبّب <code dir=\"ltr\">NameError</code> برسالة تقول إن الاسم غير معرَّف. علامات التنصيص في الرسالة تشير إلى بحث عن مفتاح."}],"answer":0},{"q":"<p>متى يكون تغليف الكود بـ <code dir=\"ltr\">try</code> / <code dir=\"ltr\">except</code> فكرة جيدة؟</p>","options":[{"text":"حول الـ script كله، كي لا يتعطّل أبدًا أمام مديرك.","why":"هذا يخفي كل الأخطاء، ومنها التي تجعل أرقامك خاطئة. التعطّل الظاهر أفضل من إجابة خاطئة صامتة."},{"text":"حول عملية واحدة تتوقّع أن تفشل مع بعض المُدخلات، مع نوع استثناء محدّد وبديل واضح.","why":"صحيح. مثلًا، التقاط <code dir=\"ltr\">ValueError</code> عند تحويل نص كتبه مستخدم، وإعادة <code dir=\"ltr\">None</code> للقيم التي ليست أرقامًا."},{"text":"كلما رأيت <code dir=\"ltr\">SyntaxError</code>.","why":"أخطاء الصياغة تحدث قبل تشغيل الكود، فلا تستطيع <code dir=\"ltr\">try</code> التقاطها؛ الحل أن تصلح الكود."}],"answer":1}],"exercise":{"kind":"python","files":[],"starter":"def parse_money(text):\n    \"\"\"' $1,234.50' -> 1234.5\"\"\"\n    pass\n\n\ndef line_revenue(quantity, unit_price, discount=0.0):\n    \"\"\"quantity x unit_price x (1 - discount), rounded to 2 decimals\"\"\"\n    pass\n\n\ndef format_money(amount):\n    \"\"\"1234.5 -> '$1,234.50'\"\"\"\n    pass\n\n\nprint(parse_money(\" $1,234.50\"), line_revenue(2, 129.0, 0.15), format_money(1234.5))\n","solution":"def parse_money(text):\n    \"\"\"' $1,234.50' -> 1234.5\"\"\"\n    return float(text.strip().replace(\"$\", \"\").replace(\",\", \"\"))\n\n\ndef line_revenue(quantity, unit_price, discount=0.0):\n    \"\"\"quantity x unit_price x (1 - discount), rounded to 2 decimals\"\"\"\n    return round(quantity * unit_price * (1 - discount), 2)\n\n\ndef format_money(amount):\n    \"\"\"1234.5 -> '$1,234.50'\"\"\"\n    return f\"${amount:,.2f}\"\n\n\nprint(parse_money(\" $1,234.50\"), line_revenue(2, 129.0, 0.15), format_money(1234.5))\n","checks":[{"id":"parse-simple","test":"parse_money('18.00') == 18.0 and parse_money(' $129.00') == 129.0"},{"id":"parse-thousands","test":"parse_money('$1,234.50') == 1234.5"},{"id":"revenue","test":"line_revenue(2, 129.0, 0.15) == 219.3 and line_revenue(3, 24.0, 0.25) == 54.0"},{"id":"revenue-default","test":"line_revenue(1, 39.0) == 39.0"},{"id":"format","test":"format_money(1234.5) == '$1,234.50' and format_money(18) == '$18.00'"}],"title":"ثلاث دوال مساعدة للتقرير","prompt":"<p>أكمل ثلاث دوال. <code dir=\"ltr\">parse_money(text)</code> تعيد عددًا عشريًا من نصوص مثل <code dir=\"ltr\">&quot; $1,234.50&quot;</code> أو <code dir=\"ltr\">&quot;$129.00&quot;</code> أو <code dir=\"ltr\">&quot;18.00&quot;</code>. و<code dir=\"ltr\">line_revenue(quantity, unit_price, discount=0.0)</code> تعيد الكمية × سعر الوحدة × (1 − الخصم)، مقرّبًا إلى منزلتين عشريتين؛ والخصم الافتراضي 0. و<code dir=\"ltr\">format_money(amount)</code> تعيد نصًا مثل <code dir=\"ltr\">&quot;$1,234.50&quot;</code>: علامة دولار، وفواصل للآلاف، ومنزلتان عشريتان بالضبط. يجب أن تُعيد كل دالة نتيجتها بـ <code dir=\"ltr\">return</code>، لا أن تطبعها.</p>\n","hints":["استبدل <code dir=\"ltr\">pass</code> بجملة <code dir=\"ltr\">return</code> في كل دالة.","في <code dir=\"ltr\">parse_money</code>، سلسِل <code dir=\"ltr\">.strip()</code> و<code dir=\"ltr\">.replace(&quot;$&quot;, &quot;&quot;)</code> و<code dir=\"ltr\">.replace(&quot;,&quot;, &quot;&quot;)</code>، ثم غلّف كل ذلك بـ <code dir=\"ltr\">float()</code>.","في <code dir=\"ltr\">format_money</code>، تقوم f-string بالمواصفة <code dir=\"ltr\">,.2f</code> بكل التنسيق: <code dir=\"ltr\">f&quot;${amount:,.2f}&quot;</code>."],"explanation":"<p>كل دالة تقوم بمهمة واحدة وتعيد نتيجتها، لذا يمكن تركيبها معًا: <code dir=\"ltr\">format_money(line_revenue(2, parse_money(&quot;$129.00&quot;), 0.15))</code> تعطي <code dir=\"ltr\">&quot;$219.30&quot;</code>. والقيمة الافتراضية <code dir=\"ltr\">discount=0.0</code> تعني أن المستدعي يستطيع تركها في البنود التي تُباع بالسعر الكامل. في <code dir=\"ltr\">format_money</code>، علامة <code dir=\"ltr\">$</code> الأولى نص حرفي، والأقواس المعقوفة تحمل القيمة مع المواصفة <code dir=\"ltr\">,.2f</code>: فواصل آلاف ومنزلتان عشريتان ثابتتان. ستعيد استخدام هذا المنطق نفسه على أعمدة pandas كاملة في القسم 3.</p>\n","checkLabels":{"parse-simple":"<code dir=\"ltr\">parse_money</code> تتعامل مع <code dir=\"ltr\">&quot;18.00&quot;</code> و<code dir=\"ltr\">&quot; $129.00&quot;</code>","parse-thousands":"<code dir=\"ltr\">parse_money</code> تتعامل مع فواصل الآلاف: <code dir=\"ltr\">&quot;$1,234.50&quot;</code> تصبح 1234.5","revenue":"<code dir=\"ltr\">line_revenue</code> تطبّق الخصم وتقرّب إلى منزلتين عشريتين","revenue-default":"<code dir=\"ltr\">line_revenue</code> تعمل دون تمرير وسيط الخصم","format":"<code dir=\"ltr\">format_money(1234.5)</code> تعيد <code dir=\"ltr\">&quot;$1,234.50&quot;</code>"}},"words":606,"readMinutes":4}