<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/page/7/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</description><language>ar</language><item><title>&#x627;&#x644;&#x639;&#x644;&#x627;&#x642;&#x627;&#x62A; &#x628;&#x64A;&#x646; &#x627;&#x644;&#x645;&#x62A;&#x63A;&#x64A;&#x631;&#x627;&#x62A; &#x627;&#x644;&#x625;&#x62D;&#x635;&#x627;&#x626;&#x64A;&#x629; &#x648;&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x646;&#x641;&#x64A;&#x630;&#x647;&#x627; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%B9%D9%84%D8%A7%D9%82%D8%A7%D8%AA-%D8%A8%D9%8A%D9%86-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D9%81%D9%8A%D8%B0%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1381/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_11/61a1283f0eeef_--.png.360d71b98cb94d927bfa7e45d0ab9840.png" /></p>

<p>
	تناولنا في المقالات السابقة كل متغير على حدة وسنناقش العلاقات بين المتغيرات في هذا الفصل، حيث نقول عن متغيرين أنهما مرتبطان إذا استطعت استنباط معلومات عن أحدهما لمجرّد علمك بالمتغير الآخر، إذ يُعَدّ الطول والوزن مثلًا متغيرَين مرتبطَين، فعادةً ما يكون الأشخاص الأطول هم الأكثر وزنًا من غيرهم، لكنها بالطبع ليست علاقةً مثاليةً، إذ يوجد بعض الأشخاص الذين لا يتمتعون بطول كبير لكنّ وزنهم مرتفع، كما يوجد بعض الأشخاص النحيلين والطوال، لكن إذا حاولت تخمين وزن شخص ما، فستكون إجابتك أكثر دقةً إذا علمت طوله.
</p>

<p>
	يمكنك الحصول على الشيفرة الخاصة بهذا المقال في <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/scatter.py" rel="external nofollow">scatter.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h2>
	مخططات الانتشار Scatter plots
</h2>

<p>
	تتمثل أسهل طريقة للتحقق مما إذا كان هناك علاقةً بين متغيرَين في إنشاء مخطط انتشار scatter plot، لكن رسم مخطط انتشار جيّد ليس بالمهمة السهلة.
</p>

<p>
	سنرسم مخطط الأوزان مقابل الأطوال للمستجيبين في نظام مراقبة عوامل المخاطر السلوكية BRFSS على أساس مثال على ذلك، كما يمكنك الاطلاع على قسم التوزيع اللوغاريتمي الطبيعي في مقال <a href="https://academy.hsoub.com/programming/python/%D9%86%D9%85%D8%B0%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-modelling-distributions-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1332/" rel="">نمذجة التوزيعات Modelling distributions في بايثون</a>.
</p>

<p>
	إليك الشيفرة التي تقرأ ملف البيانات وتستخرج الطول والوزن:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_8" style="">
<span class="pln">df </span><span class="pun">=</span><span class="pln"> brfss</span><span class="pun">.</span><span class="typ">ReadBrfss</span><span class="pun">(</span><span class="pln">nrows</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">)</span><span class="pln">
sample </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">SampleRows</span><span class="pun">(</span><span class="pln">df</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5000</span><span class="pun">)</span><span class="pln">
heights</span><span class="pun">,</span><span class="pln"> weights </span><span class="pun">=</span><span class="pln"> sample</span><span class="pun">.</span><span class="pln">htm3</span><span class="pun">,</span><span class="pln"> sample</span><span class="pun">.</span><span class="pln">wtkg2</span></pre>

<p>
	يختار التابع <code>SampleRows</code> مجموعةً جزئيةً عشوائيةً من البيانات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_10" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">SampleRows</span><span class="pun">(</span><span class="pln">df</span><span class="pun">,</span><span class="pln"> nrows</span><span class="pun">,</span><span class="pln"> replace</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">):</span><span class="pln">
    indices </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">choice</span><span class="pun">(</span><span class="pln">df</span><span class="pun">.</span><span class="pln">index</span><span class="pun">,</span><span class="pln"> nrows</span><span class="pun">,</span><span class="pln"> replace</span><span class="pun">=</span><span class="pln">replace</span><span class="pun">)</span><span class="pln">
    sample </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">loc</span><span class="pun">[</span><span class="pln">indices</span><span class="pun">]</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> sample</span></pre>

<p>
	يشير <code>df</code> إلى إطار البيانات DataFrame، في حين يشير <code>nrows</code> إلى عدد الأسطر المختارة، كما يُعَدّ <code>replace</code> متغيرًا بوليانيًا يخبرنا عما إذا كانت عملية أخذ العيّنات sampling ستكون مع الاستبدال أم لا، أي إذا كان بالإمكان اختيار الأسطر نفسها أكثر من مرة.
</p>

<p>
	تزوِّدنا <code>thinkplot</code> بالتابع <code>Scatter</code> الذي ينشئ مخططات انتشار، وفيما يلي الشيفرة الموافقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_12" style="">
<span class="pln">thinkplot</span><span class="pun">.</span><span class="typ">Scatter</span><span class="pun">(</span><span class="pln">heights</span><span class="pun">,</span><span class="pln"> weights</span><span class="pun">)</span><span class="pln">
thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'Height (cm)'</span><span class="pun">,</span><span class="pln">
               ylabel</span><span class="pun">=</span><span class="str">'Weight (kg)'</span><span class="pun">,</span><span class="pln">
               axis</span><span class="pun">=[</span><span class="lit">140</span><span class="pun">,</span><span class="pln"> </span><span class="lit">210</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">200</span><span class="pun">])</span></pre>

<p>
	تظهر النتيجة الموجودة في الشكل التالي من الجهة اليسرى شكل العلاقة، وكما هو متوقع فإنّ الأشخاص الذين يتمتعون بطول عالٍ يميلون لأن يكونوا أكثر وزنًا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="83428" href="https://academy.hsoub.com/uploads/monthly_2021_11/61a1178e7623f_7.1.png.8fc4ef2d3df46f12c70cfcae01d0d77e.png" rel=""><img alt="الشكل 7.1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="83428" data-unique="q1upxo4nc" src="https://academy.hsoub.com/uploads/monthly_2021_11/61a1178e7623f_7.1.png.8fc4ef2d3df46f12c70cfcae01d0d77e.png"></a>
</p>

<p>
	يوضِّح الشكل السابق مخططات الانتشار للأوزان مقابل الأطوال للمستجيبين BRFSS، مع العلم أنه غير عشوائي في الجهة اليسرى وعشوائي في الجهة اليمنى.
</p>

<p>
	لا يُعَدّ هذا أفضل تمثيل للبيانات لأنها محزَّمة ضمن أعمدة، وتكمن المشكلة في كون الأطوال مُقرّبة إلى أقرب بوصة inch ثم حُوِّلت إلى سنتيمترات، وبعدها قُرِّبت مرةً أخرى، وبالتالي ققد ضاعت بعض المعلومات بسبب العمليات السابقة.
</p>

<p>
	لا يمكننا استرجاع المعلومات المفقودة في الواقع، إلّا أنه يمكننا تقليل الأثر على مخططات الانتشار عن طريق عشوائية (أو قلقلة jittering) البيانات، أي إضافة ضجيج عشوائي عليها لعكس أثر التقريب.
</p>

<p>
	بما أنه طُبِّقَت عملية تقريب لأقرب بوصة على هذه القيم، فمن المحتمل أن تكون بعيدةً عن القيم الأصلية بمقدار 0.5 بوصة أو 1.3 سنتيمتر، وكذلك الأمر بالنسبة للأوزان التي يمكن أن تكون بعيدةً عن القيم الأصلية بمقدار 0.5 كيلوغرامًا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_14" style="">
<span class="pln">heights </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Jitter</span><span class="pun">(</span><span class="pln">heights</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.3</span><span class="pun">)</span><span class="pln">
weights </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Jitter</span><span class="pun">(</span><span class="pln">weights</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">)</span></pre>

<p>
	إليك تنفيذ التابع <code>Jitter</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_16" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Jitter</span><span class="pun">(</span><span class="pln">values</span><span class="pun">,</span><span class="pln"> jitter</span><span class="pun">=</span><span class="lit">0.5</span><span class="pun">):</span><span class="pln">
    n </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">values</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(-</span><span class="pln">jitter</span><span class="pun">,</span><span class="pln"> </span><span class="pun">+</span><span class="pln">jitter</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> values</span></pre>

<p>
	يمكن أن تنتمي القيم إلى أي تسلسل لكن ستكون النتيجة مصفوفة NumPy حتمًا.
</p>

<p>
	يُظهر الشكل السابق في الجهة اليمنى النتيجة، حيث تقلل العشوائية jittering الأثر المرئي للتقريب ويوضِّح شكل العلاقة، لكن من المهم الانتباه إلى وجوب اللجوء إلى قلقلة (عشوائية) البيانات في حال كنت تريد عرضها فقط، كما يجب الابتعاد عن استخدام البيانات العشواء (المُقلقلة) من أجل التحليل، ولكن مع ذلك فلا يُعَدّ التذبذب أفضل طريقة لتمثيل البيانات، حيث يوجد العديد من النقاط المتداخلة التي تخفي البيانات في الأجزاء الكثيفة من الشكل وتعطي تركيزًا غير متناسب على القيم الشاذة، ويُدعى هذا التأثير بالإشباع saturation.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="83429" href="https://academy.hsoub.com/uploads/monthly_2021_11/61a117904ac57_7.2.png.0b26b480b8dd4d09a222d88e2e6619e0.png" rel=""><img alt="الشكل 7.2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="83429" data-unique="9bjy8sjf1" src="https://academy.hsoub.com/uploads/monthly_2021_11/61a117904ac57_7.2.png.0b26b480b8dd4d09a222d88e2e6619e0.png"></a>
</p>

<p>
	يوضِّح الشكل السابق مخطط الانتشار مع عشوائية وشفافية في الجهة اليسرى، ومخطط هيكسبين في الجهة اليمنى.
</p>

<p>
	يمكننا حل هذه المشكلة باستخدام المعامِل <code>alpha</code> الذي يجعل النقاط شفافةً إلى حد ما، وتكون التعليمة الموافقة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_18" style="">
<span class="pln">thinkplot</span><span class="pun">.</span><span class="typ">Scatter</span><span class="pun">(</span><span class="pln">heights</span><span class="pun">,</span><span class="pln"> weights</span><span class="pun">,</span><span class="pln"> alpha</span><span class="pun">=</span><span class="lit">0.2</span><span class="pun">)</span></pre>

<p>
	يُظهِر الشكل السابق في الجهة اليسرى النتيجة، حيث تبدو نقاط البيانات المتداخلة أقتم من غيرها، أي يتناسب القتامة darkness مع الكثافة.
</p>

<p>
	نرى في هذا المخطط تفصيلِين اثنين لم يظهرا سابقًا، حيث يكون التفصيل الأول هو عناقيد عمودية عند أطوال مختلفة، والتفصيل الثاني هو خط أفقي قريب من الوزن 90 كيلوغرام أو 200 رطل.
</p>

<p>
	بما أن هذه البيانات تستند إلى تقارير ذاتية بالأرطال، فمن المرجَّح أن بعض المستجيبين قد طبقوا عملية تقريب على القيم. عادةً ما تكون الشفافية مناسبةً لمجموعات البيانات متوسطة الحجم، إلا أنّ هذا الشكل لا يُظهر سوى أول 5000 سجل في BRFSS من أصل 414509 سجل.
</p>

<p>
	يُعَدّ مخطط هيكسبين hexbin plot أحد الخيارات المطروحة للتعامل مع مجموعات البيانات الأكبر حجمًا، فهو يقسم المخطط graph إلى صناديق سداسية، ويلوِّن كل صندوق بلون مختلف حسب عدد نقاط البيانات الموجودة فيه، كما توفِّر <code>thinkplot</code> التابع <code>HexBin</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_20" style="">
<span class="pln">   thinkplot</span><span class="pun">.</span><span class="typ">HexBin</span><span class="pun">(</span><span class="pln">heights</span><span class="pun">,</span><span class="pln"> weights</span><span class="pun">)</span></pre>

<p>
	يُظهر الشكل السابق في الجهة اليمنى النتيجة، وتتمثل إحدى ميّزات مخطط هيكسبين في توضيح شكل العلاقة جيدًا، كما أنه فعّال في حالة مجموعات البيانات الكبيرة بالنسبة للزمن ولحجم الملف الذي يولده، إلّا أنه لا يُظهر القيم الشاذة.
</p>

<p>
	استعرضنا هذا المثال لهدف أساسي ألا وهو توضيح عدم سهولة إنشاء مخطط انتشار يوضِّح العلاقات دون ظهور عناصر مضلّلة.
</p>

<h2>
	توصيف العلاقات
</h2>

<p>
	تُعطينا مخططات الانتشار انطباعًا عامًا عن العلاقة بين المتغيرات، إلّا أنه يوجد أنواع أخرى من المخططات التي تزودنا بمعلومات أكثر تفصيلًا عن طبيعة العلاقة، إذ يمكننا مثلًا فرز أو تصنيف متغير واحد ورسم مئين percentile المتغير الآخر.
</p>

<p>
	تزوّدنا مكتبتي نمباي NumPy وبانداز pandas بدوال لتصنيف البيانات binning data كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_22" style="">
<span class="pln">df </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">dropna</span><span class="pun">(</span><span class="pln">subset</span><span class="pun">=[</span><span class="str">'htm3'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'wtkg2'</span><span class="pun">])</span><span class="pln">
bins </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">arange</span><span class="pun">(</span><span class="lit">135</span><span class="pun">,</span><span class="pln"> </span><span class="lit">210</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
indices </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">digitize</span><span class="pun">(</span><span class="pln">df</span><span class="pun">.</span><span class="pln">htm3</span><span class="pun">,</span><span class="pln"> bins</span><span class="pun">)</span><span class="pln">
groups </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">groupby</span><span class="pun">(</span><span class="pln">indices</span><span class="pun">)</span></pre>

<p>
	تحذف <code>dropna</code> الأسطر التي تحوي قيمة <code>nan</code> -أي ليس عددًا- في أيّ عمود مُدرَج، وتنشئ الدالة <code>arange</code> مصفوفة نمباي NumPy تحوي صناديق bins من 135 إلى 210 دون احتساب القيمة 210 بفارق 5 بين الصندوق والآخر، كما تحسب <code>digitize</code> فهرس الصندوق الذي يحوي كل قيمة في <code>df.htm3</code>، وتكون النتيجة مصفوفة نمباي NumPy من فهارس الأعداد الصحيحة، بحيث تكون فهارس القيم التي تقل عن أصغر صندوق هي 0، في حين تكون فهارس القيم التي تزيد عن أعلى صندوق هي <code>len(bins)</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="83430" href="https://academy.hsoub.com/uploads/monthly_2021_11/61a117919b45b_7.3.png.55732fc83d7b3cf1624a61d7c634dcae.png" rel=""><img alt="الشكل 7.3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="83430" data-unique="zrngsungk" src="https://academy.hsoub.com/uploads/monthly_2021_11/61a117919b45b_7.3.png.55732fc83d7b3cf1624a61d7c634dcae.png"></a>
</p>

<p>
	يوضِّح الشكل السابق قيم المئين للوزن بمجال صناديق الأطوال. يُعيد تابع من إطار البيانات <code>groupby</code> كائن GroupBy وهو يُستخدَم في حلقة <code>for</code>؛ أما التابع <code>groups</code> فهو يمر بالترتيب على أسماء المجموعات في أُطُر البيانات التي تمثّلها، أي يمكننا مثلًا طباعة عدد الأسطر في كل مجموعة بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_25" style="">
<span class="kwd">for</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> group </span><span class="kwd">in</span><span class="pln"> groups</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">i</span><span class="pun">,</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">group</span><span class="pun">))</span></pre>

<p>
	يمكننا الآن حساب متوسط الطول لكل مجموعة بالإضافة إلى <a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D8%AA%D8%B1%D8%A7%D9%83%D9%85%D9%8A-cumulative-distribution-functions-r1331/" rel="">دالة التوزيع التراكمي</a> للوزن:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_27" style="">
<span class="pln">heights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">group</span><span class="pun">.</span><span class="pln">htm3</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> group </span><span class="kwd">in</span><span class="pln"> groups</span><span class="pun">]</span><span class="pln">
cdfs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">group</span><span class="pun">.</span><span class="pln">wtkg2</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> group </span><span class="kwd">in</span><span class="pln"> groups</span><span class="pun">]</span></pre>

<p>
	يمكننا أخيرًا رسم قيم المئين للوزن مقابل الطول كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_32" style="">
<span class="kwd">for</span><span class="pln"> percent </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">[</span><span class="lit">75</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">]:</span><span class="pln">
    weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">cdf</span><span class="pun">.</span><span class="typ">Percentile</span><span class="pun">(</span><span class="pln">percent</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> cdf </span><span class="kwd">in</span><span class="pln"> cdfs</span><span class="pun">]</span><span class="pln">
    label </span><span class="pun">=</span><span class="pln"> </span><span class="str">'%dth'</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> percent
    thinkplot</span><span class="pun">.</span><span class="typ">Plot</span><span class="pun">(</span><span class="pln">heights</span><span class="pun">,</span><span class="pln"> weights</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="pln">label</span><span class="pun">)</span></pre>

<p>
	يُظهر الشكل السابق النتيجة، حيث تكون العلاقة بين المتغيرات من 140 إلى 200 سنتيمتر خطيّةً تقريبًا، حيث يحوي هذا المجال أكثر من نسبة 99% من البيانات، لذا ليس علينا القلق بشأن القيم المتطرفة.
</p>

<h2>
	الارتباط Correlation
</h2>

<p>
	الارتباط هو إحصائيّة هدفها تحديد قوة العلاقة بين متغيرَين، لكن في أغلب الأحيان تختلف واحدات قياس الارتباط بين المتغيرات التي نرغب بموازنتها، مما يخلق لنا تحديًا يواجهنا عند قياس الارتباط، وفي الواقع يكون مصدر هذه المتغيرات غالبًا توزيعات مختلفة حتى عندما تمتلك واحدت القياس نفسها.
</p>

<p>
	فيما يلي بعض الحلول الشائعة لهذه المشاكل:
</p>

<ol>
<li>
		حوِّل كل قيمة إلى درجة معيارية standard score التي هي عدد الانحرافات المعيارية عن المتوسط، حيث ينتج عن هذا التحويل "معامل ارتباط بيرسون الناتج عن العزوم".
	</li>
	<li>
		حوِّل كل قيمة إلى رتبتها rank التي هي الفهرس الخاص بها في القائمة المرتبة من القيم، حيث ينتج عن هذا التحويل مُعامل ارتباط سبيرمان Spearman rank correlation coefficient.
	</li>
</ol>
<p>
	إذا كانت X سلسلةً series من <code>n</code> قيمة وكل قيمة فيها هي x<sub>i</sub>، فسيمكننا تحويلها إلى درجاتها المعيارية عن طريق طرح المتوسط منها والتقسيم على الانحراف المعياري، بحيث تكون المعادلة بالصورة: z<sub>i</sub>=(x<sub>i</sub>-μ)/σ ، مع العلم أنّ البسط هو انحراف المسافة عن المتوسط، وتؤدي القسمة على σ إلى تقييس الانحراف standardizes the deviation، وبالتالي تكون قيم Z بلا أبعاد -أي ليس لها واحدات قياس- ويكون متوسط توزيعها مساوويًا للصفر وتباينه مساويًا للواحد.
</p>

<p>
	إذا كان توزيع قيم X طبيعيًا، فسيكون توزيع قيم Z طبيعيًا أيضًا، لكن إذا كان X متجانفًا skewed أو يحوي قيمًا شاذةً، فسيكون Z مثل X، وفي هذه الحالات يكون استخدام رتب المئين percentile ranks أكثر متانةً، لكن إذا حسبنا متغيرًا جديدًا هو R بحيث يكون r<sub>i</sub> رتبة x<sub>i</sub>، فسيكون توزيع R موحَّدًا uniform من 1 إلى n بغض النظر عن ماهية توزيع X.
</p>

<h2>
	التغاير Covariance
</h2>

<p>
	يُعَدّ التغاير مقياسًا لمَيل المتغيرين إلى الاختلاف معًا بحيث إذا كان لدينا سلسلتين X وY، فسيكون انحرافهما عن المتوسط كما يلي:
</p>

<ul>
<li>
		dx<sub>i</sub>=x<sub>i</sub>-x̄
	</li>
	<li>
		dy<sub>i</sub>=y<sub>i</sub>-ȳ
	</li>
</ul>
<p>
	بحيث تكون x̄ متوسط عيّنة X وȳ هي متوسط عيّنة Y، وإذا كانت العيّنتان X وY متغايرتان معًا، فسيملك انحرافهما الإشارة ذاتها.
</p>

<p>
	إن ضربنا انحرافي العيّنتين ببعضهما، فسيكون الناتج موجبًا في حال كان لهما الإشارة ذاتها، في حين سيكون سالبًا إذا كان لهما إشارة متعاكسة، لذا يمكننا القول أنّ جمع النواتج يعطي قياسًا لميل العيّنتين للتغاير معًا.
</p>

<p>
	يكون التغاير هو متوسط هذه النواتج:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium"><span style="font-style:italic">Cov</span>(<span style="font-style:italic">X</span>,<span style="font-style:italic">Y</span>) = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-size:xx-large">∑</span><span style="font-style:italic">dx</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> <span style="font-style:italic">dy</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	حيث يكون <code>n</code> طول السلسلتين ويجب أن يكون لهما الطول نفسه.
</p>

<p>
	إذا درستَ الجبر الخطي، لا بد أنّك تدرك أن <code>Cov</code> هي حاصل الضرب القياسي dot product للانحرافات مقسومًا على طولها، لذا يكون التغاير في حده الأقصى إذا كان المتجهان متطابقَين تمامًا، و0 إذا كانا متعامدين، وسالبًا إذا أشارا إلى اتجاهين متعاكسين.
</p>

<p>
	تزوِّدنا <code>thinkstats2</code> بالتابع <code>np.dot</code> لتنفيذ <code>Cov</code> تنفيذًا فعالًا، وإليك الشيفرة الموافقة لذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_34" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Cov</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">,</span><span class="pln"> meanx</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> meany</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">):</span><span class="pln">
    xs </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">asarray</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    ys </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">asarray</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> meanx </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">:</span><span class="pln">
        meanx </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> meany </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">:</span><span class="pln">
        meany </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">)</span><span class="pln">

    cov </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">dot</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">-</span><span class="pln">meanx</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">-</span><span class="pln">meany</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cov</span></pre>

<p>
	يحسب <code>Cov</code> في الحالة الافتراضية الانحرافات من متوسطات العيّنة، أو بإمكانك تزويده بالمتوسطات المعلومة.
</p>

<p>
	إذا كانتا <code>xs</code> و<code>ys</code> تسلسلي <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون</a>، فسيحوِّلهما التابع <code>np.asarray</code> إلى مصفوفتي نمباي NumPy، وبطبيعة الحال لا يغيّر <code>np.asarray</code> شيئًا إذا كانتا <code>xs</code> و<code>ys</code> مصفوفتي نمباي NumPy.
</p>

<p>
	تقصّدنا أن يكون تنفيذ التغاير هذا بسيطًا لأنّ هدفنا هو الشرح فحسب، كما توفر كل من نمباي NumPy وبانداز pandas أيضًا تنفيذات للتغاير لكن كلاهما يطبِّق تصحيحًا لأحجام العينات الصغيرة التي لم نحوِّلها بعد، كما تُعيد <code>np.cov</code> مصفوفة التغاير covariance matrix التي تكفينا الآن.
</p>

<h2>
	ارتباط بيرسون Pearson’s correlation
</h2>

<p>
	يُعَدّ التغاير مفيدًا في بعض الحسابات، ولكن نادرًا ما يتم وضعه في الإحصائيات الموجزة لأنه من الصعب تفسيره، فهو يعاني من بعض المشاكل منها أنّ واحدة قياسه هي ناتج واحدات X و Y. فمثلًا، يكون تغاير الطول والوزن في BRFSS هو 113 كيلوغرام-سنتيمترات على الرغم أنها ليست منطقية تمامًا.
</p>

<p>
	يمكن حل هذه المشكلة بعدة طرق منها تقسيم الانحرافات على الانحراف المعياري التي تحقق درجات معيارية وتحسب ناتج درجات معيارية كما يلي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">p</span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">(<span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − <span style="text-decoration:overline">x</span>)</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">S</span><sub><span style="font-style:italic;font-size:medium">X</span></sub>
</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">(<span style="font-style:italic">y</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − ȳ)</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">S</span><sub><span style="font-style:italic;font-size:medium">Y</span></sub>
</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	يكون S<sub>X</sub> وS<sub>Y</sub> الانحرافَين المعياريَين لكل من <code>X</code> و<code>Y</code>، كما يكون متوسط هذه النواتج كما يلي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium">ρ = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-size:xx-large">∑</span><span style="font-style:italic">p</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	يمكننا إعادة كتابة ρ عن طريق أخذS<sub>X</sub> وS<sub>Y</sub> في الحسبان لينتج لدينا المعادلة التالية:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium">ρ = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"><span style="font-style:italic">Cov</span>(<span style="font-style:italic">X</span>,<span style="font-style:italic">Y</span>)</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">S</span><sub><span style="font-style:italic;font-size:medium">X</span></sub><span style="font-size:medium"> <span style="font-style:italic">S</span></span><sub><span style="font-style:italic;font-size:medium">Y</span></sub>
</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	سميت هذه القيمة بارتباط بيرسون Pearson’s correlation تيمّنًا بكارل بيرسون عالم الإحصاء الرائد، وفي الواقع فمن السهل حسابه وتفسيره أيضًا لأنّ الدرجات المعيارية وρ بلا أبعاد.
</p>

<p>
	إليك التنفيذ في <code>thinkstats2</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_39" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Corr</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">):</span><span class="pln">
    xs </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">asarray</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    ys </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">asarray</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">)</span><span class="pln">

    meanx</span><span class="pun">,</span><span class="pln"> varx </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MeanVar</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    meany</span><span class="pun">,</span><span class="pln"> vary </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MeanVar</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">)</span><span class="pln">

    corr </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Cov</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">,</span><span class="pln"> meanx</span><span class="pun">,</span><span class="pln"> meany</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">(</span><span class="pln">varx </span><span class="pun">*</span><span class="pln"> vary</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> corr</span></pre>

<p>
	يحسب <code>MeanVar</code> المتوسط والتباين بصورة فعّالة أكثر من الاستدعاء المنفصل للتابعين <code>np.mean</code> و<code>np.var</code>.
</p>

<p>
	دائمًا ما يكون ارتباط بيرسون بين القيمتين 1- و 1+ متضمنًا هاتين القيمتين، وإذا كان ρ موجبًا فنقول أنّ الارتباط موجب ويعني هذا أنه إذا كانت قيمة أحد المتغيرَين عالية، فستكون قيمة الآخر عاليةً أيضًا؛ أما إذا كان ρ سالبًا فنقول أنّ الارتباط سالب ويعني هذا أنه إذا كانت قيمة أحد المتغيرَين عالية، فستكون قيمة الآخر منخفضةً.
</p>

<p>
	يشير حجم ρ إلى قوة الارتباط، حيث إذا كانت تساوي 1 أو 1- فسيكون المتغيرين مرتبطَين تمامًا، مما يعني أنه إذا كنت تعرف أحد المتغيرين فسيصبح بإمكانك تنبؤ الآخر بصورة صحيحة.
</p>

<p>
	على الرغم من أن معظم الارتباطات في العالم الحقيقي غير مثالية إلا أنها مفيدة، كما أنّ الارتباط بين الطول والوزن هو 0.51 والذي يُعَدّ ارتباطًا قويًا موازنةً بالمتغيرات المماثلة المتعلقة بالإنسان.
</p>

<h2>
	العلاقات اللاخطية Nonlinear relationships
</h2>

<p>
	قد نعتقد أنه لا يوجد علاقة بين المتغيرات إذا كان مُعامِل ارتباط بيرسون يقارب الصفر، إلا أنّ هذا ليس صحيحًا، حيث يقيس ارتباط بيرسون العلاقات الخطية فقط، وفي حال وجود علاقة لاخطية فلا يقيس ρ قوتها قياسًا صحيحًا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="83431" href="https://academy.hsoub.com/uploads/monthly_2021_11/61a11792c846c_7.4.png.7c61108912a0dbd5d31039fcc94d8574.png" rel=""><img alt="الشكل 7.4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="83431" data-unique="e4z0y6gv6" src="https://academy.hsoub.com/uploads/monthly_2021_11/61a11792c846c_7.4.png.7c61108912a0dbd5d31039fcc94d8574.png"></a>
</p>

<p>
	يوضِّح الشكل السابق أمثلةً عن مجموعات البيانات مع مجال متنوع من الارتباطات فيما بينها، ومصدر هذا الشكل من صفحة <a href="http://wikipedia.org/wiki/Correlation_and_dependence" rel="external nofollow">Correlation</a>، حيث يُظهِر مخططات الانتشار ومعامِلات الارتباطات لعدة مجموعات بيانات مبنيّة بعناية.
</p>

<p>
	يُظهِر الصف العلوي العلاقات الخطية مع مجال من الارتباطات، علمًا أنه يمكنك استخدام هذا الصف لمعرفة كيف تبدو القيم المختلفة لـ ρ؛ أمّا الصف الثاني فيُظهر ارتباطات مثاليّة مع مجال متنوع من قيم الميل، مما يشير إلى أنّ الارتباط لا علاقة له بالميل -وسنتحدث عن تقدير الميل قريبًا-، كما يُظهِر الصف الثالث متغيرات مرتبطة ارتباطًا واضحًا، ولكن معامِل الارتباط هو 0 نظرًا لكَون العلاقة لاخطيةً.
</p>

<p>
	يمكننا القول أنّ المغزى من هذه القصة هو أنه عليك الاطلاع على مخطط انتشار بياناتك قبل حساب معامِل الارتباط دون الانتباه لأي شيء.
</p>

<h2>
	معامِل ارتباط سبيرمان حسب الرتب
</h2>

<p>
	يؤدي مُعامِل بيرسون عمله جيّدًا إن كانت العلاقات بين المتغيرات خطية وإذا كانت المتغيرات طبيعيةً إلى حد ما، إلا أنه ليس متينًا في حال وجود قيم شاذة.
</p>

<p>
	يعَدّ معامِل ارتباط سبيرمان حسب الرتب Spearman’s rank correlation بديلًا يخفف من تأثير القيم الشاذة والتوزيعات المتجانفة skewed distributions، إذ يمكننا حساب ارتباط سبيرمان عن طريق حساب رتبة كل قيمة والتي هي فهرس القيمة في العيّنة المرتّبة. فمثلًا، لدينا فتكون رتبة القيمة 5 في العيّنة [7, 5, 2, 1] هي 3 لأن ترتيبها في القائمة المرتبة هو الثالث، ومن ثم نحسب ارتباط بيرسون لهذه الرُتب.
</p>

<p>
	تزودنا <code>thinkstats2</code> بدالة تحسب معامِل ارتباط سبيرمان للرتب كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_41" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">SpearmanCorr</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">):</span><span class="pln">
    xranks </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">Series</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">).</span><span class="pln">rank</span><span class="pun">()</span><span class="pln">
    yranks </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">Series</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">).</span><span class="pln">rank</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">Corr</span><span class="pun">(</span><span class="pln">xranks</span><span class="pun">,</span><span class="pln"> yranks</span><span class="pun">)</span></pre>

<p>
	حوَّلنا الوسائط arguments إلى كائنات سلسلة بانداز pandas Series لكي نستطيع استخدَام <code>rank</code> وهي تحسب رتبة كل قيمة وتُعيد سلسلةً، ومن ثم استخدمنا <code>Corr</code> لحساب ارتباط الرتب.
</p>

<p>
	كما يمكننا أيضًا استخدام <code>Series.corr</code> مباشرةً ومن ثم تحديد تابع سبيرمان كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_43" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">SpearmanCorr</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">):</span><span class="pln">
    xs </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">Series</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    ys </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">Series</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> xs</span><span class="pun">.</span><span class="pln">corr</span><span class="pun">(</span><span class="pln">ys</span><span class="pun">,</span><span class="pln"> method</span><span class="pun">=</span><span class="str">'spearman'</span><span class="pun">)</span></pre>

<p>
	مع العلم أن معامِل ارتباط سبيرمان للرتب لبيانات BRFSS هي 0.54، وهي أعلى بقليل من ارتباط بيرسون المساوية لـ 0.51، إذ يوجد هناك عدة أسباب وراء هذا الفرق منها:
</p>

<ul>
<li>
		إذا كانت العلاقة غير خطية فعادةً ما يقلل ارتباط بيرسون من قوة العلاقة.
	</li>
	<li>
		يمكن أن يتأثر ارتباط بيرسون -في أيّ اتجاه- إذا كان أحد التوزيعين متجانفًا أو يحتوي على قيم متطرفة، حيث تُعَدّ معامِل ارتباط سبيرمان للرتب أكثر متانةً من ارتباط بيرسون.
	</li>
</ul>
<p>
	نعلم أنه في مثال BRFSS يكون توزيع الأوزان لوغاريتميًا طبيعيًا تقريبًا، أي أنه في حال كان التحويل لوغاريتميًّا فهو يقارب توزيعًا طبيعيًا لا تجانف فيه، كما يمكن أيضًا إلغاء أثر التجانف عن طريق حساب ارتباط بيرسون بتطبيق لوغاريتم على الوزن والطول، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6333_46" style="">
<span class="pln">thinkstats2</span><span class="pun">.</span><span class="typ">Corr</span><span class="pun">(</span><span class="pln">df</span><span class="pun">.</span><span class="pln">htm3</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">df</span><span class="pun">.</span><span class="pln">wtkg2</span><span class="pun">)))</span></pre>

<p>
	تكون النتيجة هي 0.53 وهي قريبة من معامِل ارتباط سبيرمان التي تقدر قيمتها بـ 0.54، أي أنها تفترض أن التجانف في توزيع الأوزان يفسّر أغلب الفروق بين ارتباط بيرسون وارتباط سبيرمان.
</p>

<h2>
	الارتباط والسببية
</h2>

<p>
	إذا كان المتغيران A وB مرتبطين فسيكون لدينا ثلاثة تفسيرات وهي أنّ A تسبب B أو B تسبب A أو مجموعة أخرى من العوامل تسبب كلاً من A وB، وتدعى هذه التفسيرات بالعلاقات السببية causal relationships.
</p>

<p>
	لا يُميِّز الارتباط لوحده بين هذه التفسيرات، أي أنها لا تعطينا فكرة عن أيّ منها هو الصحيح، وغالبًا ما تُلخَّص هذه القاعدة بما يلي: "الارتباط لا يقتضي السببية" وهو قول بليغ لدرجة أنّ له صفحة <a href="https://ar.wikipedia.org/wiki/%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7_%D9%84%D8%A7_%D9%8A%D9%82%D8%AA%D8%B6%D9%8A_%D8%A7%D9%84%D8%B3%D8%A8%D8%A8%D9%8A%D8%A9" rel="external nofollow">ويكيبيديا خاصة به</a>.
</p>

<p>
	إذًا ماذا يمكنك أن تفعل لكي تقدِّم دليلًا على السببيّة؟
</p>

<ol>
<li>
		استخدِم زمنًا: إذا أتى المتغير A قبل B فيعني هذا أنّ A سبّب B وليس العكس -وهذا على الأقل حسب فهمنا الشائع للسببية-، حيث يساعدنا ترتيب الأحداث في استنتاج اتجاه السببية، لكنه لا يستبعد احتمال أن يتسبب شيء آخر في حدوث كل من A وB.
	</li>
	<li>
		استخدِم عشوائيةً: إذا قسمّتَ عينةً كبيرةً إلى مجموعتين عشوائيًا وحسبت متوسط أيّ متغير تقريبًا فستتوقع أن الفرق سيكون صغيرًا، وإذا كانت المجموعات متطابقةً تقريبًا في جميع المتغيرات ما عدا متغير واحد، فسيمكنك عندئذ استبعاد العلاقات الزائفة، وهذه الطريقة مناسبة حتى لو لم تعلم ما هي المتغيرات ذات الصلة، لكن من الأفضل أن تكون على علم بهذا لأنك تستطيع عندها التحقق فيما إذا كانت المجموعات متطابقةً أم لا.
	</li>
</ol>
<p>
	كانت هذه الأفكار هي الدافع وراء ما يُعرف <a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%B1%D8%A8%D8%A9_%D9%85%D9%86%D8%B6%D8%A8%D8%B7%D8%A9_%D9%85%D8%B9%D8%B4%D8%A7%D8%A9" rel="external nofollow">بالتجربة العشوائية المنتظمة</a> randomized controlled trial، التي يتم فيها إسناد المشاركِين إلى مجموعتين -أو أكثر-: مجموعة العلاج treatment group التي تتلقى علاجًا أو تدخّلًا من نوع ما مثل دواء جديد، ومجموعة الموازنة أو <a href="https://ar.wikipedia.org/wiki/%D9%85%D8%AC%D9%85%D9%88%D8%B9%D8%A9_%D9%85%D8%B1%D8%AC%D8%B9%D9%8A%D8%A9" rel="external nofollow">المجموعة المرجعية</a> control group التي لا تتلقى أيّ علاج أو تتلقى علاجًا أثره معروف مسبقًا.
</p>

<p>
	تُعَدّ التجربة المنتظمة التي تستخدم عينات عشوائية الطريقة الأكثر موثوقية لإثبات العلاقة السببية، وهي أساس الطب القائم على العلم انظر إلى صفحة <a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%B1%D8%A8%D8%A9_%D9%85%D9%86%D8%B6%D8%A8%D8%B7%D8%A9_%D9%85%D8%B9%D8%B4%D8%A7%D8%A9" rel="external nofollow">الويكيبيديا</a>.
</p>

<p>
	لكن لسوء الحظ، فإن التجارب العشوائية المنتظمة ليست ممكنةً إلا في العلوم المختبرية والطب وعدد قليل من التخصصات الأخرى، حيث نادرًا ما تحدث في العلوم الاجتماعية لأنها مستحيلة أو غير أخلاقية.
</p>

<p>
	يتمثَّل أحد البدائل في البحث عن تجربة طبيعية natural experiment، حيث تتلقى مجموعات متشابهة علاجات مختلفة، وأحد مخاطر التجارب الطبيعية هو أنّ المجموعات قد تكون مختلفةً بطرق غير واضحة لنا، ويمكنك قراءة المزيد عن هذا الموضوع <a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%B1%D8%A8%D8%A9_%D8%B7%D8%A8%D9%8A%D8%B9%D9%8A%D8%A9" rel="external nofollow">هنا</a>.
</p>

<p>
	يمكننا في بعض الأحيان استنتاج العلاقات السببية باستخدام تحليل الانحدار regression analysis، وهو موضوع الفصل الحادي عشر.
</p>

<h2>
	تمارين
</h2>

<p>
	يوجد حل هذا التمرين في <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/chap07soln.py" rel="external nofollow">chap07soln.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h3>
	التمرين الأول
</h3>

<p>
	استخدِم بيانات المسح الوطني لنمو الأسرة من أجل إنشاء مخطط انتشار لأوزان الولادات مقابل عمر الأم، ومن ثم ارسم قيم مئين أوزان الولادات مقابل عمر الأم، واحسب مُعامِل ارتباط بيرسون ومُعامِل ارتباط سبيرمان، وكيف تصف العلاقة بين هذه المتغيرات؟
</p>

<p>
	ترجمة -وبتصرف- للفصل <a href="https://greenteapress.com/thinkstats2/html/thinkstats2008.html" rel="external nofollow">Chapter 7 Relationships between variables analysis</a> من كتاب <a href="https://greenteapress.com/wp/think-stats-2e" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D9%83%D8%B4%D8%A7%D9%81%D9%8A%D8%A9-%D9%84%D8%A5%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B8%D8%B1%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-r1246/" rel="">تحليل البيانات الاستكشافية لإثبات النظريات الإحصائية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1303/" rel="">دوال الكتلة الاحتمالية في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">التوزيعات الإحصائية في بايثون</a>
	</li>
</ul>
<style type="text/css">
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
td p{margin:0px;}
.vbar{border:none;width:2px;background-color:black;}
.hbar{display: block;border:none;height:2px;width:100%;background-color:black;}
.display{border-collapse:separate;border-spacing:2px;width:auto;border:none;}
.dcell{white-space:nowrap;padding:0px; border:none;}
.dcenter{margin:0ex auto;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
table{border-collapse:collapse;}
td{padding:0;}
.cellpadding0 tr td{padding:0;}
.cellpadding1 tr td{padding:1px;}
.center{text-align:center;margin-left:auto;margin-right:auto;}</style>
]]></description><guid isPermaLink="false">1381</guid><pubDate>Tue, 30 Nov 2021 16:08:00 +0000</pubDate></item><item><title>&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x643;&#x62B;&#x627;&#x641;&#x629; &#x627;&#x644;&#x627;&#x62D;&#x62A;&#x645;&#x627;&#x644;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AB%D8%A7%D9%81%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1335/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_10/6158a66d1cfa0_--.png.08f56094c6440d4a0b89aedaf1b8f4f2.png" /></p>

<p>
	توجد الشيفرة الخاصة بهذا الفصل في ملف <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/density.py" rel="external nofollow">density.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h2>
	دوال الكثافة الاحتمالية probability density functions
</h2>

<p>
	يمكن تعريف دالة الكثافة الاحتمالية probability density function -أو PDF اختصارًا- على أنها مشتق دالة التوزيع التراكمي cumulative distribution function -أو CDF اختصارًا-، وتكون الصيغة الرياضية على سبيل المثال لدالة الكثافة الاحتمالية الخاصة بالتوزيع الأسي exponential distribution هي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">PDF</span><sub><span style="font-style:italic;font-size:medium">expo</span></sub><span style="font-size:medium">(<span style="font-style:italic">x</span>) = λ <span style="font-style:italic">e</span></span><sup><span style="font-size:medium">−λ <span style="font-style:italic">x</span></span></sup><span style="font-size:medium">   </span>
			</td>
		</tr></tbody></table>
<p>
	كما تكون الصيغة الرياضية لدالة الكثافة الاحتمالية الخاصة بالتوزيع الطبيعي normal distribution هي:
</p>
<style type="text/css">
div table{margin-left:inherit;margin-right:inherit;margin-bottom:2px;margin-top:2px}
td p{margin:0px;}
.vbar{border:none;width:2px;background-color:black;}
.hbar{display: block;border:none;height:2px;width:100%;background-color:black;}
.display{border-collapse:separate;border-spacing:2px;width:auto;border:none;}
.dcell{white-space:nowrap;padding:0px; border:none;}
.dcenter{margin:0ex auto;}
.theorem{text-align:left;margin:1ex auto 1ex 0ex;}
table{border-collapse:collapse;}
td{padding:0;}
.cellpadding0 tr td{padding:0;}
.cellpadding1 tr td{padding:1px;}
.center{text-align:center;margin-left:auto;margin-right:auto;}</style>
<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">PDF</span><sub><span style="font-style:italic;font-size:medium">normal</span></sub><span style="font-size:medium">(<span style="font-style:italic">x</span>) = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<table class="display"><tbody><tr style="vertical-align:middle">
<td class="dcell">
												<span style="font-size:medium">σ </span>
											</td>
											<td class="dcell">
												<span style="font-size:x-large">√</span>
											</td>
											<td class="dcell">
												<table class="cellpadding0" style="border:0;border-spacing:1;border-collapse:separate;"><tbody>
<tr>
<td class="hbar">
																 
															</td>
														</tr>
<tr>
<td style="text-align:center;white-space:nowrap">
																<span style="font-size:medium">2 π</span>
															</td>
														</tr>
</tbody></table>
</td>
										</tr></tbody></table>
</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium">  exp</span>
			</td>
			<td class="dcell">
				<span style="font-size:medium">⎡<br>
				⎢<br>
				⎢<br>
				⎢<br>
				⎢<br>
				⎢<br>
				⎣</span>
			</td>
			<td class="dcell">
				<span style="font-size:medium">−</span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">2</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium">  </span>
			</td>
			<td class="dcell">
				<span style="font-size:medium">⎛<br>
				⎜<br>
				⎜<br>
				⎝</span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"><span style="font-style:italic">x</span> − µ</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">σ</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<span style="font-size:medium">⎞<br>
				⎟<br>
				⎟<br>
				⎠</span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:left">
								<span style="font-size:medium">2</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:left">
								<br><br>
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:left">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<span style="font-size:medium;">⎤<br>
				⎥<br>
				⎥<br>
				⎥<br>
				⎥<br>
				⎥<br>
				⎦</span>
			</td>
		</tr></tbody></table>
<p>
	وبطبيعة الحال، لا يفيدنا في أغلب الأحيان تقييم دالة الكثافة الاحتمالية لقيمة معيّنة مثل x، كما لا تكون النتيجة احتمالًا بل كثافة احتمالية.
</p>

<p>
	تُعرّف الكثافة في الفيزياء على أنها كتلة المادة لكل وحدة حجم، ومن أجل الحصول على الكتلة يجب أن نضرب بالحجم أو علينا إجراء تكامل مع الحجم في حال لم تكن الكثافة ثابتة، وكذلك فإنّ الكثافة الاحتمالية تقيس الاحتمال لكل وحدة x، لذا فمن أجل الحصول على كتلة احتمالية يجب إجراء تكامل مع x.
</p>

<p>
	يزوّدنا مستودع <code>thinkstats2</code> بصنف class يسمى Pdf يمثِّل دالة الكثافة الاحتمالية، كما يزوِّدنا كل كائن من Pdf بالتوابع التالية:
</p>

<ul>
<li>
		<code>Density</code> يأخذ هذا التابع قيمة x ويُعيد كثافة التوزيع عند x.
	</li>
	<li>
		<code>Render</code> يقيِّم هذا التابع الكثافة عند مجموعة متقطِّعة من القيم ويعيد زوجًا من التسلسلات sequences والتي هي <code>xs</code> أي القيم التي رُتّبت و<code>df</code> أي الكثافة الاحتمالية الخاصة بهذه القيم.
	</li>
	<li>
		<code>MakePmf</code> يقيِّم هذا التابع الكثافة عند مجموعة متقطّعة من القيم ويعيد صنف Pmf بعد توحيده بحيث يكون مقاربًا للصنف Pdf.
	</li>
	<li>
		<code>GetLinspace</code> يُعيد هذا التابع المجموعة الافتراضية من النقاط التي يستخدِمها كل من التابعَين <code>Render</code> و<code>MakePmf</code>
	</li>
</ul>
<p>
	يُعَدّ Pdf صنف أب مجرَّد abstract parent class أو صنفًا مورِّثًا -أي أن صنف ترثه عدة أصناف أخرى-، وتدلّ كلمة مجرَّد على عدم إمكانية استنساخه أي لا يمكن إنشاء كائن Pdf، وبالتالي علينا بدلًا عن ذلك تعريف صنف ابن يرث من الصنف Pdf ويعرِّف التابعَين <code>Density</code> و<code>GetLinspace</code>؛ أما التابعين <code>Render</code> و<code>MakePmf</code> فسيتكفّل الصنف Pdf بتعريفهما.
</p>

<p>
	يزوّدنا مستودع <code>thinkstats2</code> على سبيل المثال بصنف يُدعى <code>NormalPdf</code> يقيِّم دالة الكثافة الطبيعية، وتكون الشيفرة الموافقة له كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_8" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">NormalPdf</span><span class="pun">(</span><span class="typ">Pdf</span><span class="pun">):</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> mu</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> sigma</span><span class="pun">=</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">''</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">mu </span><span class="pun">=</span><span class="pln"> mu
        self</span><span class="pun">.</span><span class="pln">sigma </span><span class="pun">=</span><span class="pln"> sigma
        self</span><span class="pun">.</span><span class="pln">label </span><span class="pun">=</span><span class="pln"> label

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Density</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> scipy</span><span class="pun">.</span><span class="pln">stats</span><span class="pun">.</span><span class="pln">norm</span><span class="pun">.</span><span class="pln">pdf</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">mu</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">sigma</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">GetLinspace</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        low</span><span class="pun">,</span><span class="pln"> high </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">mu</span><span class="pun">-</span><span class="lit">3</span><span class="pun">*</span><span class="pln">self</span><span class="pun">.</span><span class="pln">sigma</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">mu</span><span class="pun">+</span><span class="lit">3</span><span class="pun">*</span><span class="pln">self</span><span class="pun">.</span><span class="pln">sigma
        </span><span class="kwd">return</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">linspace</span><span class="pun">(</span><span class="pln">low</span><span class="pun">,</span><span class="pln"> high</span><span class="pun">,</span><span class="pln"> </span><span class="lit">101</span><span class="pun">)</span></pre>

<p>
	يحتوي كائن الصنف <code>NormalPdf</code> على المعامِلَين <code>mu</code> و<code>sigma</code>، كما يستخدِم التابع <code>Density</code> الكائن <code>scipy.stats.norm</code> الذي يمثِّل توزيعًا طبيعيًا ويزوِّدنا بالتابعَين <code>cdf</code> و<code>pdf</code>، بالإضافة إلى العديد من التوابع الأخرى -ويمكنك الاطلاع على <a data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/programming/python/%D9%86%D9%85%D8%B0%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-modelling-distributions-r1332/" rel=""> نمذجة التوزيعات Modelling distributions</a>-.
</p>

<p>
	تُنشِئ الشيفرة الموجودة في المثال التالي الصنف <code>NormalPdf</code> مع المتوسط mean والتباين variance الخاصَّين بأطوال الإناث البالغات مقدَّرةً بالسنتيمتر ومأخوذةً من نظام مراقبة عوامل المخاطر السلوكية BRFSS، ومن ثم تحسب هي كثافة التوزيع في موقع يبعد انحرافًا معياريًا واحدًا عن المتوسط كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_12" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> mean</span><span class="pun">,</span><span class="pln"> var </span><span class="pun">=</span><span class="pln"> </span><span class="lit">163</span><span class="pun">,</span><span class="pln"> </span><span class="lit">52.8</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> std </span><span class="pun">=</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">(</span><span class="pln">var</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">NormalPdf</span><span class="pun">(</span><span class="pln">mean</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pdf</span><span class="pun">.</span><span class="typ">Density</span><span class="pun">(</span><span class="pln">mean </span><span class="pun">+</span><span class="pln"> std</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0.0333001</span></pre>

<p>
	تكون النتيجة حوالي 0.03 مقدَّرةً بواحدة كتلة احتمالية لكل سنتيمتر، كما نشدِّد على فكرة أنّ الكثافة الاحتمالية لا تعنينا لوحدها لكن إذا رسمنا الصنف <code>Pdf</code> كما يلي، فيمكننا رؤية شكل التوزيع:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_18" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> thinkplot</span><span class="pun">.</span><span class="typ">Pdf</span><span class="pun">(</span><span class="pln">pdf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'normal'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">()</span></pre>

<p>
	يرسم التابع <code>thinkplot.Pdf</code> الصنف <code>Pdf</code> على أساس دالة منتظمة smooth على عكس التابع <code>thinkplot.Pmf</code> الذي يرسم الصنف <code>Pmf</code> على أساس دالة خطوة، ويُظهِر الشكل التالي النتيجة بالإضافة إلى دالة الكثافة الاحتمالية المقدَّرة من عيّنة، والتي سنحسبها في القسم التالي.
</p>

<p>
	يمكننا استخدام التابع <code>MakePmf</code> من أجل إنشاء نسخة تقريبية من الصنف Pdf كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_20" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf </span><span class="pun">=</span><span class="pln"> pdf</span><span class="pun">.</span><span class="typ">MakePmf</span><span class="pun">()</span></pre>

<p>
	يحتوي الصنف Pmf الناتج على 101 نقطة افتراضيًا تبتعد عن بعضها بمسافات متساوية من mu-3<em>sigma إلى mu+3</em>sigma، ويمكن للتابعَين <code>MakePmf</code> و<code>Render</code> أخذ الوسطاء المفتاحية التالية: <code>low</code> و<code>high</code> و<code>n</code> بصورة اختيارية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78774" data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/uploads/monthly_2021_10/6158a6702e035_6.1.png.ede960fcb74715138df2f2a2a88a9207.png" rel=""><img alt="الشكل 6.1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78774" data-unique="1b43pm5f6" src="https://academy.hsoub.com/uploads/monthly_2021_10/6158a6702e035_6.1.png.ede960fcb74715138df2f2a2a88a9207.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة كثافة احتمالية طبيعية لنمذجة أطوال الإناث البالغات في الولايات المتحدة الأمريكية، وتقدير كثافة نواة العيّنة في حال كانت n=500.
</p>

<h2>
	تقدير كثافة النواة
</h2>

<p>
	يُعَد تقدير كثافة النواة Kernel density estimation -أو KDE اختصارًا- خوارزميةً تأخذ عيّنة، وتوجِد دالة كثافة احتمالية منتظمة تناسب البيانات، ويمكنك قراءة تفاصيل على <a data-ss1633769399="1" data-ss1633770619="1" href="https://en.wikipedia.org/wiki/Kernel_density_estimation" rel="external nofollow">ويكيبيديا</a>.
</p>

<p>
	تزوّدنا <code>scipy</code> بتنفيذ لتقدير كثافة النواة، كما يزوّدنا مستودع <code>thinkstats2</code> بصنف يُدعى <code>EstimatedPdf</code> يستخدِم ذلك التنفيذ كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_22" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">EstimatedPdf</span><span class="pun">(</span><span class="typ">Pdf</span><span class="pun">):</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> sample</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">kde </span><span class="pun">=</span><span class="pln"> scipy</span><span class="pun">.</span><span class="pln">stats</span><span class="pun">.</span><span class="pln">gaussian_kde</span><span class="pun">(</span><span class="pln">sample</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Density</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> xs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">kde</span><span class="pun">.</span><span class="pln">evaluate</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span></pre>

<p>
	يأخذ التابع <code>__init__</code> عيّنةً ويحسب تقدير كثافة النواة، حيث يكون الناتج كائن <code>gaussian_kde</code> الذي يزوِّدنا بتابع <code>evaluate</code>؛ أما التابع <code>Density</code> فيأخذ قيمةً أو تسلسلًا يُدعى <code>gaussian_kde.evaluate</code> ويُعيد الكثافة الناتجة، كما تَظهر الكلمة Gaussian في الاسم لأنها تستخدم مرشِّحًا يعتمد على التوزيع الغاوسي لجعل تقدير كثافة النواة منتظمًا smooth.
</p>

<p>
	إليك شيفرةً تولِّد عيّنةً من توزيع طبيعي ومن ثم تنشِئ صنف EstimatedPdf يناسبها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_24" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> sample </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">random</span><span class="pun">.</span><span class="pln">gauss</span><span class="pun">(</span><span class="pln">mean</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">500</span><span class="pun">)]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> sample_pdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">EstimatedPdf</span><span class="pun">(</span><span class="pln">sample</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> thinkplot</span><span class="pun">.</span><span class="typ">Pdf</span><span class="pun">(</span><span class="pln">sample_pdf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'sample KDE'</span><span class="pun">)</span></pre>

<p>
	تمثِّل <code>sample</code> قائمةً تحوي أطوال عشوائية عددها 500؛ أما <code>sample_pdf</code> فهو كائن Pdf يحتوي على تقدير كثافة النواة المقدَّر من العيّنة.
</p>

<p>
	يُظهر الشكل السابق دالة الكثافة الطبيعية وتقدير كثافة النواة بناءً على العيّنة التي تحتوي على أطوال عشوائية عددها 500، بحيث يكون التقدير مناسبًا للتوزيع الأصلي.
</p>

<p>
	يُعَدّ تقدير دالة الكثافة عن طريق تقدير كثافة النواة مفيدًا لعدة أغراض منها:
</p>

<ul>
<li>
		<strong>التصوّر/التوضيح المرئي Visualization</strong>: فغالبًا ما تُعَدّ دوال الكثافة التراكمية أفضل توضيح مرئي للتوزيع خلال مرحلة استكشاف المشروع، حيث أنه بإمكانك بعد النظر إلى دالة التوزيع التراكمي تحديد فيما إذا كانت دالة الكثافة الاحتمالية المقدَّرة تُعَدّ نموذجًا مناسبًا للتوزيع أم لا، فإذا كانت كذلك فستكون خيارًا أفضل لتمثيل التوزيع في حال لم يكن الجمهور المستهدف على اطلاع على دوال التوزيع التراكمي.
	</li>
	<li>
		<strong>الاستيفاء Interpolation</strong>: تفيد دالة الكثافة الاحتمالية المقدَّرة في الانتقال من عيّنة إلى نموذج للسكان، حيث يمكنك استخدَام تقدير كثافة النواة لاستيفاء كثافة القيم التي لا تظهر في العيّنة إذا كنت تعتقد أنّ توزيع السكان منتظمًا smooth.
	</li>
	<li>
		<strong>المحاكاة Simulation</strong>: غالبًا ما تكون المحاكاة مبنيّة على توزيع العيّنة، فإذا كان حجم العيّنة صغيرًا قد يكون من المناسب استخدام تقدير كثافة النواة KDE من أجل جعل توزيع العيّنة منتظمًا، مما يسمح للمحاكاة باستكشاف المزيد من النتائج المحتملة بدلًا من تكرار البيانات الملحوظة.
	</li>
</ul>
<h2>
	إطار التوزيع The distribution framework
</h2>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78775" data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/uploads/monthly_2021_10/6158a670d39e5_6.2.png.be109545ecf6e1491eb1507356cc4e49.png" rel=""><img alt="الشكل 6.2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78775" data-unique="cqkntjnmd" src="https://academy.hsoub.com/uploads/monthly_2021_10/6158a670d39e5_6.2.png.be109545ecf6e1491eb1507356cc4e49.png"></a>
</p>

<p style="text-align: center;">
	يوضِّح الشكل السابق إطارًا يربط بين تمثيلات دوال التوزيع.
</p>

<p>
	الآن بعد مرورنا على دوال الكتلة الاحتمالية PMFs ودوال التوزيع التراكمي CDFs ودوال الكثافة الاحتمالية PDFs، سنتوقف قليلًا لنراجع هذه المفاهيم، حيث يُظهر الشكل السابق كيفية ارتباط هذه الدوال ببعضها البعض.
</p>

<p>
	بدأنا بدراسة دوال الكتلة الاحتمالية التي تمثِّل احتمالات مجموعة متقطِّعة من القيم، حيث يمكننا الانتقال من دالة كتلة احتمالية PMF إلى دالة توزيع تراكمي CDF عن طريق جمع الكتل الاحتمالية للحصول على الاحتمالات التراكمية، وللانتقال من دالة توزيع تراكمي إلى دالة كتلة احتمالية يمكننا حساب الفروق في الاحتمالات التراكمية، كما سنرى تنفيذ هذه العمليات في الأقسام القليلة القادمة.
</p>

<p>
	يمكن تعريف دالة الكثافة الاحتمالية على أنها مشتق من دالة التوزيع التراكمي المستمرة، أو على نحو مكافئ بأنها تكامل لدالة الكثافة الاحتمالية -أي نحصل على دالة توزيع تراكمي عن طريق تطبيق تكامل على دالة الكثافة الاحتمالية-، حيث تحوِّل دالة الكثافة الاحتمالية القيم إلى كثافات احتمالية، ويجب تطبيق التكامل للحصول على احتمال.
</p>

<p>
	يمكننا جعل التوزيع منتظمًا بعدة طرق من أجل الانتقال من توزيع متقطِّع إلى توزيع مستمر، وإحدى أشكال التنظيم أو التنعيم smoothing هي افتراض أنّ مصدر البيانات هو توزيع تحليلي مستمر -مثل التوزيع الأسي أو الطبيعي-، ومن ثم تقدير معامِلات التوزيع، كما يمكننا جعل التوزيع منتظمًا عن طريق تقدير كثافة النواة KDE على أساس خيار آخر.
</p>

<p>
	يُعَدّ التكميم quantizing -أو التقطيع discretizing- عمليةً معاكسةً لعملية التنظيم smoothing، كما يمكننا توليد دالة الكتلة الاحتمالية التي تُعدّ تقريبًا لدالة الكثافة الاحتمالية وذلك عن طريق تقييم دالة الكثافة الاحتمالية عند نقاط متقطِّعة، كما يمكننا الحصول على تقريب أفضل باستخدام التكامل العددي.
</p>

<p>
	سنستخدم مصطلح دالة الكثافة التراكمية للدلالة على دالة التوزيع التراكمي المتقطعة، وذلك بهدف التمييز بين دوال التوزيع التراكمي المستمرة ودوال التوزيع التراكمي المتقطِّعة، لكننا نعتقد أن هذا المصطلح غير مستخدَم من قِبَل أيّ شخص آخر.
</p>

<h2>
	تنفيذ Hist
</h2>

<p>
	لا بدّ أنك الآن تجيد استخدام الأنواع الأساسية التي يزوّدنا بها مستودع <code>thinkstats2</code> وهي: Hist وPmf وCdf وPdf، كما ستزوِّدنا الأقسام القليلة القادمة بتفاصيل حول تنفيذها، وقد تساعدك هذه المعلومات على استخدام هذه الأصناف استخدامًا فعّالًا لكنها ليست ضروريةً تمامًا.
</p>

<p>
	يرث الصنفان <code>Hist</code> و<code>Pmf</code> توابعهما من صنف أب يُدعى <code>‎_DictWrapper‎</code> حيث تشير الشَرطة السفلية underscore إلى أن الصنف "داخلي"، أي لا يمكن استخدامه من قِبَل شيفرات موجودة في وحدات modules أخرى؛ أمّا اسم الصنف فيشير إلى قاموس مغلّف Dictionary Wrapper، والسمة الأساسية فيه هي <code>d</code> أي القاموس dictionary الذي يحوِّل القيم إلى تردداتها.
</p>

<p>
	يمكن أن تنتمي القيم إلى أيّ نوع قابل للتجزئة hashable، وعلى الرغم أنه يجب أن تكون الترددات قيمًا صحيحةً إلا أنها يمكن أن تنتمي إلى أي نوع عددي.
</p>

<p>
	يحتوي <code>‎_DictWrapper</code> على توابع ملائمة لكلًا من الصنف Hist والصنف Pmf بما فيها <code>__init__</code> و <code>Values</code> و <code>Items</code> و <code>Render</code> بالإضافة إلى توفير توابع محوِّلة هي <code>Set</code> و <code>Incr</code> و <code>Mult</code> و <code>Remove</code> فكل هذه التوابع مُنفَّذة مع عمليات القاموس، انظر مثلًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_26" style="">
<span class="com"># class _DictWrapper</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Incr</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> term</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> term

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Mult</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> factor</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> factor

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Remove</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">del</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span></pre>

<p>
	يزوّدنا الصنف Hist بالتابع <code>Freq</code> الذي يوجِد تردد قيمة معطاة.
</p>

<p>
	هذه التوابع تعمل عوامِل وتوابع Hist بزمن ثابت لأنها مبنية على قواميس، أي أنّ زمن تنفيذها لا يزداد مع ازدياد حجم الصنف Hist.
</p>

<h2>
	تنفيذ Pmf
</h2>

<p>
	يتشابه الصنفان Pmf وHist إلى حد التطابق تقريبًا إلا أنّ Pmf يحوِّل القيم إلى احتمالات عشرية؛ أما Hist فيحول القيم إلى ترددات نوعها صحيح integer، بحيث إذا كان مجموع الاحتمالات مساويًا للواحد فسيكون Pmf موحَّدًا.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: تنظيم أو توحيد للواحد أو توحيد أحادي هي عملية حسابية بسيطة لتبسيط النسب وهي على نمط النظام المئوي المعروف، مع اختلاف أنّ النسبة طبقًا للنظام المئوي تقع بين 0 % و100% بينما في التوحيد للواحد فستقع النسبة بين 0 و1، كما يمكنك الاطلاع على <a data-ss1633769399="1" data-ss1633770619="1" href="https://ar.wikipedia.org/wiki/%D8%AA%D9%86%D8%B8%D9%8A%D9%85_(%D8%B9%D9%85%D9%84%D9%8A%D8%A9_%D8%B1%D9%8A%D8%A7%D8%B6%D9%8A%D8%A9)" rel="external nofollow">المصدر</a>.
	</p>
</blockquote>

<p>
	يزوِّدنا الصنف Pmf بالتابع <code>Normalize</code> الذي يحسب مجموع الاحتمالات ويقسمها على معامِل factor كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_28" style="">
<span class="com"># class Pmf</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Normalize</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> fraction</span><span class="pun">=</span><span class="lit">1.0</span><span class="pun">):</span><span class="pln">
        total </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="typ">Total</span><span class="pun">()</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> total </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0.0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">ValueError</span><span class="pun">(</span><span class="str">'Total probability is zero.'</span><span class="pun">)</span><span class="pln">

        factor </span><span class="pun">=</span><span class="pln"> float</span><span class="pun">(</span><span class="pln">fraction</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> total
        </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">:</span><span class="pln">
            self</span><span class="pun">.</span><span class="pln">d</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">*=</span><span class="pln"> factor

        </span><span class="kwd">return</span><span class="pln"> total</span></pre>

<p>
	يحدِّد المتغير <code>fraction</code> مجموع الاحتمالات بعد توحيدها للواحد، حيث أنّ القيمة الاقتراضية هي الواحد، وإذا كان مجموع الاحتمالات 0 فلا يمكن توحيد الصنف Pmf، لذا سترمي دالة <code>Normalize</code> خطأً من النوع <code>ValueError</code>. يملك الصنفان Hist وPmf الباني نفسه، حيث يأخذ هذا الباني وسيطًا ليكون <code>dict</code> أو Hist أو Pmf أو Cdf، أو سلسلة بانداز pandas Series أو قائمةً من أزواج (قيمة وتردد) أو تسلسلًا من القيم.
</p>

<p>
	إذا أنشأت نسخةً من الصنف Pmf، فستكون النتيجة موحَّدة إلى الواحد (normalized)؛ أما إذا أنشأت نسخةً من الصنف Hist، فلن تكون النتيجة موحَّدة إلى الواحد، حيث يمكنك إنشاء صنف Pmf فارغ وتعديله لبناء صنف Pmf غير موحَّد، إذ أنّ معدلات Pmf لا لا تعيد توحيد الصنف Pmf.
</p>

<h2>
	تنفيذ Cdf
</h2>

<p>
	تحوّل دالة التوزيع التراكمي القيم إلى احتمالاتها التراكمية، لذا كان من الممكن تنفيذ Hist على أساس <code>‎_‎DictWrapper</code> إلا أنّ القيم في الصنف Hist مرتبّة على عكس <code>‎_DictWrapper</code>.
</p>

<p>
	يُعَد حساب دالة التوزيع التراكمي العكسية inverse CDF مفيدًا في البعض الأحيان، بحيث تكون دالة التوزيع التراكمي العكسية هي تحويل الاحتمال التراكمي إلى قيمته، لذا اخترنا التنفيذ الذي يحوي قائمتَين مرتبتَين وذلك لكي نستطيع إجراء بحث lookup أمامي أو عكسي في زمن تنفيذ لوغاريتمي عن طريق استخدام البحث الثنائي binary search.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: قد لا يكون الفرق بين search وlookup واضحًا أو معروفًا لدى الكثيرين، إلا أنه موجود، حيث أنه في عملية lookup نفترض أن القيمة التي نبحث عنها موجودة، وتكون لدينا طريقةً واضحةً لاستخراجها؛ أمّا في عملية search فلسنا واثقين من وجود القيمة التي نبحث عنها وقد لا يكون لدينا طريقةً واضحة لاستخراجها.
	</p>
</blockquote>

<p>
	يمكن لباني Cdf أن يأخذ تسلسلًا من القيم على أساس معامِل له أو قد يأخذ سلسلة بانداز pandas Series أو قاموسًا dictionary يحوِّل القيم إلى احتمالاتها، أو تسلسلًا من أزواج (القيمة والاحتمال) أو Hist، أو Pmf، أو Cdf، أو إذا أُعطي الباني معامِلان فسيعاملهما على أساس تسلسل مرتّب من القيم، وتسلسل من الاحتمالات التراكمية الموافقة.
</p>

<p>
	يمكن للباني إنشاء Hist بإعطاء تسلسل أو سلسلة بانداز pandas Series، أو قاموس، ومن ثم يستخدِم Hist من أجل تهيئة السمات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_30" style="">
<span class="pln">        self</span><span class="pun">.</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> freqs </span><span class="pun">=</span><span class="pln"> zip</span><span class="pun">(*</span><span class="pln">sorted</span><span class="pun">(</span><span class="pln">dw</span><span class="pun">.</span><span class="typ">Items</span><span class="pun">()))</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">ps </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">cumsum</span><span class="pun">(</span><span class="pln">freqs</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">=</span><span class="pln">np</span><span class="pun">.</span><span class="pln">float</span><span class="pun">)</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">ps </span><span class="pun">/=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">ps</span><span class="pun">[-</span><span class="lit">1</span><span class="pun">]</span></pre>

<p>
	تمثِّل <code>xs</code> قائمةً مرتّبةً من القيم وتمثِّل <code>freqs</code> قائمة الترددات الموافقة للقيم الموجودة في <code>xs</code>.
</p>

<p>
	يحسب التابع <code>np.cumsum</code> المجموع التراكمي للترددات علمًا أنّ التقسيم على التردد الكلي يُنتِج الاحتمالات التراكمية، كما يتناسب وقت بناء الصنف Cdf مع <code>n logn</code> في حال كان عدد القيم يساوي <code>n</code>.
</p>

<p>
	إليك تنفيذ التابع <code>Prob</code> الذي يأخذ قيمةً ويُعيد الاحتمال التراكمي:
</p>

<pre class="ipsCode">
# class Cdf
    def Prob(self, x):
        if x &lt; self.xs[0]:
            return 0.0
        index = bisect.bisect(self.xs, x)
        p = self.ps[index - 1]
        return p
</pre>

<p>
	تزوّدنا الوحدة <code>bisect</code> بتنفيذ البحث الثنائي، وإليك تنفيذ التابع <code>Value</code> الذي يأخذ الاحتمال التراكمي ويُعيد القيمة الموافقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_33" style="">
<span class="com"># class Cdf</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Value</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> p</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> p </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> p </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">ValueError</span><span class="pun">(</span><span class="str">'p must be in range [0, 1]'</span><span class="pun">)</span><span class="pln">

        index </span><span class="pun">=</span><span class="pln"> bisect</span><span class="pun">.</span><span class="pln">bisect_left</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">ps</span><span class="pun">,</span><span class="pln"> p</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">xs</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span></pre>

<p>
	يمكننا حساب Pmf في حال كان لدينا Cdf عن طريق حساب الفروقات بين احتمالين تراكميَّين متتاليين، وإذا استدعينا باني Cdf ومررنا له Pmf، فسيحسب الفروقات عن طريق استدعاء <code>Cdf.Items</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_35" style="">
<span class="com"># class Cdf</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Items</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        a </span><span class="pun">=</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">ps
        b </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">roll</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
        b</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> zip</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> a</span><span class="pun">-</span><span class="pln">b</span><span class="pun">)</span></pre>

<p>
	يُزيح التابع <code>np.roll</code> قيمًا من <code>a</code> إلى اليمين ويُدحرج القيمة الأخيرة إلى البداية، كما نستبدل القيمة 0 بالعنصر الأول من <code>b</code> ثم نحسب الفرق <code>a-b</code>، وتكون النتيجة هي مصفوفة نمباي NumPy من الاحتمالات.
</p>

<p>
	يزوِّدنا Cdf بالتابعَين <code>Shift</code> و<code>Scale</code> الذين يعدِّلان القيم الموجودة في Cdf إلا أنه يجب التعامل مع الاحتمالات على أنها قيم ثابتة غير قابلة للتبديل أو التعديل.
</p>

<h2>
	العزوم moments
</h2>

<p>
	عندما نأخذ عيّنةً ونحولّها إلى عدد منفرد أي نقلّصها، سينتج لدينا ما يُعرف بالإحصائية، وقد رأينا عدة إحصائيات حتى الآن، منها المتوسط mean والتباين variance والوسيط median والانحراف الربيعي interquartile range.
</p>

<p>
	يُعِدّ العزم الخام raw moment نوعًا من أنواع الإحصائيات، فإذا كانت لديك إحصائية تحوي قيمًا عددها x<sub>i</sub>‎ فستكون الصيغة الرياضية للعزم الخام رقم k أي kth raw moment كما يلي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium"><span style="font-style:italic">m</span>′</span><sub><span style="font-style:italic;font-size:medium">k</span></sub><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><sup><span style="font-style:italic;font-size:medium">k</span></sup><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	أو إذا كنت تفضِّل صيغة بايثون، فهذه هي الشيفرة الموافقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_38" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">RawMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">x</span><span class="pun">**</span><span class="pln">k </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> xs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span></pre>

<p>
	وفي حال كنا نريد إيجاد <a data-ss1633769399="1" data-ss1633770619="1" href="https://ar.wikipedia.org/wiki/%D8%B9%D8%B2%D9%85_(%D8%B1%D9%8A%D8%A7%D8%B6%D9%8A%D8%A7%D8%AA)" rel="external nofollow">العزم</a> الأول أي k=1 ستكون النتيجة هي متوسط العيّنة <code>x̄</code>، وفي الواقع لا تفيدنا العزوم الخام لوحدها إلّا أنها تُستخدَم في بعض أنواع الحسابات.
</p>

<p>
	تُعَدّ العزوم المركزية أكثر فائدةً من العزوم الخام، وتكون الصيغة الرياضية للعزم المركزي ذو الرقم k كما يلي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">m</span><sub><span style="font-style:italic;font-size:medium">k</span></sub><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> (<span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − <span style="text-decoration:overline">x</span>)</span><sup><span style="font-style:italic;font-size:medium">k</span></sup><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	أمّا الشيفرة الموافقة في بايثون فتكون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7451_40" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">CentralMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">):</span><span class="pln">
    mean </span><span class="pun">=</span><span class="pln"> </span><span class="typ">RawMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> sum</span><span class="pun">((</span><span class="pln">x </span><span class="pun">-</span><span class="pln"> mean</span><span class="pun">)**</span><span class="pln">k </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> xs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span></pre>

<p>
	إذا كانت k=2 فستكون النتيجة هي العزم المركزي الثاني، أي ما يُعرَف بالتباين variance، وقد يفيدنا التعريف الخاص بالتباين في معرفة السبب وراء تسمية هذه الإحصائيات بالعزوم، حيث إذا ثبّتنا ثقلًا على طول مسطرة في كل موقع x<sub>i</sub>‎ ومن ثم دوّرنا المسطرة حول المتوسط mean، فسيكون عزم العطالة -أو عزم القصور الذاتي- مساويًا لتباين القيم، وإذا لم تكن لديك فكرةً مسبقةً عن عزم العطالة، فيمكنك الاطلاع على <a data-ss1633769399="1" data-ss1633770619="1" href="https://ar.wikipedia.org/wiki/%D8%B9%D8%B2%D9%85_%D8%A7%D9%84%D9%82%D8%B5%D9%88%D8%B1_%D8%A7%D9%84%D8%B0%D8%A7%D8%AA%D9%8A" rel="external nofollow">معنى عزم القصور الذاتي</a>.
</p>

<p>
	من المهم وضع واحدات القياس في الحسبان عند التعامل مع الإحصائيات المبنية على العزوم، فإذا كانت القيم x<sub>i</sub>‎ مقدَّرةً بالسنتيمتر، فسيكون العزم الخام الأول مقدَّرًا بالسنتيمتر أيضًا، لكن يكون العزم الثاني مقدَّرًا بالسنتيمتر مربّع أي cm<sup>2</sup>‎، ويكون العزم الثالث مقدَّرًا بالسنتيمتر مكعَّب أي cm<sup>3</sup>‎ وهكذا.
</p>

<p>
	وبسبب هذه الواحدات فإنه من الصعب تفسير وفهم العزوم لوحدها، لذا عادةً ما يُحسب الانحراف المعياري عند ذكر العزم الثاني، حيث يمكن حساب الانحراف المعياري عن طريق تطبيق الجذر التربيعي على التباين، لذا فهو يُقدَّر واحدات قياس x<sub>i</sub>‎ نفسها. 8
</p>

<h2>
	معامل التجانف Skewness
</h2>

<p>
	<a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%A7%D9%86%D9%81" rel="external nofollow">التجانف</a> skewness هو خاصية تصف شكل التوزيع، فإذا كان التوزيع متناظرًا حول النزعة المركزية central tendency سنقول أنّه غير متجانف unskewed، وإذا كانت القيم ممتدة إلى أقصى اليمين فسيكون متجانفًا إلى اليمين؛ أما إن كانت ممتدة إلى أقصى اليسار فسيكون متجانفًا إلى اليسار.
</p>

<p>
	لا يدل في الواقع استخدام كلمة متجانف skewed على المعنى المعتاد منحازة biased، حيث يصف التجانف شكل التوزيع فقط ولا يذكر أيّ معلومات حول ما إن كانت عملية أخذ العيّنات منحازةً أم لا.
</p>

<p>
	عادةً ما يتم حساب كمية تجانف -أو انحراف- توزيع معيّن عن طريق استخدام عدة أنواع من الإحصائيات، فإذا كان لدينا تسلسل من القيم x<sub>i</sub>‎، فيمكننا حساب تجانف العيّنة sample skewness التي يرمز لها g<sub>1</sub> بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9186_16" style="">
<span class="pln">def </span><span class="typ">StandardizedMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">var</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CentralMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    std </span><span class="pun">=</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">(</span><span class="kwd">var</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">CentralMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> k</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> std</span><span class="pun">**</span><span class="pln">k

def </span><span class="typ">Skewness</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="typ">StandardizedMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	يكون g<sub>1</sub> هو العزم القياسي standardized moment الثالث، أي أنه وُحِّد normalized ولذلك ليس له واحدات قياس.
</p>

<p>
	يدل التجانف السالب على أنّ التوزيع متجانف إلى اليسار -أي منحرف نحو اليسار-؛ أمّا التجانف الموجب فيدل على أنّ التوزيع متجانف إلى اليمين -أي منحرف نحو اليمين-، كما يدل مقدار g<sub>1‎ على قوة التجانف إلا أنه ليس من السهل تفسيره لوحده.</sub></p>

<p>
	بالنظر إلى الجانب العملي يمكننا القول إن حساب عيّنة التجانف sample skewness ليست فكرةً سديدةً في أغلب الأحيان، إذ يخلق وجود القيم الشاذة outliers تأثيرًا غير متناسب على g<sub>1‎. </sub></p>

<p>
	توجد طريقة أخرى لتقييم لاتناظر توزيع معيّن من خلال دراسة العلاقة بين المتوسط والوسيط، حيث تؤثِّر القيم المتطرِّفة على المتوسط أكثر مما تؤثره على الوسيط، لذا يكون المتوسط أقل من الوسيط في التوزيعات التي تتجانف إلى اليسار، ويكون المتوسط أكبر من الوسيط في التوزيعات التي تتجانف إلى اليمين.
</p>

<p>
	يُعدّ معامل التجانف المتوسط لبيرسون Pearson’s median skewness coefficient مقياسًا للتجانف يعتمد على الفرق بين متوسط العيّنة والوسيط، وتكون الصيغة الرياضية له كما يلي:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">g</span><sub><span style="font-style:italic;font-size:medium">p</span></sub><span style="font-size:medium"> = 3 (<span style="text-decoration:overline">x</span> − <span style="font-style:italic">m</span>) / <span style="font-style:italic">S</span> </span>
			</td>
		</tr></tbody></table>
<p>
	حيث يكون x̄ متوسط العيّنة وm هي الوسيط وS هي الانحراف المعياري، وتكون شيفرة بايثون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-ruby prettyprinted" id="ips_uid_9186_20" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Median</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">):</span><span class="pln">
    cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> cdf</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">(</span><span class="lit">0.5</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> </span><span class="typ">PearsonMedianSkewness</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">):</span><span class="pln">
    median </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Median</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">)</span><span class="pln">
    mean </span><span class="pun">=</span><span class="pln"> </span><span class="typ">RawMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
    var </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CentralMoment</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    std </span><span class="pun">=</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">(</span><span class="pln">var</span><span class="pun">)</span><span class="pln">
    gp </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">mean </span><span class="pun">-</span><span class="pln"> median</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> std
    </span><span class="kwd">return</span><span class="pln"> gp</span></pre>

<p>
	تُعَدّ الإحصائية متينةً robust أي أنها أقل عرضة لتأثير القيم الشاذة outliers.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78776" data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/uploads/monthly_2021_10/6158a6717971f_6.3.png.1666416c31b3e9f33de05a175b8f6547.png" rel=""><img alt="الشكل 6.3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78776" data-unique="3bhux9ovp" src="https://academy.hsoub.com/uploads/monthly_2021_10/6158a6717971f_6.3.png.1666416c31b3e9f33de05a175b8f6547.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة الكثافة الاحتمالية PDF المقدَّرة لبيانات أوزان المواليد من المسح الوطني لنمو الأسرة NSFG.
</p>

<p>
	سنرى مثالًا عن هذا وهو تجانف أوزان المواليد في بيانات حالات الحمل الموجودة في المسح الوطني لنموّ الأسرة NSFG، وفيما يلي الشيفرة التي ترسم دالة الكتلة الاحتمالية وتقدِّرها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9186_22" style="">
<span class="pln">    live</span><span class="pun">,</span><span class="pln"> firsts</span><span class="pun">,</span><span class="pln"> others </span><span class="pun">=</span><span class="pln"> first</span><span class="pun">.</span><span class="typ">MakeFrames</span><span class="pun">()</span><span class="pln">
    data </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">.</span><span class="pln">totalwgt_lb</span><span class="pun">.</span><span class="pln">dropna</span><span class="pun">()</span><span class="pln">
    pdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">EstimatedPdf</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Pdf</span><span class="pun">(</span><span class="pln">pdf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'birth weight'</span><span class="pun">)</span></pre>

<p>
	يُظهِر الشكل السابق النتيجة، حيث يبدو الذيل الأيسر أطول من الذيل الأيمن لذا قد نعتقد أنّ التوزيع متجانفًا إلى اليسار، كما نجد أنّ المتوسط الذي يقدَّر بحوالي 3.29 كيلوغرامًا أي 7.27 رطلًا هو أقل من الوسيط الذي يقدَّر بحوالي 3.34 كيلوغرامًا أي 7.38 رطلًا، لذلك يتناسب هذا مع التجانف إلى اليسار، كما نجد أنّ معاملَي التجانف سالبان، حيث تكون قيمة عيّنة التجانف-0.59، وقيمة معامل التجانف المتوسط لبيرسون هو -0.23.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78777" data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/uploads/monthly_2021_10/6158a672b838a_6.4.png.eeb218a33c18e182c29206bb97a601b2.png" rel=""><img alt="الشكل 6.4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78777" data-unique="wfzwmnc9r" src="https://academy.hsoub.com/uploads/monthly_2021_10/6158a672b838a_6.4.png.eeb218a33c18e182c29206bb97a601b2.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة الكثافة الاحتمالية المقدَّرة لبيانات أوزان البالغين من نظام مراقبة عوامل المخاطر السلوكية BRFSS؛ أما الآن فسنوازن بين هذا التوزيع وبين توزيع أوزان البالغين في نظام مراقبة عوامل المخاطر السلوكية BRFSS، وفيما يلي الشيفرة الموافقة لذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9186_24" style="">
<span class="pln">    df </span><span class="pun">=</span><span class="pln"> brfss</span><span class="pun">.</span><span class="typ">ReadBrfss</span><span class="pun">(</span><span class="pln">nrows</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">)</span><span class="pln">
    data </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">wtkg2</span><span class="pun">.</span><span class="pln">dropna</span><span class="pun">()</span><span class="pln">
    pdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">EstimatedPdf</span><span class="pun">(</span><span class="pln">data</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Pdf</span><span class="pun">(</span><span class="pln">pdf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'adult weight'</span><span class="pun">)</span></pre>

<p>
	يُظهر الشكل السابق النتيجة، حيث يبدو التوزيع متجانفًا إلى اليمين، وبالطبع يكون المتوسط الذي يقدَّر بحوالي 35.8338 كيلوغرامًا أي 79.0 رطلًا أكبر من الوسيط الذي يقدَّر بحوالي 35.06269 كيلوغرامًا أي 77.3 رطلًا، كما تكون عيّنة التجانف هي 1.1، ومعامل التجانف المتوسط لبيرسون هو 0.26.
</p>

<p>
	يمكننا الاستنتاج من إشارة مُعامِل التجانف ما إذا كان التوزيع متجانفًا إلى اليمين أو إلى اليسار، لكن من الصعب تفسيرها بخلاف ذلك.
</p>

<p>
	تُعَد عيّنة التجانف أقل متانةً أي أنها أكثر عرضةً لتأثير القيم الشاذة، ونتيجةً لذلك فإنّ العيّنة أقل موثوقيةً عند تطبيقها على التوزيعات المتجانفة، أي هي غير موثوقة كثيرًا في أكثر وقت نحتاجها فيه بأن تكون موثوقة.
</p>

<p>
	يعتمد معامِل التجانف المتوسط لبيرسون على المتوسط والتباين المحسوبَين، لذا فهو أكثر عرضةً لتأثير القيم الشاذة، لكن بما أنه لا يعتمد على عزم ثالث فهو أكثر متانةً إلى حد ما.
</p>

<h2>
	تمارين
</h2>

<p>
	يوجد حل هذا التمرين في <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/chap06soln.py" rel="external nofollow">chap06soln.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h3>
	تمرين 1
</h3>

<p>
	من المعروف أن توزيع الدخل يتجانف إلى اليمين، لذا سنقيس في هذا التمرين مدى قوة هذا التجانف.
</p>

<p>
	يُعَدّ المسح السكاني الحالي Current Population Survey -أو CPS اختصارًا- جهدًا مشتركًا بين مكتب إحصاءات العمل ومكتب التعداد لدراسة الدخل والمتغيرات ذات الصلة، كما أنّ البيانات التي جُمعَت في عام 2013 متاحة في <a data-ss1633769399="1" data-ss1633770619="1" href="http://www.census.gov/hhes/www/cpstables/032013/hhinc/toc.htm" rel="external nofollow">census.gov</a>.
</p>

<p>
	حمّلنا ملف <code>hinc06.xls</code> وهو جدول بيانات إكسل يحتوي على معلومات حول دخل الأسر المعيشية، ومن ثم حولناه إلى <code>hinc06.csv</code> وهو ملف من النوع CSV يمكنك إيجاده في مستودع هذا الكتاب، كما ستجد <code>hinc2.py</code> الذي يقرأ الملف السابق ويحوِّل بياناته.
</p>

<p>
	تتخذ مجموعة البيانات شكل سلسلة مجالات الدخل وعدد المستجيبين الموجودين في كل مجال، إذ يشمل المجال الأدنى المستجيبين الذين أفادوا بأن دخل الأسر المعيشية في السنة أقل من 5000 دولارًا أمريكيًا، في حين يشمل المجال الأعلى المستجيبين الذين يكسبون 250000 دولارًا أمريكيًا أو أكثر.
</p>

<p>
	لتقدير المتوسط والإحصائيات الأخرى الخاصة من هذه البيانات علينا وضع بعض الافتراضات بما يخص الحدود الدنيا والعليا وبما يخص توزيع القيم في كل مجال.
</p>

<p>
	يزوِّدنا <code>hinc2.py</code> بالتابع <code>InterpolateSample</code> الذي ينمذج البيانات بإحدى الطرق المتاحة، حيث يأخذ إطار بيانات DataFrame مع عمود، و<code>income</code> الذي يحتوي القيمة العليا لكل مجال، و<code>freq</code> الذي يحوي عدد المستجيبين في كل إطار، و<code>log_upper</code> وهي القيمة العليا المفترضة على المجال الأعلى ويُعبَّر عنها كما يلي: <code>log10</code> دولارًا -أي نحسب اللوغاريتم العشري للقيمة بالدولار-.
</p>

<p>
	تمثِّل القيمة الافتراضية <code>log_upper=6.0‎</code> الافتراض الذي يقول أن الدخل الأعلى ضمن المستجيبين هو 10‎<sup>6</sup>‎ أي مليون دولار.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: log10(10‎<sup>6</sup>)=6.0).
	</p>
</blockquote>

<p>
	يولّد <code>InterpolateSample</code> عيّنةً وهميةً pseudo-sample، أي عيّنةً من مداخيل (جمع دخل) الأسر المعيشية تحتوي على عدد المستجيبين نفسه الموجود في كل مجال البيانات الفعلية، كما تفترض العيّنة الوهمية أن جميع المداخيل في كل مجال تبعد عن بعضها مسافات متساوية على مقياس log10. احسب الوسيط والمتوسط والتجانف وتجانف بيرسون للعيّنة الناتجة، وما هي نسبة الأسر المعيشية التي يكون دخلها الخاضع للضريبة أقل من المتوسط؟ وكيف تعتمد النتائج على الحد الأعلى upper bound المفترَض؟
</p>

<p>
	ترجمة -وبتصرف- للفصل <a data-ss1633769399="1" data-ss1633770619="1" href="https://greenteapress.com/thinkstats2/html/thinkstats2007.html" rel="external nofollow">Chapter 6 Probability density functions analysis</a> من كتاب <a data-ss1633769399="1" data-ss1633770619="1" href="https://greenteapress.com/wp/think-stats-2e" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1303/" rel="">دوال الكتلة الاحتمالية في جافاسكريبت</a>
	</li>
	<li>
		<a data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">التوزيعات الإحصائية في بايثون</a>
	</li>
	<li>
		النسخة الكاملة من كتب <a data-ss1633769399="1" data-ss1633770619="1" href="https://academy.hsoub.com/files/17-%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A-%D9%88%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9/" rel="">مدخل إلى الذكاء الاصطناعي وتعلم الآلة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1335</guid><pubDate>Mon, 04 Oct 2021 15:01:00 +0000</pubDate></item><item><title>&#x646;&#x645;&#x630;&#x62C;&#x629; &#x627;&#x644;&#x62A;&#x648;&#x632;&#x64A;&#x639;&#x627;&#x62A; Modelling distributions &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%86%D9%85%D8%B0%D8%AC%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-modelling-distributions-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1332/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeaa583bd_-.png.640fd79613803428b250834efb5f8a6b.png" /></p>

<p>
	تندرج جميع التوزيعات التي استخدمناها حتى الآن تحت اسم التوزيعات التجريبية empirical distributions لأنها مبنية على ملاحظات تجريبية وهي بالضرورة عيّنات محدودة.
</p>

<p>
	يأتي التوزيع التحليلي analytic distribution بديلًا عنها، وهو يتميز بدالة توزيع تراكمي -cumulative distribution function أو CDF اختصارًا-، والتي تتصف بأنها دالة رياضية، حيث يمكننا استخدام التوزيعات التحليلية لنمذجة التوزيعات التجريبية. ويكون النموذج model في هذا السياق مبسَّطًا ولا يتعمق في التفاصيل الغير ضرورية.
</p>

<p>
	يناقش هذا المقال التوزيعات التحليلية الشائعة وطريقة استخدامها لنمذجة البيانات من مصادر متنوعة، وتوجد الشيفرة الخاصة بهذا المقال في <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/analytic.py" rel="external nofollow">analytic.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h1>
	التوزيع الأسي
</h1>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78333" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb5c0d70_5.1.png.9acee34cde030a268723e8616f6754bd.png" rel=""><img alt="الشكل 5.1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78333" data-unique="y86nul232" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb5c0d70_5.1.png.9acee34cde030a268723e8616f6754bd.png"></a>
</p>

<p style="text-align: center;">
	يوضِّح الشكل السابق دوال التوزيع التراكمي للتوزيعات الأسية مع معامِلات متنوعة.
</p>

<p>
	ستكون البداية مع التوزيع الأسي exponential distribution لأنه سهل نسبيًا، وتكون الصيغة الرياضية لدالة التوزيع التراكمي للتوزيع الأسي هي:
</p>

<p style="text-align: center;">
	CDF(x) = 1- e<sup>-λx</sup></p>

<p>
	يحدِّد المعامِل <code>λ</code> شكل التوزيع، ويُظهر الشكل السابق شكل دالة التوزيع التراكمي عندما تكون <code>λ=0.5</code> و<code>λ=1</code> و<code>λ=2</code>.
</p>

<p>
	تظهر التوزيعات الأسيّة في العالم الحقيقي عندما ندرس سلسلة من الأحداث ونقيس الأزمنة الفاصلة بينها، وتُدعى أوقات الوصول البينية interarrival times، حيث إذا كان احتمال حصول الأحداث متساو في أيّ وقت كان فسيبدو توزيع أوقات الوصول البينية أنه التوزيع الأسي، كما يمكنك الاطلاع على هذه <a href="https://tanmiyat.mosuljournals.com/pdf_161825_6dfd854e9e4a5042e0b6a093e5ad637a.html" rel="external nofollow">الورقة</a> للاستئناس.
</p>

<p>
	سنلقي نظرةً على أوقات الوصول البينية الخاصة بالولادات على أساس مثال عن الفكرة السابقة، ففي يوم 18 من شهر 12 عام 1997، ولِد 44 طفلًا في مستشفى في مدينة بريسبان في أستراليا1، حيث وُثِّق وقت ولادة جميع هؤلاء الأطفال في صحيفة محلية، كما توجد مجموعة البيانات كاملةً في ملف <code>babyboom.dat</code> في مستودع <code>ThinkStats2</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_7" style="">
<span class="pln">    df </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ReadBabyBoom</span><span class="pun">()</span><span class="pln">
    diffs </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">minutes</span><span class="pun">.</span><span class="pln">diff</span><span class="pun">()</span><span class="pln">
    cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">diffs</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'actual'</span><span class="pun">)</span><span class="pln">

    thinkplot</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">cdf</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'minutes'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'CDF'</span><span class="pun">)</span></pre>

<p>
	تقرأ الدالة <code>ReadBabyBoom</code> ملف البيانات وتُعيد إطار بيانات DataFrame مع الأعمدة التالية: <code>time</code> يدل على وقت الولادة و<code>sex</code> يدل على جنس المولود، و<code>weight_g</code> يدل على الوزن عند الولادة، و<code>minutes</code> يدل على وقت الولادة بعد تحويله إلى الدقائق منذ منتصف الليل.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78335" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb833690_5.2.png.3d83b7276d52ff643439d8001ed2b12a.png" rel=""><img alt="الشكل 5.2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78335" data-unique="kn2weh6f9" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb833690_5.2.png.3d83b7276d52ff643439d8001ed2b12a.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة التوزيع التراكمي لأوقات الوصول البينية في الجهة اليمنى، ودالة التوزيع التراكمي المتمِّمة complementary cumulative distribution function -أو CCDF اختصارًا- على مقياس لوغاريتمي على محور y في الجهة اليسرى، كما أنّ <code>diffs</code> هو الفارق بين أزمنة الولادة المتتالية، و<code>cdf</code> هو توزيع أوقات الوصول البينية هذه، كما يُظهر الشكل السابق دالة التوزيع التراكمي، إذ يبدو أن للدالة الشكل العام للتوزيع الأسي، لكن كيف يمكننا التيقن من هذا؟
</p>

<p>
	تتمثل إحدى الطرق في رسم دالة التوزيع التراكمي المتمِّمة complementary CDF ومعادلتها <code>‎‎1‎-CDF(x‎)‎</code> على مقياس لوغاريتمي على محور y -أي المحور العمودي-، كما تكون النتيجة هي عبارة عن خط مستقيم في حال كانت البيانات من توزيع أسّي، وسنرى تطبيقًا عمليًا لهذا.
</p>

<p>
	إذا رسمت دالة التوزيع التراكمي المتمِّمة لمجموعة بيانات معيّنة تعتقد أنها أسيّة، فستتوقع رؤية دالة مثل التي يُعبّر عنها بالصيغة الرياضية التالية:
</p>

<p style="text-align: center;">
	y ≈ e<sup>-λx</sup></p>

<p>
	بتطبيق اللوغاريتم على الطرفين:
</p>

<p style="text-align: center;">
	logy ≈ -λx
</p>

<p>
	أي أنّ دالة التوزيع التراكمي المتمِّمة على مقياس لوغاريتمي على المحور العمودي هي عبارة عن خط مستقيم بميل قدره <code>‏‏‏‏‏‏‏‏‏λ-</code>، وفيما يلي الشيفرة التي تولِّد الرسم:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_9" style="">
<span class="pln">    thinkplot</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">cdf</span><span class="pun">,</span><span class="pln"> complement</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'minutes'</span><span class="pun">,</span><span class="pln">
                   ylabel</span><span class="pun">=</span><span class="str">'CCDF'</span><span class="pun">,</span><span class="pln">
                   yscale</span><span class="pun">=</span><span class="str">'log'</span><span class="pun">)</span></pre>

<p>
	يمكن لدالة <code>thinkplot.Cdf</code> حساب دالة التوزيع التراكمي المتمِّمة قبل الرسم وذلك بفضل الوسيط <code>complement=True</code>، كما يمكن للدالة <code>thinkplot.Show</code> ضبط مقياس محور x -أي المحور الأفقي- ليصبح لوغاريتميًا بفضل الوسيط <code>yscale='log'‎</code>.
</p>

<p>
	يُظهِر الشكل اليميني السابق النتيجة، وفي الواقع فإنّ الخرج ليس خطًا مستقيمًا مما يعني أنّ التوزيع الأسي ليس نموذجًا مثاليًا لهذه البيانات، ومن المرجَّح أنّ الافتراض الأساسي -الذي يقول أنّ احتمال الولادة نفسه لأيّ وقت من اليوم- ليس صحيحًا تمامًا، ومع ذلك قد يكون من المنطقي نمذجة مجموعة البيانات هذه بتوزيع أسي، حيث يمكننا تلخيص التوزيع بمعامِل واحد إذا استخدمنا هذا التبسيط في عملية النمذجة.
</p>

<p>
	يمكن تفسير المعامِل <code>λ</code> على أنّه معدّل rate أي عدد الأحداث التي تحدث وسطيًا في وحدة الزمن، أي في هذا المثال وُلِد 44 طفلًا في 24 ساعة، لذا فإن المعدل هو <code>λ=0.306</code> ولادة في الدقيقة الواحدة، كما يكون متوسط mean التوزيع الأسي هو <code>‎</code>1/‎λ، لذا فإنّ متوسط الزمن بين الولادات هو 32.7 دقيقة.
</p>

<h2>
	التوزيع الطبيعي normal distribution
</h2>

<p>
	يُستخدَم التوزيع الطبيعي normal distribution والذي يُدعى أيضًا "التوزيع الغاوسي" استخدامًا كبيرًا لأنه يصف العديد من الظواهر -يصفها بصورة تقريبية على الأقل-، ولم يأتِ هذا الانتشار الواسع للتوزيع الطبيعي من عبث، بل يوجد سبب مقنع سنناقشه في مقال لاحق، في القسم الرابع تحت عنوان "نظرية الحد المركزيّ".
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78336" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb8c56f4_5.3.png.76b85df58619440ee714d37e8924a028.png" rel=""><img alt="الشكل 5.3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78336" data-unique="ysoi3od9i" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb8c56f4_5.3.png.76b85df58619440ee714d37e8924a028.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة التوزيع التراكمي لتوزيعات طبيعية مع مجال وسائط parameters ما. ويتميّز التوزيع الطبيعي بمعامِلَين اثنين هما <code>μ</code> المتوسط mean، و<code>σ</code> الانحراف المعياري standard deviation.
</p>

<p>
	يُعَدّ التوزيع الطبيعي القياسي standard normal distribution حالةً خاصةً من التوزيع الطبيعي يكون فيها المتوسط مساويًا للصفر<code>μ = 0</code> وقيمة الانحراف المعياري مساويةً للواحد <code>σ = 1</code>، حيث يمكن تعريف دالة التوزيع التراكمي الخاصة بهذا التوزيع على أنّه تكامل لا يحوي على حلّ منغلق الشكل إلا أنه هناك خوارزميات تستطيع تقييمه بكفاءة.
</p>

<p>
	تزوِّدنا مكتبة ساي باي SciPy بإحدى هذه الخوارزميات، حيث أنّ <code>scipy.stats.norm</code> هو كائن يمثِّل توزيعًا طبيعيًا، ويزوِّدنا بتابع <code>cdf</code> يقيّم دالة التوزيع التراكمي القياسية الطبيعية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_11" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> scipy</span><span class="pun">.</span><span class="pln">stats
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scipy</span><span class="pun">.</span><span class="pln">stats</span><span class="pun">.</span><span class="pln">norm</span><span class="pun">.</span><span class="pln">cdf</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0.5</span></pre>

<p>
	هذه النتيجة صحيحة، حيث يكون وسيط median التوزيع الطبيعي هو 0 -كما هو الحال في المتوسط mean-، ونصف القيم أقلّ من الوسيط، وبالتالي CDF(0)=0.5.
</p>

<p>
	تأخذ الدالة <code>norm.cdf</code> معامِلَين اختياريين هما <code>loc</code> الذي يحدِّد المتوسط mean، و<code>scale</code> الذي يحدِّد الانحراف المعياري، ويسّهِل مستودع <code>thinkstats2</code> علينا هذه الدالة عن طريق تزويدنا بالدالة <code>EvalNormalCdf</code> التي تأخذ معامِلَين اختياريين هما <code>mu</code> و<code>sigma</code> وتقيِّم دالة التوزيع التراكمي عند <code>x</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_13" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">EvalNormalCdf</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> mu</span><span class="pun">=</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> sigma</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> scipy</span><span class="pun">.</span><span class="pln">stats</span><span class="pun">.</span><span class="pln">norm</span><span class="pun">.</span><span class="pln">cdf</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> loc</span><span class="pun">=</span><span class="pln">mu</span><span class="pun">,</span><span class="pln"> scale</span><span class="pun">=</span><span class="pln">sigma</span><span class="pun">)</span></pre>

<p>
	يُظهِر الشكل السابق دوال التوزيع التراكمي للتوزيعات الطبيعية مع مجال من المعامِلات، كما يُعَدّ هذا الشكل السّيني sigmoid للمنحنيات صفة مميّزة للتوزيع الطبيعي.
</p>

<p>
	ألقينا في <a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D8%AA%D8%B1%D8%A7%D9%83%D9%85%D9%8A-cumulative-distribution-functions-r1331/" rel="">المقال السابق</a> نظرةً على توزيع أوزان الولادات في المسح الوطني لنمو الأسرة، ويُظهِر الشكل التالي دوال التوزيع التراكمي التجريبي لأوزان جميع الولادات الحية، كما يُظهِر التوزيع الطبيعي مع مراعاة أن قيمة التباين variance وقيمة المتوسط mean هي ذاتها في الحالتين.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78337" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebaec131_5.4.png.8a425864f8303260c0b3671ee0f11ea6.png" rel=""><img alt="الشكل 5.4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78337" data-unique="3c16qt5lv" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebaec131_5.4.png.8a425864f8303260c0b3671ee0f11ea6.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة التوزيع التراكمي لأوزان الولادات مع نموذج طبيعي، حيث يُعَدّ التوزيع الطبيعي نموذجًا جيّدًا لمجموعة البيانات هذا، لذا فإن لخصّنا هذا التوزيع بالمعامِلات التالية: <code>μ=7.28</code> و<code>σ=1.24</code>، فسيكون الخطأ الناتج صغير، مع العلم أنّ الخطأ هنا يشير إلى الفرق بين النموذج والبيانات.
</p>

<p>
	هناك تناقض discrepancy بين البيانات وبين النموذج تحت المئين العاشر، حيث أنه يوجد في التوزيع عدد أطفال خفيفي الوزن أكثر من المتوقع في التوزيع الطبيعي، لكن إذا كنا مهتمين بدراسة الأطفال الخدّج، فسيكون الحصول على نتيجة دقيقة لهذا الجزء من التوزيع أمرًا هامًّا، لذلك قد لا يكون النموذج الطبيعي مناسبًا لهذا الغرض.
</p>

<h2>
	رسم الاحتمال الطبيعي normal probability plot
</h2>

<p>
	هناك تحويلات بسيطة يمكن استخدامها لاختبار فيما إذا كان التوزيع التحليلي يُعَدّ نموذجًا جيدًا لمجموعة بيانات معينة أم لا، ويمكن تطبيق ذلك على التوزيعات الأسية بالإضافة إلى بعض الأنواع الأخرى. وعلى الرغم من استحالة تطبيق هذه التحويلات على التوزيع الطبيعي، إلا أنه يوجد حل بديل يدعى رسم الاحتمال الطبيعي normal probability plot، كما يمكن توليده بطريقتين إحداهما صعبة والأخرى سهلة، ويمكنك الاطلاع على الطريقة الصعبة من <a href="https://en.wikipedia.org/wiki/Normal_probability_plot" rel="external nofollow">هنا</a>.
</p>

<p>
	أما بالنسبة للطريقة السهلة، فإليك الخطوات التالية:
</p>

<ol>
<li>
		رتّب القيم في العيّنة.
	</li>
	<li>
		بدءًا من توزيع طبيعي قياسي -أي <code>μ=0</code> و<code>σ=1</code>-، وولِّد عيّنة عشوائية لها حجم العيّنة نفسه ثم رتّبها.
	</li>
	<li>
		ارسم القيم المرتّبة من العيّنة والقيم العشوائية.
	</li>
</ol>
<p>
	تكون النتيجة خطًا مستقيمًا مع نقطة تقاطع ميو mu أي <code>μ</code> وميل قدره سيمغا sigma أي<code>σ</code> إذا كان توزيع العيّنة طبيعيًا تقريبًا.
</p>

<p>
	يزوّدنا مستودع <code>thinkstats2</code> بالدالة <code>NormalProbability</code> التي تأخذ عيّنةً وتُعيد مصفوفتَي نمباي NumPy، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_16" style="">
<span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">NormalProbability</span><span class="pun">(</span><span class="pln">sample</span><span class="pun">)</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78338" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebc990cc_5.5.png.b97400e4682a320666a6e592f293d443.png" rel=""><img alt="الشكل 5.5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78338" data-unique="1r8k0riwm" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebc990cc_5.5.png.b97400e4682a320666a6e592f293d443.png"></a>
</p>

<p>
	يوضِّح الشكل السابق رسم الاحتمال الطبيعي لعيّنات عشوائية من توزيع طبيعي، حيث تحتوي المصفوفة <code>ys</code> على القيم المرتّبة من العيّنة؛ أما المصفوفة <code>xs</code> فتحتوي على القيم العشوائية من التوزيع الطبيعي القياسي. وقد وَلّدنا بعض العيّنات المزيفة التي استقيناها من توزيعات طبيعية ذات معامِلات متنوعة وذلك بهدف اختبار الدالة <code>NormalProbability</code>، حيث يُظهِر الشكل السابق النتائج.
</p>

<p>
	نلاحظ أنّ الخطوط مستقيمة تقريبًا مع وجود انحراف في القيم الموجودة في الذيول أكثر من القيم القريبة من المتوسط.
</p>

<p>
	دعنا نجري التجربة على البيانات الحقيقية الآن. تولِّد هذه الشيفرة رسمًا احتماليًا طبيعيًا لبيانات أوزان الولادات الموجودة في القسم السابق، حيث ترسم هذه الشيفرة خطًا رماديًا يمثِّل النموذج، وخطًا أزرقًا يمثِّل البيانات.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_27" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">MakeNormalPlot</span><span class="pun">(</span><span class="pln">weights</span><span class="pun">):</span><span class="pln">
    mean </span><span class="pun">=</span><span class="pln"> weights</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">()</span><span class="pln">
    std </span><span class="pun">=</span><span class="pln"> weights</span><span class="pun">.</span><span class="pln">std</span><span class="pun">()</span><span class="pln">

    xs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[-</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">]</span><span class="pln">
    fxs</span><span class="pun">,</span><span class="pln"> fys </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">FitLine</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> inter</span><span class="pun">=</span><span class="pln">mean</span><span class="pun">,</span><span class="pln"> slope</span><span class="pun">=</span><span class="pln">std</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Plot</span><span class="pun">(</span><span class="pln">fxs</span><span class="pun">,</span><span class="pln"> fys</span><span class="pun">,</span><span class="pln"> color</span><span class="pun">=</span><span class="str">'gray'</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'model'</span><span class="pun">)</span><span class="pln">

    xs</span><span class="pun">,</span><span class="pln"> ys </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">NormalProbability</span><span class="pun">(</span><span class="pln">weights</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Plot</span><span class="pun">(</span><span class="pln">xs</span><span class="pun">,</span><span class="pln"> ys</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'birth weights'</span><span class="pun">)</span></pre>

<p>
	تمثِّل <code>weights</code> سلسلة بانداز pandas Series لأوزان الولادات، كما يمثِّل <code>mean</code> المتوسط، في حين يمثِّل <code>std</code> الانحراف المعياري. وتأخذ الدالة <code>FitLine</code> تسلسلًا sequence من <code>xs</code> ونقطة تقاطع ومَيل، كما تُعيد <code>xs</code> و<code>ys</code> اللتين تمثِّلان خطًا مع المعامِلات المُعطاة مقيّمًا عند القيم في <code>xs</code>.
</p>

<p>
	تُعيد الدالة <code>NormalProbability</code> مصفوفتَين <code>xs</code> و<code>ys</code> تحتويان على قيم من التوزيع الطبيعي القياسي وقيمًا من <code>weights</code>، حيث يجب أن تكون البيانات مطابقةً للنموذج في حال كان توزيع الأوزان طبيعيًا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78339" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebe59046_5.6.png.3299659ba2ff4aeb44eb8cbbbac5b467.png" rel=""><img alt="الشكل 5.6.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78339" data-unique="748bz14lq" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebe59046_5.6.png.3299659ba2ff4aeb44eb8cbbbac5b467.png"></a>
</p>

<p style="text-align: center;">
	يوضِّح الشكل السابق رسم الاحتمال الطبيعي لأوزان الولادات.
</p>

<p>
	يُظهر الشكل السابق نتائج جميع الولادات الحيّة وجميع الولادات التامة -التي كانت مدة الحمل فيها أكثر من 36 أسبوعًا-، حيث يُطابق المنحينان النموذج قرب المتوسط وينحرفان عند الذيول. كما أنّ وزن الأطفال الأكثر وزنًا أكثر مما يتوقّعه النموذج، ووزن الأطفال الأخف وزنًا أقل مما يتوقّعه النموذج.
</p>

<p>
	عندما نحدِّد الولادات التامة فقط سنستبعد بعض الأطفال خفيفي الوزن مما يقلّل من التناقض في الذيل المنخفض من التوزيع. وبحسب هذا الرسم فإنّ النموذج الطبيعي يصف التوزيع وصفًا جيدًا مع بعض الانحرافات المعيارية ضمن المتوسط، لكن لا توجد في الذيول، لكن كَون النموذج مناسبًا بما فيه الكفاية للتطبيقات العملية أم لا، فهو أمر يعود إلى الغرض من النمذجة.
</p>

<h2>
	التوزيع اللوغاريتمي الطبيعي The lognormal distribution
</h2>

<p>
	إذا كان للوغاريتمات مجموعة من القيم توزيعًا طبيعيًا، فستمتلك القيم توزيعًا لوغاريتميًا طبيعيًا lognormal distribution، كما أنّ دالة التوزيع التراكمي للتوزيع اللوغاريتمي الطبيعي هي ذاتها بالنسبة للتوزيع الطبيعي لكن مع استبدال logx بـ x.
</p>

<p style="text-align: center;">
	CDF<sub>lognormal</sub>(x) = CDF<sub>normal</sub>(logx)‎
</p>

<p>
	عادةً ما تتم الإشارة إلى معامِلات التوزيع اللوغاريتمي الطبيعي بـ <code>μ</code> و<code>σ</code>، لكنها لا تشير هنا إلى المتوسط والانحراف المعياري كما هو الحال سابقًا، إذ يكون المتوسط للتوزيع اللوغاريتمي الطبيعي هو exp(μ + σ<sup>2</sup>/2)‎؛ أما الانحراف المعياري فهو معقد، ويمكنك الاطلاع عليه من <a href="https://en.wikipedia.org/wiki/Log-normal_distribution" rel="external nofollow">هنا</a>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78340" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebfdf0f5_5.7.png.5bae4df6b5821fa8bba7093565c3cc59.png" rel=""><img alt="الشكل 5.7.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78340" data-unique="7s3z1wj38" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eebfdf0f5_5.7.png.5bae4df6b5821fa8bba7093565c3cc59.png"></a>
</p>

<p style="text-align: center;">
	يوضِّح الشكل السابق دالة التوزيع التراكمي لأوزان البالغين على مقياس خطي في الجهة اليسرى، ومقياس لوغاريتمي في الجهة اليمنى.
</p>

<p>
	إذا كانت العيّنة تمثِّل توزيعًا لوغاريتميًا طبيعيًا تقريبًا ورسمتَ دالة التوزيع التراكمي الخاصة بها على مقياس لوغاريتمي على المحور الأفقي -أي محور x-، فستكون له خصائص شكل التوزيع الطبيعي.
</p>

<p>
	يمكنك إنشاء رسم احتمالي طبيعي باستخدام لوغاريتم القيم في العيّنة لاختبار ما إذا كان النموذج اللوغاريتمي الطبيعي يناسب العيّنة، كما سنلقي نظرةً على توزيع أوزان البالغين على سبيل المثال والذي يُعَدّ توزيعًا لوغاريتميًا طبيعيًا تقريبًا.2
</p>

<p>
	يُجري المركز الوطني للوقاية من الأمراض المزمنة وتعزيز الصحة مسحًا سنويًا على أساس جزء من نظام مراقبة عوامل المخاطر السلوكية Behavioral Risk Factor Surveillance System -أو BRFSS3 اختصارًا-، حيث قابل المسؤولون عن المسح 414509 مستجيبًا عام 2008 وسألوهم عن معلوماتهم الديموغرافية وصحتهم والمخاطر الصحية التي تحيط بهم، ومن بين المعلومات التي جمعوها هي أوزان 398484 مستجيب مقدرةً بالكيلوغرام.
</p>

<p>
	يحوي المستودع repository الخاص بهذا الكتاب ملفًا باسم <code>CDBRFS08.ASC.gz</code> وهو ملف أسكي ASCII -أي الشيفرة القياسية الأمريكية لتبادل المعلومات- ذو عرض ثابت يحتوي على بيانات نظام مراقبة عوامل المخاطر السلوكية، وكذلك يحوي ملفًا باسم <code>brfss.py</code> الذي يقرأ الملف ويحلِّل البيانات.
</p>

<p>
	يُظهر الشكل السابق اليساري توزيع أوزان البالغين على مقياس خطي وباستخدام نموذج طبيعي؛ أما الشكل اليميني فيُظهر التوزيع نفسه على مقياس لوغاريتمي وباستخدام نموذج لوغاريتمي طبيعي، كما نلاحظ أنّ النموذج اللوغاريتمي الطبيعي أكثر ملاءمةً للعيّنة، إلا أن هذا التمثيل للبيانات لا يجعل الفرق واضحًا بصورة كبيرة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78341" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eec085f77_5.8.png.7e5330f858fe2f5a6d8baaab03c31109.png" rel=""><img alt="الشكل 5.8.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78341" data-unique="zkshri4be" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eec085f77_5.8.png.7e5330f858fe2f5a6d8baaab03c31109.png"></a>
</p>

<p style="text-align: center;">
	رسم الاحتمال الطبيعي لأوزان البالغين على مقياس خطي في الجهة اليسرى ومقياسًا لوغاريتميًا في الجهة اليمنى.
</p>

<p>
	يُظهر الشكل السابق الرسوم الاحتمالية الطبيعية لأوزان البالغين <code>w</code> ويُظهر الرسوم الاحتمالية الطبيعية للوغاريتماتها log<sub>10</sub>w‎. وبهذا فقد أصبح من الواضح الآن أنّ البيانات تنحرف انحرافًا كبيرًا عن النموذج الطبيعي، لكن من ناحية أخرى نرى أنّ النموذج اللوغاريتمي الطبيعي يلائم البيانات جيدًا.
</p>

<h2>
	توزيع باريتو The Pareto distribution
</h2>

<p>
	سُمي توزيع باريتو Pareto distribution بهذا الاسم نسبةً إلى الاقتصادي فيلفريدو باريتو Vilfredo Pareto الذي استخدَم هذا التوزيع في وصف توزيع الثروات، ولمزيد من التفاصيل يمكنك الاطلاع على <a href="https://ar.wikipedia.org/wiki/%D8%AA%D9%88%D8%B2%D9%8A%D8%B9_%D8%A8%D8%A7%D8%B1%D9%8A%D8%AA%D9%88" rel="external nofollow">توزيع باريتو بويكيبيديا</a>.
</p>

<p>
	لقد اعتُمِد هذا التوزيع من ذلك الوقت لوصف الظواهر الطبيعية والاجتماعية بما في ذلك أحجام المدن والبلدات وذرات الرمل والنيازك وحرائق الغابات والزلازل.
</p>

<p>
	الصيغة الرياضيّة لدالة التوزيع التراكمي لتوزيع باريتو Pareto distribution هي:
</p>

<p style="text-align: center;">
	CDF(x) =1- xxm-
</p>

<p>
	يحدِّد المعامِلَين x<sub>m</sub>‎ و<code>α</code> الموقع وشكل التوزيع، حيث x<sub>m</sub> هي أصغر قيمة ممكنة، ويُظهر الشكل التالي دوال التوزيع التراكمي لتوزيعات باريتو Pareto distributions مع افتراض أنّ x<sub>m</sub> = 0.5 وتجريب عدة قيم مختلفة لـ <code>α</code>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78342" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eec15a637_5.9.png.3d11eb4aca2218b4effa4c85a593a9c3.png" rel=""><img alt="الشكل 5.9.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78342" data-unique="j6lfikcww" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eec15a637_5.9.png.3d11eb4aca2218b4effa4c85a593a9c3.png"></a>
</p>

<p style="text-align: center;">
	يوضِّح الشكل السابق دوال التوزيع التراكمي لتوزيعات باريتو Pareto distributions بمعامِلات مختلفة.
</p>

<p>
	هناك اختبار مرئي بسيط يخبرنا عما إن كان التوزيع التجريبي يلائم توزيع باريتو Pareto distribution أم لا، ويبدو لنا على مقياس لوغاريتمي-لوغاريتمي أنّ دوال التوزيع التراكمي المتمِّمة هي خط مستقيم، وسنرى التطبيق العملي لهذا.
</p>

<p style="text-align: center;">
	y = xxm -
</p>

<p>
	بتطبيق اللوغاريتم على الطرفين يكون لدينا:
</p>

<p style="text-align: center;">
	logy ≈ -α(logx - logx<sub>m</sub>)
</p>

<p>
	لذا فإن رسمت logy مقابل logx، فيجب أن يبدو الشكل مستقيمًا مع ميل قدره <code>‎-‎α</code> ونقطة تقاطع هي α logx<sub>m</sub> ‎‎‎.
</p>

<p>
	سنأخذ أحجام المدن والبلدات على أساس مثال عن هذا، حيث ينشر مكتب الإحصاء الأمريكي The U.S. Census Bureau عدد السكان في كل مدينة وبلدة في الولايات المتحدة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78334" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb66969c_5_10.png.2440ebb835f99d34391c8393f4f170e8.png" rel=""><img alt="الشكل 5.10.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78334" data-unique="gxsrylo8a" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb66969c_5_10.png.2440ebb835f99d34391c8393f4f170e8.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دوال التوزيع التراكمي المتمِّمة لسكان المدينة والبلدة على مقياس لوغاريتمي-لوغاريتمي أي أنّ المقياس المستخدَم للمحورين الأفقي والعمودي هو لوغاريتمي.
</p>

<p>
	يمكن تنزيل بيانات هذا المركز من <a href="http://www.census.gov/popest/data/cities/totals/2012/SUB-EST2012-3.html" rel="external nofollow">هنا</a>، كما توجد هذه البيانات في مستودع الكتاب تحت اسم <code>PEP_2012_PEPANNRES_with_ann.csv</code>، ويحتوي هذا المستودع على ملف <code>populations.py</code> الذي يقرأ الملف ويرسم توزيع السكان.
</p>

<p>
	يُظهر الشكل السابق وقوع أكبر 1% من البلدات والمدن التي تقل عن ‎10<sup>-2</sup>‎ على طول خط مستقيم، لذا يمكننا استنتاج أنّ ذيل هذا التوزيع يناسب نموذج باريتو Pareto model وهذا يطابق قول بعض الباحثِين.
</p>

<p>
	ينمذِج التوزيع اللوغاريتمي الطبيعي من ناحية أخرى البيانات جيدًا، ويوضِّح الشكل التالي دالة التوزيع التراكمي للسكان ونموذجًا لوغاريتميًا طبيعيًا في الجهة اليسرى، وفي الجهة اليمنى رسمًا احتماليًا طبيعيًا، كما نستنتج أنّ الرسمَين يُظهران ملاءمةً جيدةً بين البيانات والنموذج.
</p>

<p>
	لا يُعَدّ كل نموذج لوحده هنا مثاليًا في الواقع، حيث ينطبق نموذج باريتو Pareto model على أكبر 1% من المدن فقط، لكنه أكثر ملاءمةً لهذا الجزء من التوزيع، كما يناسب النموذج اللوغاريتمي الطبيعي بقية البيانات أي ما يقارب 99% من البيانات، أي يعتمد مدى ملاءمة نموذج معيّن للبيانات على جزء التوزيع الذي نهتم بدراسته.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78332" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb05d157_5_11.png.767a9196eadbaf2da7505f6fc5940af4.png" rel=""><img alt="الشكل 5.11.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78332" data-unique="jkvm67iv1" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155eeb05d157_5_11.png.767a9196eadbaf2da7505f6fc5940af4.png"></a>
</p>

<p>
	يُظهر الشكل السابق دالة التوزيع التراكمي لسكان المدينة والبلدة على مقياس لوغاريتمي على المحور الأفقي x في الجهة اليسرى، ورسم الاحتمال الطبيعي للسكان بعد تطبيق تحويل لوغاريتمي log-transformation على السكان في الجهة اليمنى.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: في التحويل اللوغاريتمي تُحوَّل كل x في البيانات إلى log(x).
	</p>
</blockquote>

<h2>
	توليد أعداد عشوائية
</h2>

<p>
	يمكن استخدام دوال التوزيع التراكمي التحليلية لتوليد أعداد عشوائية إذا كان لدينا دالة توزيع مُعطاة مسبقًا، حيث أنّ p=CDF(x)، وإذا كانت هناك طريقة فعالة لحساب دالة التوزيع التراكمي العكسية، فسيمكننا توليد قيم عشوائية مع التوزيع المناسب وذلك عن طريق اختيار <code>p</code> من توزيع موحَّد بين 0 و1، ومن ثم اختيار x=ICDF(p).
</p>

<p>
	الصيغة الرياضية على سبيل المثال لدالة التوزيع التراكمي للتوزيع الأسي هي:
</p>

<p style="text-align: center;">
	p = 1- e<sup>-λx</sup></p>

<p>
	بحل المعادلة بالنسبة لـ x ينتج:
</p>

<p style="text-align: center;">
	x = -log(1-p) / λ
</p>

<p>
	كما تكون الشيفرة الموافقة بلغة بايثون:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_20" style="">
<span class="pln">    </span><span class="kwd">def</span><span class="pln"> expovariate</span><span class="pun">(</span><span class="pln">lam</span><span class="pun">):</span><span class="pln">
    p </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">random</span><span class="pun">()</span><span class="pln">
    x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="pln">math</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="lit">1</span><span class="pun">-</span><span class="pln">p</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> lam
    </span><span class="kwd">return</span><span class="pln"> x</span></pre>

<p>
	تأخذ الدالة <code>expovariate</code> معامِلًا هو <code>lam</code> وتُعيد قيمةً عشوائيةً مختارة من التوزيع الأسي مع المعامِل <code>lam</code>.
</p>

<p>
	إليك ملاحظتين اثنتين حول هذا التنفيذ: استدعينا المعامِل <code>lam</code> لأن <code>lambda</code> هي كلمة مفتاحية في لغة بايثون، وبما أن log0 هي قيمة غير معرَّفة undefined، فيجب أن نكون حذرين قليلًا.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: لامدا أو lambda تقابل الحرف الإغريقي المذكور آنفًا .
	</p>
</blockquote>

<p>
	يمكن أن تُعيد الدالة <code>random.random</code> القيمة 0 لكن لا يمكنها إعادة 1، لذا يمكن أن تكون قيمة 1-pهي 1، لكن لا يمكن أن تكون 0، وبالتالي تكون قيمة <code>log(1-p)</code> هي دائمًا معرَّفة.
</p>

<h2>
	بم تفيدنا النمذجة؟
</h2>

<p>
	ذكرنا في بداية المقال أنه يمكن نمذجة العديد من الظواهر التي تحصل في الحياة الواقعية باستخدام النماذج التحليلية، لذا قد تقول: "ماذا إذًا؟"
</p>

<p>
	تُعَدّ التوزيعات التحليلية تجريدات مثل حال النماذج الأخرى، أي أنّها تُهمل التفاصيل التي لا علاقة لها بموضوع الدراسة. فمثلًا، قد يكون في التوزيع الملحوظ أخطاء في القياس أو عيوب متعلقة بالعيّنة، فتأتي النماذج التحليلية لتخفيف هذه المشاكل.
</p>

<p>
	كما تُعَدّ النماذج التحليلية شكلًا form من ضغط البيانات، حيث أنه عندما يناسب نموذج معيّن لمجموعة بيانات، فسيمكن عندها تلخيص كمية كبيرة من البيانات باستخدام مجموعة صغيرة من المعامِلات.
</p>

<p>
	قد نتفاجأ في حال وجدنا أنّ بيانات إحدى الظواهر الطبيعية قد لاءمت توزيعًا تحليليًا، لكن يمكن أن توفِّر لنا هذه الملاحظات معلومات أكثر عن النظم الفيزيائية.
</p>

<p>
	يمكننا في بعض الأحيان وصف السبب الذي يجعل توزيعًا ملحوظًا يظهر بشكل معيّن، فغالبًا ما تكون توزيعات باريتو Pareto distributions على سبيل المثال، نتيجةً لعمليات توليدية ذات رد فعل إيجابي أو ما يُعرَف باسم <a href="https://en.wikipedia.org/wiki/Preferential_attachment" rel="external nofollow">عمليات الإلحاق التفضيلية preferential attachment processes</a>.
</p>

<p>
	تصلح التوزيعات التحليلية للتحليل الرياضي كما سنرى في مقال لاحق، لكن من المهم أن نتذكّر أن جميع النماذج غير مثالية، ولا يمكن للبيانات الصادرة من العالم الحقيقي أن تناسب التوزيع التحليلي بصورة مثالية.
</p>

<p>
	يتحدث الأفراد في بعض الأحيان كما لو كانت البيانات تُولَّد من نماذج، فقد يسأل البعض مثلًا فيما إذا كان توزيع أطوال البشر طبيعيًا، أو قد يسألون فيما إن كان توزيع الدخل لوغاريتميًا طبيعيًا، وإذا أخذنا الأمور بحَرفيّة فستكون هذه الأقوال غير صحيحة بسبب وجود فروق بين النماذج الرياضية والعالم الحقيقي.
</p>

<p>
	تفيد هذه النماذج إذا استطاعت التقاط الجوانب التي تهمنا من العالم الحقيقي وإهمال التفاصيل غير المهمة في آن واحد، لكن "الجوانب التي تهمنا" و"التفاصيل غير المهمة" هي أمور معتمدة على الغرض من استخدام النموذج.
</p>

<h2>
	تمارين
</h2>

<p>
	يمكنك الانطلاق من <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/chap05ex.ipynb" rel="external nofollow">chap05ex.ipynb</a></code> لحل هذه التمارين، مع العلم أن الحل الخاص بنا موجود في ملف <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/solutions/chap05soln.ipynb" rel="external nofollow">chap05soln.ipynb</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub حيث ستجد كل الشيفرات والملفات المطلوبة.
</p>

<h3>
	 التمرين الأول
</h3>

<p>
	يُعَدّ توزيع الأطوال في نظام مراقبة عوامل المخاطر السلوكية BRFSS طبيعيًا تقربيًا مع العلم أنّ المعامِلات بالنسبة للرجال هي μ=178 cm وσ = 7.7، وبالنسبة للنساء هي μ=163 cm وσ = 7.3.
</p>

<p>
	هناك شرط للانتساب لمجموعة <a href="http://bluemancasting.com/" rel="external nofollow">بلو مان</a> وهو أن يكون الفرد ذكرًا طوله بين ''10'5 قدمًا -أي حوالي 177.8 سنتي مترًا- و''1'6 قدمًا -أي حوالي 185.42 سنتي مترًا-. فما هي نسبة الرجال الأمريكيين الذي ينطبق عليهم هذا الشرط؟
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		تلميح: استخدم <code>scipy.stats.norm.cdf</code>.
	</p>
</blockquote>

<h3>
	التمرين الثاني
</h3>

<p>
	للتعرف على توزيع باريتو Pareto distribution، سنرى كيف سيكون العالم مختلفًا فيما لو كان توزيع أطوال البشر هو عن باريتو Pareto.
</p>

<p>
	يمكننا الحصول على توزيع ذي قيمة صغرى منطقية 1m أي مترًا واحدًا، ووسيط median هو 1.5 m أي متر ونصف، أي في حال كانت المعامِلات هي x<sub>m</sub> = 1 و<code>α=1.7</code>.
</p>

<p>
	ارسم هذا التوزيع وأجب عن الأسئلة التالية:
</p>

<ul>
<li>
		ما هو متوسط mean أطوال البشر في عالم باريتو؟
	</li>
	<li>
		ما هي نسبة fraction الأشخاص الذين يقل طولهم عن المتوسط؟
	</li>
	<li>
		إذا كان هناك 7 مليار فرد في عالم باريتو، فكم هو عدد الأفراد الذي من المتوقع أن يزيد طولهم عن كيلومتر واحد؟
	</li>
	<li>
		كم طول أطول شخص ممكن توقّعه؟
	</li>
</ul>
<h3>
	التمرين الثالث
</h3>

<p>
	يُعَدّ توزيع وايبول Weibull distribution تعميمًا للتوزيع الأسي الذي يظهر في تحليل الفشل، حيث يمكنك الاطلاع على ذلك في <a href="https://ar.wikipedia.org/wiki/%D8%AA%D9%88%D8%B2%D9%8A%D8%B9_%D9%88%D8%A7%D9%8A%D8%A8%D9%88%D9%84" rel="external nofollow">ويكيبيديا</a> للمزيد من المعلومات، وتكون الصيغة الرياضية لدالة التوزيع التراكمي لهذا التوزيع بالصورة التالية:
</p>

<p style="text-align: center;">
	CDF(x) = 1 - e<sup>-(x/λ)<sup>k</sup></sup></p>

<p>
	لكن هل يمكننا إيجاد تحويل ليبدو توزيع وايبول خطًا مستقيمًا؟ علامَ يدل كل من الميل ونقطة التقاطع؟ استخدِم هنا <code>random.weibullvariate</code> لتوليد عيّنة من توزيع وايبول واستخدِمه في اختبار تحويلك.
</p>

<h3>
	التمرين الرابع
</h3>

<p>
	لا نتوقع أن يكون التوزيع التجريبي مناسبًا للتوزيع التحليلي بدقة من أجل القيم الصغيرة من n، حيث تتمثل إحدى طرق تقييم جودة الملاءمة في توليد عيّنة من توزيع تحليلي ومن ثم التحقق من مدى ملاءمتها للبيانات.
</p>

<p>
	رسمنا مثلًا في القسم الأول -التوزيع الأسي- توزيع الوقت بين الولادات، ورأينا أنه أسي تقريبًا، لكن التوزيع مبني على 44 نقطة بيانات فقط.
</p>

<p>
	لنرى ما إذا كانت البيانات قد أتت من توزيع أسي، يجب عليك توليد 44 قيمة من توزيع أسي له متوسط البيانات هذه نفسها، أي بوجود 33 دقيقة بين الولادة والأخرى. وارسم توزيع القيم العشوائية ووازنه مع التوزيع الفعلي، كما يمكنك استخدام <code>random.expovariate</code> لتوليد القيم.
</p>

<h3>
	التمرين الخامس
</h3>

<p>
	ستجد في <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">مستودع هذا الكتاب</a> مجموعةً من ملفات البيانات تُدعى <code>mystery0.dat</code> و <code>mystery1.dat</code> وهكذا، حيث يحتوي كل ملف على تسلسل من الأعداد العشوائية المولَّدة من توزيع تحليلي.
</p>

<p>
	كما ستجد ملفًا يدعى <code>test_models.py</code> وهو عبارة عن سكربت يقرأ البيانات من ملف ويرسم دالة التوزيع التراكمي مع مجموعة متنوعة من التحويلات، إذ يمكنك تشغيل الملف عن طريق استخدام مثل التعليمة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4017_22" style="">
<span class="pln">$ python test_models</span><span class="pun">.</span><span class="pln">py mystery0</span><span class="pun">.</span><span class="pln">dat</span></pre>

<p>
	يمكنك استنتاج نوع التوزيع المولَّد في كل ملف بناءً على الرسوم هذه، لكن إذا كنت في حيرة من أمرك، فيمكنك البحث في ملف <code>mystery.py</code> الذي يحتوي على الشيفرة التي ولَّدت الملفات.
</p>

<h3>
	التمرين السادس
</h3>

<p>
	تكون توزيعات الدخل والثروة في بعض الأحيان منمذجةً باستخدام توزيعات باريتو Pareto distributions وتوزيعات لوغاريتمية طبيعية lognormal، ولكي نرى أيّ منها أفضل سنلقي نظرةً على مجموعة من البيانات.
</p>

<p>
	يُعَدّ <a href="http://www.census.gov/hhes/www/cpstables/032013/hhinc/toc.htm" rel="external nofollow">المسح السكاني الحالي Current Population Survey</a> -أو CPS اختصارًا- جهدًا مشتركًا بين مكتب إحصاءات العمل ومكتب التعداد لدراسة الدخل والمتغيرات ذات الصلة.
</p>

<p>
	حمّلنا الملف <code>hinc06.xls</code> وهو عبارة عن جدول بيانات spreadsheet إكسل يحوي معلومات عن دخل الأسرة المعيشية household income، وحوَّلناه إلى <code>hinc06.csv</code> وهو ملف ستجده في المستودع الخاص بهذا الكتاب، كما ستجد <code>hinc.py</code> الذي يقرأ الملف السابق.
</p>

<p>
	استخرج توزيع مجموعة المداخيل من مجموعة البيانات هذه، وهل يُعَد أيّ توزيع من التوزيعات التحليلية الواردة في هذا المقال نموذجًا جيدًا للبيانات؟
</p>

<p>
	يوجد حل هذا التمرين في الملف <code>hinc_soln.py</code> فستجد كل الشيفرات والملفات في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a>.
</p>

<h2>
	مفاهيم أساسية
</h2>

<ul>
<li>
		<strong>التوزيع التجريبي exponential distribution</strong>: هو توزيع القيم في عيّنة ما.
	</li>
	<li>
		<strong>التوزيع الأسي analytic distribution</strong>: هو التوزيع الذي تتصف دالة التوزيع التراكمي الخاصة به بأنّها دالة تحليلية.
	</li>
	<li>
		<strong>النموذج model</strong>: هو تبسيط يقدِّم معلومات مفيدة، حيث غالبًا ما تُعَدّ التوزيعات التحليلية أنها نماذجَ جيدة لتوزيعات تجريبية empirical distributions أكثر تعقيدًا.
	</li>
	<li>
		فاصل الوصول interarrival time: هو الزمن الفاصل بين حدثين اثنين.
	</li>
	<li>
		<strong>دالة التوزيع التراكمي المتمِّمة complementary CDF</strong>: هي دالة تحوِّل القيمة x إلى كسر من القيم التي تتجاوز x، وتكون صيغتها الرياضية 1-CDF(x).
	</li>
	<li>
		<strong>التوزيع الطبيعي القياسي standard normal distribution</strong>: هو حالة خاصة من التوزيع الطبيعي تكون قيمة الانحراف المعياري standard deviation فيه هي 1، وقيمة المتوسط mean هي 0.
	</li>
	<li>
		<strong>رسم الاحتمال الطبيعي normal probability plot</strong>: هو رسم للقيم الموجودة في عيّنة ما مقابل قيم عشوائية من توزيع طبيعي قياسي.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a href="https://greenteapress.com/thinkstats2/html/thinkstats2006.html" rel="external nofollow">Chapter 5 Modelling distributions analysis</a> من كتاب <a href="https://greenteapress.com/wp/think-stats-2e" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">التوزيعات الإحصائية في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1303/" rel="">دوال الكتلة الاحتمالية في جافاسكريبت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1332</guid><pubDate>Wed, 29 Sep 2021 15:00:00 +0000</pubDate></item><item><title>&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x62A;&#x648;&#x632;&#x64A;&#x639; &#x627;&#x644;&#x62A;&#x631;&#x627;&#x643;&#x645;&#x64A; Cumulative distribution functions</title><link>https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9-%D8%A7%D9%84%D8%AA%D8%B1%D8%A7%D9%83%D9%85%D9%8A-cumulative-distribution-functions-r1331/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_09/6155e9fa3f782_---.png.c159079ab60aa7f6e701f130567ff3b1.png" /></p>

<p>
	يمكنك الحصول على الشيفرة الخاصة توجد بهذا المقال في <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/cumulative.py" rel="external nofollow">cumulative.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h2>
	حدود دوال الكتلة الاحتمالية
</h2>

<p>
	تؤدي دوال الكتلة الاحتمالية probability mass functions -أو PMFs اختصارًا- وظيفتها بصورة جيدة عندما يكون عدد القيم صغيرًا، لكن كلما ازداد عدد القيم، أصبح الاحتمال المرتبط بكل قيمة أصغر ويزداد أثر الضجيج العشوائيّ.
</p>

<p>
	قد نرغب بدراسة توزيع أوزان الأطفال الخدّج في بيانات المسح الوطني لنمو الأسرة NSFG على سبيل المثال، حيث يسجِّل المتغير <code>totalwgt_lb</code> وزن الطفل عند ولادته مقدرًا بالرطل، ويُظهر الشكل التالي دالة الكتلة الاحتمالية لأوزان الأطفال الأوائل والأطفال الآخرين -أي جميع الأطفال الذين يولدون بعد الطفل الأول للأم ذاتها- عند الولادة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78324" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea39bc7aa_4.1.png.2705fcbf141e7059759f9c50ca55cf34.png" rel=""><img alt="الشكل 4.1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78324" data-unique="augb6hvht" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea39bc7aa_4.1.png.2705fcbf141e7059759f9c50ca55cf34.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة الكتلة الاحتمالية لأوزان المواليد، كما يظهر هذا الشكل وجود حدود على دوال الكتلة الاحتمالية، إلا أنه لا يمكن موازنتها بصريًا.
</p>

<p>
	تشبه هذه التوزيعات عمومًا شكل الجرس كما هو الحال في التوزيع الطبيعي normal distribution مع توضُّع الكثير من القيم بالقرب من المتوسط mean، وتوضُّع قلة قليلة من القيم في كلا الطرفين -أي أعلى وأخفض من المتوسط بكثير-، ولكن يصعب تفسير بعض هذه أجزاء هذا الشكل، إذ توجد العديد من القمم -الارتفاعات- والانخفاضات بالإضافة إلى بعض الفروقات الواضحة بين التوزيعات، إلا أنه من الصعب معرفة إن كانت هذه الميزات ذات معنى، ومن الصعب أيضًا رؤية الأنماط العامة، مثل ما هو برأيك التوزيع الذي يحتوي على المتوسط الأعلى؟
</p>

<p>
	يمكن تخفيف هذه المشاكل عن طريق تصنيف binning البيانات وهي تقسيم مجالات القيم إلى مجالات غير متداخلة بالإضافة إلى حساب عدد القيم في كل مجال مصنَّف bin.
</p>

<p>
	قد تكون عملية تصنيف مفيدة، إلا أنّ الحصول على الحجم الصحيح للمجالات المصنَّفة ليس بالأمر السهل، فإذا كان حجمها كبيرًا بما يكفي لتخفيف الضجيج، فستتسبب في تنعيم معلومات مفيدة.
</p>

<p>
	تُعَدّ دوال التوزيع التراكمي cumulative distribution functions -أو CDF اختصارًا- حلًا بديلًا يجنبنا هذه المشاكل، وسيكون هذا المفهوم موضوع دراسة المقال الحالي.
</p>

<p>
	سنستهل حديثنا بشرح مفهوم المئين percentiles قبل البدء بشرح دوال التوزيع التراكمي CDFs.
</p>

<h2>
	المئين percentiles
</h2>

<p>
	إذا خضعت لامتحان موحد سابقًا، فمن المرجح أن تكون تلقيت نتيجتك على صورة مجموع صافي ورتبة مئين percentile rank، وتكون رتبة المئين في سياقنا هذا هي نسبة الأشخاص الذين حصلوا على مجموع أقل من المجموع الذي حصلت عليه أو مجموع يساويه، فإذا كنت في رتبة المئين التسعين، فهذا يعني أنّ أداءك في الامتحان كان بمستوى أو أفضل من تسعين بالمئة ممن خضعوا لهذا الامتحان.
</p>

<p>
	إليك طريقة حساب رتبة المئين لقيمة معيّنة (ويمثلها المتغيّر <code>your_score</code>) بالنسبة للقيم في متسلسلة sequence التي تحوي الدرجات <code>scores</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_12" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">PercentileRank</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">,</span><span class="pln"> your_score</span><span class="pun">):</span><span class="pln">
    count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> score </span><span class="kwd">in</span><span class="pln"> scores</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> score </span><span class="pun">&lt;=</span><span class="pln"> your_score</span><span class="pun">:</span><span class="pln">
            count </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

    percentile_rank </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100.0</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> count </span><span class="pun">/</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> percentile_rank</span></pre>

<p>
	إذا كانت الدرجات في متسلسلة على سبيل المثال هي 55 و66 و77 و88 و99، وكانت نتيجتك هي 88، فستكون رتبة المئين هي 80 والتي تحصل عليها عن طريق المعادلة التالية: <code>100‎ * 4 / 5</code>.
</p>

<p>
	فإذا كانت لديك قيمة معيّنة ،فسيكون حساب رتبة المئين سهل للغاية، إلا أنّ العملية العكسية أصعب بقليل، فإذا أُعطيت رتية مئين وتريد إيجاد القيمة الموافقة لها فسيكون أحد الخيارات المتاحة لديك هي ترتيب القيم، ومن ثم البحث عن القيمة التي تريدها كما في هذه الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_14" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Percentile</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">,</span><span class="pln"> percentile_rank</span><span class="pun">):</span><span class="pln">
    scores</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> score </span><span class="kwd">in</span><span class="pln"> scores</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> </span><span class="typ">PercentileRank</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">,</span><span class="pln"> score</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;=</span><span class="pln"> percentile_rank</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> score</span></pre>

<p>
	نتيجة هذا الحساب هي المئين percentile، فالمئين الخمسين مثلًا هو القيمة ذات رتبة المئين percentile rank الخمسين، ويكون المئين الخمسين في توزيع درجات الامتحان هو 77.
</p>

<p>
	لا يُعَدّ تنفيذ دالة <code>Percentile</code> في الشيفرة السابقة فعالًا، إلا أنه توجد طريقة أفضل، وهي استخدام رتبة المئين percentile rank من أجل حساب فهرس المئين الموافق كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_16" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">Percentile2</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">,</span><span class="pln"> percentile_rank</span><span class="pun">):</span><span class="pln">
    scores</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">()</span><span class="pln">
    index </span><span class="pun">=</span><span class="pln"> percentile_rank </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">scores</span><span class="pun">)-</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">//</span><span class="pln"> </span><span class="lit">100</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> scores</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span></pre>

<p>
	قد يكون التمييز بين "المئين" percentile و"رتبة المئين" percentile rank أمرًا محيّرًا خاصةً أن الناس لا يستخدِمون المصطلحات بدقة دائمًا، ويمكننا القول باختصار تأخذ الدالة <code>PercentileRank</code> قيمة على أساس وسيط لها وتحسب رتبة المئين percentile rank لها في مجموعة من القيم؛ أما الدالة <code>Percentile</code> فهي تأخذ ترتيبًا مئيني وتحسب القيمة الموافقة له.
</p>

<h2>
	دوال التوزيع التراكمي
</h2>

<p>
	والآن بعد شرح مفهومي المئين ورتبة المئين أصبحنا جاهزين لتناول موضوع دالة التوزيع التراكمي Cumulative distribution function -أو CDF اختصارًا-، وهي دالة تحوِّل القيمة إلى ترتيب مئين percentile rank.
</p>

<p>
	تُعَدّ دالة التوزيع التراكمي دالةً لـ x، بحيث تكون x هي أيّ قيمة موجودة في التوزيع، ولتقييم دالة التوزيع التراكمي CDF(‎x‎)‎ لقيمة محدَّدة x علينا حساب نسبة القيم الموجودة في التوزيع والتي هي أقل أو تساوي القيمة x.
</p>

<p>
	لدينا فيما يلي الدالة التي تأخذ وسيطين هما <code>sample</code> وهو متسلسلة sequence و<code>x</code> القيمة التي لدينا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_18" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">EvalCdf</span><span class="pun">(</span><span class="pln">sample</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">):</span><span class="pln">
    count </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.0</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> value </span><span class="kwd">in</span><span class="pln"> sample</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> value </span><span class="pun">&lt;=</span><span class="pln"> x</span><span class="pun">:</span><span class="pln">
            count </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

    prob </span><span class="pun">=</span><span class="pln"> count </span><span class="pun">/</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">sample</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> prob</span></pre>

<p>
	تشبه هذه الدالة دالة <code>PercentileRank</code> إلى حد التطابق تقريبًا، إلا أنّ الفرق الوحيد هو أنّ نتيجة دالة <code>EvalCdf</code> احتمالية في المجال 0-1، في حين تكون نتيجة <code>PercentileRank</code> هي رتبة مئين في المجال 0-100.
</p>

<p>
	لنستعرض مثالًا عن الفكرة السابقة، حيث لدينا عيّنة تحوي القيم <code>[5, 3, 2, 2, 1]</code>، وإليك قيم من دالة التوزيع التراكمي الخاصة بهذه العيّنة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_20" style="">
<span class="pln">CDF</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)=</span><span class="lit">0</span><span class="pln">
CDF</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)=</span><span class="lit">0.2</span><span class="pln">
CDF</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)=</span><span class="lit">0.6</span><span class="pln">
CDF</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)=</span><span class="lit">0.8</span><span class="pln">
CDF</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)=</span><span class="lit">0.8</span><span class="pln">
CDF</span><span class="pun">(</span><span class="lit">5</span><span class="pun">)=</span><span class="lit">1</span></pre>

<p>
	يمكننا تخمين دالة التوزيع التراكمي لأيّ قيمة للمتغير x، أي ليس فقط للقيم الموجودة في العيّنة، فإذا كانت قيمة x أقل من أصغر قيمة موجودة في العيّنة، فإن دالة التوزيع التراكميّ هي 0 أي CDF(x)=0؛ أما إذا كانت قيمتها أعلى من أكبر قيمة، فستساوي دالة التوزيع التراكمي للمتغيّر x الواحد أي CDF(x)=1.
</p>

<p>
	يوضِّح الشكل التالي مثالًا عن دالة توزيع تراكمي CDF.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78325" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3a37ecd_4.2.png.40677c10511cb56bea9b2f97620fb53b.png" rel=""><img alt="الشكل 4.2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78325" data-unique="7axonqvk2" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3a37ecd_4.2.png.40677c10511cb56bea9b2f97620fb53b.png"></a>
</p>

<p>
	يُعَدّ الشكل السابق تمثيلًا رسوميًا لدالة التوزيع التراكمي هذه، كما تُعَدّ دالة التوزيع التراكمي الخاصة بعيّنة دالة خطوة step function.
</p>

<h2>
	تمثيل دوال التوزيع التراكمي
</h2>

<p>
	تزوّدنا مكتبة <code>thinkstats2</code> بصنف class يدعى Cdf ويمثِّل دوال التوزيع التراكمي، وفيما يلي التوابع الأساسية التي يزودنا بها صنف Cdf:
</p>

<ul>
<li>
		<code>(x)Prob</code>: بفرض لدينا قيمة <code>x</code>، فإن هذا التابع يحسب الاحتمال <code>p=CDF(x)</code>
	</li>
	<li>
		<code>(p)Value</code>: بفرض أنه لدينا قيمة احتمال <code>p</code>، فسيحسب هذا التابع القيمة الموافقة <code>x</code>، أي أنّها دالة التوزيع التراكمي العكسية inverse CDF للاحتمال <code>p</code>.
	</li>
</ul>
<p>
	يوضِّح الشكل التالي دالة التوزيع التراكمي لمدة الحمل.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78326" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3acc52b_4.3.png.b19699c39c593ef76e87ef226a61b802.png" rel=""><img alt="الشكل 4.3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78326" data-unique="bsqa9wz1s" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3acc52b_4.3.png.b19699c39c593ef76e87ef226a61b802.png"></a>
</p>

<p>
	يمكن أن يأخذ باني Cdf قائمةً list من القيم على أساس وسيط أو سلسلة بانداز pandas Series، أو Hist، أو Pmf، أو Cdf آخر.
</p>

<p>
	تمثِّل الشيفرة التالية Cdf لتوزيع احتمالي لمدة الحمل في المسح الوطني لنمو الأسرة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_22" style="">
<span class="pln">    live</span><span class="pun">,</span><span class="pln"> firsts</span><span class="pun">,</span><span class="pln"> others </span><span class="pun">=</span><span class="pln"> first</span><span class="pun">.</span><span class="typ">MakeFrames</span><span class="pun">()</span><span class="pln">
    cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">live</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'prglngth'</span><span class="pun">)</span></pre>

<p>
	يزوّدنا <code>thinkplot</code> بدالة تدعى <code>Cdf</code> ترسم دوال التوزيع التراكمي على صورة أسطر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_24" style="">
<span class="pln">   thinkplot</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">cdf</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'weeks'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'CDF'</span><span class="pun">)</span></pre>

<p>
	يُظهر الشكل السابق النتيجة، وإحدى طرق قراءة دالة توزيع تراكمي هي المئينات. فمثلًا، يبدو أنّ 10% من حالات الحمل استمرت فترةً تقل عن 36 أسبوع، بينما لم تتعدى 90% من الحالات مدة 41 أسبوع.
</p>

<p>
	تزوّدنا دالة التوزيع التراكمي بتمثيل رسومي لشكل التوزيع، وتكون القيم الشائعة -التي تظهر عادةً- على شكل أجزاء حادة أو رأسية من دالة التوزيع التراكمي، حيث يكون المنوال mode في هذا المثال وضوحًا 39 أسبوع، كما يوجد عدد قليل من القيم أقل من 30 أسبوع، لذا تكون دالة التوزيع التراكمي في هذا المجال منبسطة flat
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توضيح: الدالة المنبسطة هي دالة منتظمة smooth مستقرها ومنطلقها مجموعة الأعداد الحقيقية ، إلا أنّ جميع مشتقاتها تختفي عند نقطة معيّنة من مجموعة الأعداد الحقيقية .
	</p>
</blockquote>

<p>
	إنّ التعوّد على دوال التوزيع التراكميّ ليس بالمهمة السهلة، فهي تحتاج إلى وقت طويل، لكن حالما تصبح مألوفةً بالنسبة لك ستجد أنها تزودنا بمعلومات أكثر من دوال الكتلة الاحتمالية PMFs وبوضوح أكبر منها أيضًا.
</p>

<h2>
	موازنة دوال التوزيع التراكمي
</h2>

<p>
	تتجلى فائدة دوال التوزيع التراكمي بصورة خاصة في موازنة التوزيعات. فمثلًا، إليك الشيفرة التي ترسم دالة التوزيع التراكمي لأوزان الأطفال الأوائل والأطفال الآخرين عند الولادة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_26" style="">
<span class="pln">   first_cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">firsts</span><span class="pun">.</span><span class="pln">totalwgt_lb</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'first'</span><span class="pun">)</span><span class="pln">
    other_cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">others</span><span class="pun">.</span><span class="pln">totalwgt_lb</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'other'</span><span class="pun">)</span><span class="pln">

    thinkplot</span><span class="pun">.</span><span class="typ">PrePlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Cdfs</span><span class="pun">([</span><span class="pln">first_cdf</span><span class="pun">,</span><span class="pln"> other_cdf</span><span class="pun">])</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'weight (pounds)'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'CDF'</span><span class="pun">)</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="78327" href="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3b5de03_4.4.png.d2039eeba99df4247d39f4af0c7b848f.png" rel=""><img alt="الشكل 4.4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78327" data-unique="e3o3h7lcm" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3b5de03_4.4.png.d2039eeba99df4247d39f4af0c7b848f.png"></a>
</p>

<p>
	يوضِّح الشكل السابق دالة التوزيع التراكمي لأوزان الأطفال الأوائل وبقية الأطفال، كما يُظهر النتيجة، ويمكن أن نلاحظ بالموازنة مع الشكل الأول في هذا المقال أن شكل التوزيعات والفرق بينهما تظهر بوضوح أكبر في الشكل السابق، كما نلاحظ أيضًا أن التوزيع يُظهر أنّ وزن الأطفال الأوائل أخف، بالإضافة إلى وجود تباين أكبر فوق المتوسط mean.
</p>

<h2>
	الإحصائيات المبنية على أساس المئين
</h2>

<p>
	يصبح حساب المئينات ورتبة المئين عمليةً سهلةً عند حساب دالة التوزيع التراكمي، ويزوّدنا الصنف <code>Cdf</code> بالتابعين التاليين:
</p>

<ul>
<li>
		<code>PercentileRank(x)‎</code>: يحسب هذا التابع رتبة المئين لقيمة معيّنة <code>x</code> بالشكل: 100 CDF(x)
	</li>
	<li>
		<code>Percentile(p)‎</code>: يحسب هذا التابع القيمة الموافقة <code>x</code> لرتبة مئين <code>p</code> وهي تساوي Value(p/100)<code>‎</code>.
	</li>
</ul>
<p>
	يمكن استخدام التابع <code>Percentile</code> لحساب إحصائية موجزة مبينة على أساس المئين. فالمئين الخمسين مثلًا هو القيمة التي تقسم التوزيع إلى النصف، ويُعرف أيضًا باسم الوسيط <strong>median</strong> الذي يُعَدّ مقياسًا للنزعة المركزية لتوزيع معيّن مثل المتوسط mean.
</p>

<p>
	توجد في الواقع عدة تعريفات لمفهوم "الوسيط" ولكل منها خصائص مختلفة عن الآخر، إلا أنه من السهل حسابه عن طريق Percentile(50) وهي طريقة فعالة وبسيطة.
</p>

<p>
	يُعدّ <a href="https://ar.wikipedia.org/wiki/%D8%A7%D9%86%D8%AD%D8%B1%D8%A7%D9%81_%D8%B1%D8%A8%D9%8A%D8%B9%D9%8A" rel="external nofollow">الانحراف الربيعي</a> interquartile range -أو IQR اختصارًا- إحصائيةً مبنيةً على أساس المئين، وهو مقياس للانتشار في توزيع معيّن، أي أنّ الانحراف الربيعي هو الفرق بين المئين الخامس والسبعين والمئين الخامس والعشرين.
</p>

<p>
	يُستخدَم المئين عمومًا لتلخيص شكل التوزيع، فغالبًا ما يكون توزيع الدخل مثلًا على صورة نقاط التجزيء الخمسية quintiles أي مقسومة عند المئينات العشرين والأربعين والستين والثمانين؛ أما التوزيعات الأخرى فتُقسم إلى 10 نقاط أعشارية deciles.
</p>

<p>
	يُدعى هذا النوع من الإحصائيات التي تمثل النقاط التي تبعد عن بعضها مسافات متساوية في دالة توزيع تراكمي نقاط التجزيء quantiles، ويمكنك زيارة <a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%AC%D8%B2%D9%8A%D8%A1_(%D8%A5%D8%AD%D8%B5%D8%A7%D8%A1)" rel="external nofollow">الرابط</a> لمزيد من المعلومات.
</p>

<h2>
	الأعداد العشوائية
</h2>

<p>
	لنفترض أننا اخترنا عيّنةً عشوائيةً من مجموعة الولادات الحية وننظر إلى رتبة المئين لأوزان الأطفال عند الولادة، ومن ثم لنفترض أننا حسبنا دالة التوزيع التراكمي لرتب المئين، برأيك كيف سيبدو التوزيع؟
</p>

<p>
	إليك كيفية حسابه، لكن في البداية يجب إنشاء دالة التوزيع التراكمي Cdf لأوزان الولادات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_28" style="">
<span class="pln">    weights </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">.</span><span class="pln">totalwgt_lb
    cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">weights</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'totalwgt_lb'</span><span class="pun">)</span></pre>

<p>
	ومن ثم نولِّد عيّنةً ونحسب رتبة المئين لكل قيمة في العيّنة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_30" style="">
<span class="pln">    sample </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">choice</span><span class="pun">(</span><span class="pln">weights</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">,</span><span class="pln"> replace</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span><span class="pln">
    ranks </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">cdf</span><span class="pun">.</span><span class="typ">PercentileRank</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> sample</span><span class="pun">]</span></pre>

<p>
	بحيث تكون <code>sample</code> عيّنةً عشوائيةً لأوزان 100 ولادة مُختارة مع الاستبدال replacement، أي أنّه يمكن اختيار القيمة نفسها أكثر من مرة، وكذلك تكون <code>ranks</code> قائمةً list من رتب المئين.
</p>

<p>
	يمكننا الآن إنشاء ورسم دالة التوزيع التراكمي لرتب المئين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_32" style="">
<span class="pln">   rank_cdf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">ranks</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Cdf</span><span class="pun">(</span><span class="pln">rank_cdf</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'percentile rank'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'CDF'</span><span class="pun">)</span></pre>

<p style="text-align: center;">
	<img alt="الشكل 4.5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="78328" data-unique="jjqd17d7i" src="https://academy.hsoub.com/uploads/monthly_2021_09/6155ea3bce805_4.5.png.d93aca060d71730ba342f133c7dd2990.png"></p>

<p>
	يوضَّح الشكل السابق دالة التوزيع التراكمي لرتب المئين لعينة عشوائية من أوزان الولادات، كما يُظهر النتيجة، بحيث تكون دالة التوزيع التراكمي خطًا مستقيمًا أي أنّ التوزيع موحَّد.
</p>

<p>
	قد لا يكون هذا الخرج واضحًا إلا أنّه نتج بسبب طريقة تعريف دالة التوزيع التراكمي، حيث يُظهر هذا الشكل أن 10% من العيّنة هي تحت المئين العاشر، و20% من العيّنة تحت رتبة المئين العشرين، وهكذا، كما كنا متوقعين.
</p>

<p>
	لذا يكون توزيع رتب المئين موحَّدًا بعض النظر عن شكل دالة التوزيع التراكمي، وتُعَدّ هذه الخاصية مفيدةً لأنها أساس لخوارزمية بسيطة وفعالة تولِّد أعداد عشوائية في حال وجود دالة توزيع تراكمي، وذلك عن طريق اتباع الطريقة التالية:
</p>

<ul>
<li>
		اختر رتبة مئين بصورة موحَّدة من المجال 0-100.
	</li>
	<li>
		استخدِم <code>Cdf.Percentile</code> من أجل إيجاد القيمة الموجودة في التوزيع والتي توافق رتبة المئين التي اخترتها.
	</li>
</ul>
<p>
	يزوّدنا Cdf بتنفيذ لهذه الخوارزمية ويدعى <code>Random</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_34" style="">
<span class="com"># class Cdf:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> self</span><span class="pun">.</span><span class="typ">Percentile</span><span class="pun">(</span><span class="pln">random</span><span class="pun">.</span><span class="pln">uniform</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">100</span><span class="pun">))</span></pre>

<p>
	كما يزودنا Cdf بـ <code>Sample</code> التي تأخذ عددًا صحيحًا <code>n</code>، وتُعيد قائمةً عدد عناصرها <code>n</code> وقيمها مُختارة عشوائيًا من Cdf.
</p>

<h2>
	موازنة رتب المئين
</h2>

<p>
	تفيد رُتب المئين percentile ranks في موازنة المقاييس في مجموعات مختلفة، إذ يُجمع الأشخاص الذين يشاركون في سباقات الركض مثلًا حسب العمر والجنس عادةً، كما يمكنك تحويل وقت السباق إلى رُتب مئين لموازنة الأشخاص في المجموعات العمرية المختلفة.
</p>

<p>
	شارك آلان بي داوني Allen B. Downey في سباق جيمس جويس رامبل بطول مسار 10 كيلومتر في ديدهام في ماساتشوستس منذ عدة سنوات، وكان في ترتيب 97 من أصل 1633، أي تغلّب على أو تعادل مع 1633 عدّاء، وهذا يعني أنّ رتبة المئين الخاصة به في الملعب كانت 94%.
</p>

<p>
	يمكننا عمومًا حساب رتبة المئين باستخدام الموقع وحجم الملعب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_36" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">PositionToPercentile</span><span class="pun">(</span><span class="pln">position</span><span class="pun">,</span><span class="pln"> field_size</span><span class="pun">):</span><span class="pln">
    beat </span><span class="pun">=</span><span class="pln"> field_size </span><span class="pun">-</span><span class="pln"> position </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    percentile </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100.0</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> beat </span><span class="pun">/</span><span class="pln"> field_size
    </span><span class="kwd">return</span><span class="pln"> percentile</span></pre>

<p>
	كانت مرتبته 26 من أصل 256 في فئته العمرية التي كان يُشار إليها بـ M4049، والتي تعني ذّكر male بين عمري 40 و49، وبالتالي كانت رتبة المئين الخاصة بي في فئته العمرية هي 90%، وإذا لم يتوقف عن الركض بعد 10 سنوات -وهو يأمل ذلك-، فسيصبح في فئة M5059.
</p>

<p>
	لنفترض الآن أنّ رتبة المئين الخاصة به في الفئة العمرية هذه لم تتغير، كم سأكون أبطأ حينها؟ يمكننا الإجابة عن هذا السؤال عن طريق تحويل رتبة المئين في الفئة M4049 إلى موقع في الفئة M5059، وإليك الشيفرة التي تعبر عن ذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3706_38" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">PercentileToPosition</span><span class="pun">(</span><span class="pln">percentile</span><span class="pun">,</span><span class="pln"> field_size</span><span class="pun">):</span><span class="pln">
    beat </span><span class="pun">=</span><span class="pln"> percentile </span><span class="pun">*</span><span class="pln"> field_size </span><span class="pun">/</span><span class="pln"> </span><span class="lit">100.0</span><span class="pln">
    position </span><span class="pun">=</span><span class="pln"> field_size </span><span class="pun">-</span><span class="pln"> beat </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> position</span></pre>

<p>
	كان هناك 171 شخصًا في الفئة M5059، لذا يجب أن يكون في المكان السابع عشر أو الثامن عشر ليكون لديه رتبة المئين نفسها، كما أنّ زمن انتهاء العدّاء رقم 17 في الفئة M5059 كان 46:05، أي يجب أن يصل بهذا الوقت لكي يحافظ على رتبة المئين.
</p>

<h2>
	تمارين
</h2>

<p>
	يمكنك البدء بـ <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/chap04ex.ipynb" rel="external nofollow">chap04ex.ipynb</a></code> من أجل التمارين التالية، علمًا أنّ الحل الخاص بنا موجود في ملف <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/solutions/chap04soln.ipynb" rel="external nofollow">chap04soln.ipynb</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub حيث ستجد كل الشيفرات والملفات المطلوبة.
</p>

<h3>
	تمرين 1
</h3>

<p>
	كم كان وزنك عندما ولدت؟ إذا لم يكن لديك الجواب فبإمكانك الاتصال بوالدتك أو أحد آخر يملك الجواب، وباستخدام بيانات المسح الوطني لنمو الأسرة لكل الولادات الحية؛ احسب توزيع أوزان الولادات، ومن ثم استخدمه لحساب رتبة المئين الخاصة بك.
</p>

<p>
	إذا كنت الطفل الأول في عائلتك، فاحسب رتبة المئين الخاصة بك في توزيع الأطفال الأوائل، وإلا فاستخدم توزيع الأطفال الآخرين. وإذا كنت في المئين التسعين أو أكثر، فاتصل بوالدتك واعتذر إليها.
</p>

<h3>
	تمرين 2
</h3>

<p>
	من المفترض أن تكون الأعداد التي تولِّدها <code>random.random</code> موحَّدةً بين 0 و1، أي يجب أن يكون لكل قيمة في المجالالاحتمال نفسه.
</p>

<p>
	ولِّد 1000 عدد باستخدام الدالة <code>random.random</code> وارسم دالة الكتلة الاحتمالية ودالة التوزيع التراكمي لها. هل وجدت أنّ التوزيع موحَّد؟
</p>

<h2>
	المفاهيم الأساسية
</h2>

<ul>
<li>
		<strong>رتبة المئين percentile rank</strong>: تشير إلى النسبة المئوية للقيم الموجودة في توزيع معيّن والتي تساوي قيمة محدَّدة أو أصغر منها.
	</li>
	<li>
		<strong>المئين percentile</strong>: القيمة المرتبطة برتبة مئين معطاة.
	</li>
	<li>
		<strong>دالة التوزيع التراكمي cumulative distribution function -أو CDF اختصارًا-</strong>: دالة تحوِّل القيم إلى احتمالاتها التراكمية، حيث أنّ CDF(x) هو نسبة القيم من العيّنة التي إما تساوي x أو أصغر منها.
	</li>
	<li>
		<strong>دالة التوزيع التراكمي العكسية inverse CDF</strong>: دالة تحوِّل الاحتمال التراكمي <code>p</code> إلى القيمة الموافقة له.
	</li>
	<li>
		<strong>الوسيط median</strong>: وهو المئين الخمسون -أي 50th percentile-، وغالبًا ما يُستخدَم على أساس مقياس للنزعة المركزيّة central tendency.
	</li>
	<li>
		<strong>الانحراف الربيعي interquartile range</strong>: الفرق بين المئين الخامس والسبعين 75th percentile والمئين الخامس والعشرين 25th percentile، ويُستخدَم على أساس مقياس للانتشار.
	</li>
	<li>
		<strong>نقطة التجزيء quantile</strong>: متسلسلة من القيم التي توافق الترتيبات المئينة التي تبعد عن بعضها مسافات متساوية، فنقاط التجزيء لتوزيع ما هي المئين رقم 25 والمئين رقم 50 والمئين رقم 75.
	</li>
	<li>
		<strong>الاستبدال replacement</strong>: خاصية من خواص عملية اختيار العيّنات sampling، حيث يشير المصطلح "مع استبدال" إلى أنه يمكن استخدام القيمة نفسها أكثر من مرة، كما يشير مصطلح "بدون استبدال" إلى أنه حالما تُختار القيمة فإنها تُحذَف من المجموعة السكانية.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a href="https://greenteapress.com/thinkstats2/html/thinkstats2005.html" rel="external nofollow">Chapter 4 Cumulative distribution functions analysis</a> من كتاب <a href="https://greenteapress.com/wp/think-stats-2e" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1303/" rel="">دوال الكتلة الاحتمالية في جافاسكريبت</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1303/" rel="">دوال الكتلة الاحتمالية في جافاسكريبت</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">التوزيعات الإحصائية في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1331</guid><pubDate>Sat, 28 Aug 2021 15:00:00 +0000</pubDate></item><item><title>&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x643;&#x62A;&#x644;&#x629; &#x627;&#x644;&#x627;&#x62D;&#x62A;&#x645;&#x627;&#x644;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%83%D8%AA%D9%84%D8%A9-%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%85%D8%A7%D9%84%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1303/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/6129410e9bb3b_--.png.769b163bcd96fdb495a0e12e0c045d1f.png" /></p>

<p>
	قبل البدء في ذكر تفاصيل المقال، تجدر الإشارة إلى أنه توجد الشيفرة الخاصة بهذا المقال في ملف <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/probability.py" rel="external nofollow">probability.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub.
</p>

<h2>
	دوال الكتلة الاحتمالية
</h2>

<p>
	تُعَد دالة الكتلة الاحتمالية probability mass function -أو PMF اختصارًا- طريقةً أخرى لتمثيل التوزيع، وهي دالة تحوّل القيمة إلى احتمالها.
</p>

<p>
	الاحتمال هو تردد يُعبَّر عنه على أساس كسر من حجم العينة <code>n</code>، حيث نقسِّم التردد على n لتحويله إلى احتمال، وهذا ما يُسمى بالتوحيد normalization.
</p>

<p>
	إذا كان لدينا مدرَّج تكراري Hist، فيمكننا إنشاء قاموس dictionary يربط كل قيمة باحتمالها، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_10" style="">
<span class="pln">n </span><span class="pun">=</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Total</span><span class="pun">()</span><span class="pln">
d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> freq </span><span class="kwd">in</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Items</span><span class="pun">():</span><span class="pln">
    d</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> freq </span><span class="pun">/</span><span class="pln"> n</span></pre>

<p>
	أو يمكننا استخدام الصنف Pmf الموجود في <code>thinkstats2</code>.
</p>

<p>
	يأخذ باني الصنف Pmf مثل Hist قائمةً أو pandas Series -أي سلسلة بانداز- أو قاموسًا dictionary، أو مدرَّجًا تكراريًا Hist، أو كائن Pmf آخر، وإليك مثالًا عن استخدام قائمة بسيطة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_14" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> thinkstats2
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Pmf</span><span class="pun">([</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf
</span><span class="typ">Pmf</span><span class="pun">({</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0.2</span><span class="pun">})</span></pre>

<p>
	سنلاحظ هنا أنّ صنف Pmf موحّد بحيث يكون الاحتمال الكلي هو 1. يتشابه الكائنان Pmf وHist في الكثير من الأمور، إذ يرثان الكثير من التوابع صنف أب مشترك، حيث يؤدي التابعان <code>Values</code> و<code>items</code> مثلًا العمل نفسه في كل من Hist وPmf، ويكمن الفرق الأكبر في أنّ Hist يحوّل القيم إلى عدّاد صحيح integer counters؛ أما Pmf فيحوِّل القيم إلى احتمال عشري floating-point probabilities. ويمكن استخدام <code>Prob</code> للبحث عن الاحتمال المرتبط بقيمة معينة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_17" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Prob</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0.4</span></pre>

<p>
	كما يمكننا في هذه الحالة استخدام عامِل القوس المربع [] للحصول على النتيجة نفسها كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_20" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
</span><span class="lit">0.4</span></pre>

<p>
	يمكن تعديل Pmf حالي بزيادة الاحتمال المرتبط بقيمة معينة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_22" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Incr</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.2</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Prob</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0.6</span></pre>

<p>
	أو ضرب الاحتمال بمعامل factor كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_24" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Mult</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.5</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Prob</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0.3</span></pre>

<p>
	إذا عدَّلت Pmf ما، فقد تكون النتيجة غير موحَّدة، أي قد لا يكون مجموع الاحتمالات 1، ويمكننا هنا استدعاء دالة <code>Total</code> التي تُعيد مجموع الاحتمالات للتحقق من هذا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_26" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Total</span><span class="pun">()</span><span class="pln">
</span><span class="lit">0.9</span></pre>

<p>
	كما يمكننا استدعاء <code>Normalize</code> لإعادة التوحيد:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_28" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Normalize</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Total</span><span class="pun">()</span><span class="pln">
</span><span class="lit">1.0</span></pre>

<p>
	يوفّر كائن Pmf التابع <code>Copy</code> الذي يعمل على إنشاء وتعديل نسخة دون التأثير على النسخة الأصلية. وقد تبدو الصيغة المذكورة في هذه الفقرة غير متّسقة، إلا أنّ كل التسميات السابقة تجري وفق نظام معيَّن كما يلي:
</p>

<p>
	يدلّ Pmf على الصنف class، ويدل <code>pmf</code> على نسخة instance من الصنف؛ أما PMF فهو مصطلح الدالة الكتلة الاحتمالية الرياضي.
</p>

<h2>
	رسم دوال الكتلة الاحتمالية
</h2>

<p>
	يوفِّر <code>thinkplot</code> طريقتَين لرسم دوال الكتلة الاحتمالية:
</p>

<ul>
<li>
		يمكن استخدام <code>thinkplot.Hist</code> لرسم دالة الكتلة الاحتمالية على أساس رسم بياني شريطي، حيث يكون الرسم البياني الشريطي مفيدًا جدًا إذا كان عدد القيم في Pmf صغيرًا.
	</li>
	<li>
		يمكن استخدام <code>thinkplot.Pmf</code> لرسم دالة الكتلة الاحتمالية على أساس دالة خطوة step function، كما يُعدّ هذا الخيار مفيدًا جدًا في حال وجود عدد كبير من القيم وفي حال كانت دالة الكتلة الاحتمالية منتظمة، في حين تعمل هذه الدالة مع كائنات Hist أيضًا.
	</li>
</ul>
<p>
	يزودنا <code>pyplot</code> أيضًا بدالة تُدعى <code>hist</code>؛ حيث تأخذ متسلسلةً من القيم ثم تحسب المدرَّج التكراري وترسمه، كما لا نستخدِم <code>pyplot.hist</code> عادةً لأننا نستخدِم كائنات Hist.
</p>

<p style="text-align: center;">
	<img alt="الشكل 3.1.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75577" data-unique="yr2omtp54" src="https://academy.hsoub.com/uploads/monthly_2021_08/612941201211c_3.1.jpg.60fd0dfd29a5ef2ebe2a51b4b217d1fa.jpg"></p>

<p>
	يُظهِر الشكل السابق دالة الكتلة الاحتمالية لمدة الحمل بالأطفال الأوائل وبقية الأطفال، وذلك باستخدام الرسم البياني الشريطي الموجود على يسار الشكل ودالة الخطوة الموجودة على يمين الشكل.
</p>

<p>
	يمكننا موازنة التوزيعين من دون أن يضللنا الفرق في حجم العيّنة بين التوزيعين، وذلك برسم دالة الكتلة الاحتمالية PMF بدلًا من رسم المدرَّج التكراري histogram.
</p>

<p>
	بناءً على هذا الشكل يكون احتمال ولادة الطفل الأول في الوقت المحدد -أي في الأسبوع التاسع والثلاثين 39- أقل من البقية، ومن المحتمل أكثر أن يتأخر في الولادة أي حتى الأسبوع 41 والأسبوع 42.
</p>

<p>
	تكون الشيفرة التي تولِّد الشكل السابق كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_30" style="">
<span class="pln">    thinkplot</span><span class="pun">.</span><span class="typ">PrePlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> cols</span><span class="pun">=</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">first_pmf</span><span class="pun">,</span><span class="pln"> align</span><span class="pun">=</span><span class="str">'right'</span><span class="pun">,</span><span class="pln"> width</span><span class="pun">=</span><span class="pln">width</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">other_pmf</span><span class="pun">,</span><span class="pln"> align</span><span class="pun">=</span><span class="str">'left'</span><span class="pun">,</span><span class="pln"> width</span><span class="pun">=</span><span class="pln">width</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Config</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'weeks'</span><span class="pun">,</span><span class="pln">
                     ylabel</span><span class="pun">=</span><span class="str">'probability'</span><span class="pun">,</span><span class="pln">
                     axis</span><span class="pun">=[</span><span class="lit">27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">46</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.6</span><span class="pun">])</span><span class="pln">

    thinkplot</span><span class="pun">.</span><span class="typ">PrePlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">SubPlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Pmfs</span><span class="pun">([</span><span class="pln">first_pmf</span><span class="pun">,</span><span class="pln"> other_pmf</span><span class="pun">])</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'weeks'</span><span class="pun">,</span><span class="pln">
                   axis</span><span class="pun">=[</span><span class="lit">27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">46</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0.6</span><span class="pun">])</span></pre>

<p>
	تأخذ <code>PrePlot</code> معاملَين اختياريّين هما <code>rows</code> و<code>cols</code> لتصنع شبكةً من الأشكال، وفي حالتنا هذه سيتوضَّع شكلان في سطر واحد، حيث يُظهر الشكل الأول الموجود في الجهة اليسرى الـ Pmfs باستخدام <code>thinkplot.Hist</code> كما رأينا سابقًا؛ أمّا الاستدعاء الثاني لـ <code>PrePlot</code> فهو يضبط مولّد اللون، ومن ثمّ ينتقل <code>SubPlot</code> إلى الشكل الثاني الموجود في الجهة اليمنى ويعرض الـ Pmfs باستخدام <code>thinkplot.Pmfs</code>، كما استخدِم خيار <code>axis</code> لضمان توضُّع الشكلين على المحاور ذاتها، وهذه فكرة جيّدة إذا كان الهدف هو الموازنة بين شكلين اثنين.
</p>

<h2>
	رسوم بيانية أخرى
</h2>

<p>
	تفيد كل من دوال الكتلة الاحتمالية والمدرَّجات التكرارية في اسكتشاف البيانات ومحاولة تحديد الأنماط patterns والعلاقات relationships، لكن حالما نعلم بما يحصل، فستصبح الخطوة التالية الجيدة هي تصميم رسم بياني يجعل الأنماط التي حدَّدتها واضحةً قدر الإمكان.
</p>

<p>
	تكون الفوارق الكبرى في التوزيعات في بيانات المسح الوطني لنمو الأسرة NSFG قريبةً من المنوال mode، لذا فمن المنطقي تكبير الصورة على هذا الجزء من الرسم البياني وتحويل البيانات للتأكد من الاختلافات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_32" style="">
<span class="pln">    weeks </span><span class="pun">=</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">35</span><span class="pun">,</span><span class="pln"> </span><span class="lit">46</span><span class="pun">)</span><span class="pln">
    diffs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> week </span><span class="kwd">in</span><span class="pln"> weeks</span><span class="pun">:</span><span class="pln">
        p1 </span><span class="pun">=</span><span class="pln"> first_pmf</span><span class="pun">.</span><span class="typ">Prob</span><span class="pun">(</span><span class="pln">week</span><span class="pun">)</span><span class="pln">
        p2 </span><span class="pun">=</span><span class="pln"> other_pmf</span><span class="pun">.</span><span class="typ">Prob</span><span class="pun">(</span><span class="pln">week</span><span class="pun">)</span><span class="pln">
        diff </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="pln">p1 </span><span class="pun">-</span><span class="pln"> p2</span><span class="pun">)</span><span class="pln">
        diffs</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">diff</span><span class="pun">)</span><span class="pln">

    thinkplot</span><span class="pun">.</span><span class="typ">Bar</span><span class="pun">(</span><span class="pln">weeks</span><span class="pun">,</span><span class="pln"> diffs</span><span class="pun">)</span></pre>

<p>
	يدل المتغير <code>weeks</code> في الشيفرة السابقة على مجال الأسابيع؛ أما <code>diffs</code> فهو الفارق بين دالتي كتلة احتمالية بالنقاط المئوية.
</p>

<p>
	يُظهِر الشكل التالي النتيجة على أساس مخطط شريطي bar chart، كما يُظهِر هذا الشكل النمط بوضوح أكبر، إذ يشير إلى قلة احتمال ولادة الأطفال الأوائل في الأسبوع 39، ويزداد احتمال الولادة في الأسبوعين 41 و42.
</p>

<p style="text-align: center;">
	<img alt="الشكل 3.2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="75578" data-unique="lwe8oqtdz" src="https://academy.hsoub.com/uploads/monthly_2021_08/61294120827e1_3.2.png.379c13dab6e41ec6dc7ad2b4de7e704e.png"></p>

<p>
	كما يُظهِر الشكل السابق الفرق بالنقاط المئوية أسبوعيًا.
</p>

<p>
	لنضع هذه النتيجة نصب أعيننا مبدئيًا ومؤقتًا فحسب، حيث استخدمنا مجموعة البيانات نفسها لتحديد الفرق الواضح ومن ثم اخترنا تصورًا يجعل هذا الفرق واضحًا، إلا أنه لا يمكننا التأكد من أنّ هذا التأثير حقيقي، إذ يُمكن أن يكون بسبب التباين العشوائي، لكننا سنعالِج هذا لاحقًا.
</p>

<h2>
	مفارقة حجم الصفوف الدراسية
</h2>

<p>
	سنوضِّح قبل المتابعة أحد أنواع الحسابات التي يمكننا إجراؤها باستخدام كائنات Pmf، وسنسمّي هذا المثال: "مفارقة حجم الصف الدراسي"
</p>

<p>
	تكون نسبة الطلاب إلى أعضاء الهيئة التدريسية في الكثير من الجامعات والكليّات الأمريكية هي حوالي 10:1، ولكن غالبًا ما يفاجَأ الطلاب أن المتوسط الحسابي لحجم الصف الدراسي الذي يدرسون فيه أكبر من 10. ولهذا التناقض سببين اثنين هما:
</p>

<ul>
<li>
		يدرس الطلاب عادةً حوالي 4 - 5 صفوف دراسية في الفصل الدراسي الواحد، لكن غالبًا ما يدرِّس الأستاذ حوالي صفًا أو صفَين دراسيَين.
	</li>
	<li>
		يفضل عدد قليل من الطلاب التواجد في صف دراسي صغير، إلا أنّ عدد الطلاب كبير في صف دراسي ضخم.
	</li>
</ul>
<p>
	بالطبع فإنّ التاثير الأول واضح، كما يصبح واضحًا حالما يُشار إليه على الأقل، كما أنّ التأثير الثاني أقل وضوحًا، وسنأخذ مثالًا على هذا كما يلي:
</p>

<p>
	لنفترض أنّ الكليّة توفِّر 65 صفًا دراسيًا في الفصل الدراسيّ الواحد مع التوزيع التالي للأحجام:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_34" style="">
<span class="pln"> size      count
 </span><span class="lit">5</span><span class="pun">-</span><span class="pln"> </span><span class="lit">9</span><span class="pln">          </span><span class="lit">8</span><span class="pln">
</span><span class="lit">10</span><span class="pun">-</span><span class="lit">14</span><span class="pln">          </span><span class="lit">8</span><span class="pln">
</span><span class="lit">15</span><span class="pun">-</span><span class="lit">19</span><span class="pln">         </span><span class="lit">14</span><span class="pln">
</span><span class="lit">20</span><span class="pun">-</span><span class="lit">24</span><span class="pln">          </span><span class="lit">4</span><span class="pln">
</span><span class="lit">25</span><span class="pun">-</span><span class="lit">29</span><span class="pln">          </span><span class="lit">6</span><span class="pln">
</span><span class="lit">30</span><span class="pun">-</span><span class="lit">34</span><span class="pln">         </span><span class="lit">12</span><span class="pln">
</span><span class="lit">35</span><span class="pun">-</span><span class="lit">39</span><span class="pln">          </span><span class="lit">8</span><span class="pln">
</span><span class="lit">40</span><span class="pun">-</span><span class="lit">44</span><span class="pln">          </span><span class="lit">3</span><span class="pln">
</span><span class="lit">45</span><span class="pun">-</span><span class="lit">49</span><span class="pln">          </span><span class="lit">2</span></pre>

<p>
	إذا سألت عميد الكليّة عن المتوسط الحسابي لحجم الصف الدراسي، فسيبني دالة كتلة احتمالية ويحسب المتوسط mean، ويبلغك بأنّ المتوسط الحسابي لحجم الصف الدراسي هو 23.7، وستكون الشيفرة الموافقة لهذا كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_36" style="">
<span class="pln">    d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">7</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="pln"> </span><span class="lit">14</span><span class="pun">,</span><span class="pln"> </span><span class="lit">22</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> 
          </span><span class="lit">27</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">32</span><span class="pun">:</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">37</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">47</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">}</span><span class="pln">

    pmf </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Pmf</span><span class="pun">(</span><span class="pln">d</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'actual'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'mean'</span><span class="pun">,</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Mean</span><span class="pun">())</span></pre>

<p>
	لكن إذا أجريت مسحًا لمجموعة من الطلاب وسألتهم عن عدد الطلاب في صفهم وحسبت المتوسط، فسنعتقِد أنّ المتوسط الحسابي للصف الدراسي أكبر، لكن دعنا نرى كم سيكون أكبر.
</p>

<p>
	سنحسب في البداية التوزيع حسب ملاحظة الطلاب، حيث يكون الاحتمال المرتبط بحجم الصف الدراسي "منحازًا biased" إلى عدد الطلاب في الصف الدراسي.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_38" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">BiasPmf</span><span class="pun">(</span><span class="pln">pmf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">):</span><span class="pln">
    new_pmf </span><span class="pun">=</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Copy</span><span class="pun">(</span><span class="pln">label</span><span class="pun">=</span><span class="pln">label</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Items</span><span class="pun">():</span><span class="pln">
        new_pmf</span><span class="pun">.</span><span class="typ">Mult</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> x</span><span class="pun">)</span><span class="pln">

    new_pmf</span><span class="pun">.</span><span class="typ">Normalize</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> new_pmf</span></pre>

<p>
	لكل صف دراسي حجم هو x، وسنضرب الاحتمال بـ x وهو عدد الطلاب الذين يلاحظون حجم الصف الدراسي، حيث ستكون النتيجة هي Pmf جديد يمثِّل التوزيع المتحيِّز، ويمكننا رسم التوزيع الحقيقي والمُلاحظ كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_40" style="">
<span class="pln">    biased_pmf </span><span class="pun">=</span><span class="pln"> </span><span class="typ">BiasPmf</span><span class="pun">(</span><span class="pln">pmf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'observed'</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">PrePlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Pmfs</span><span class="pun">([</span><span class="pln">pmf</span><span class="pun">,</span><span class="pln"> biased_pmf</span><span class="pun">])</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'class size'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'PMF'</span><span class="pun">)</span></pre>

<p style="text-align: center;">
	<img alt="الشكل 3.3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="75576" data-unique="09xob2nyx" src="https://academy.hsoub.com/uploads/monthly_2021_08/6129411ed7658_3.3.png.54cbaff941fefa15ede3a119acf6b96d.png"></p>

<p>
	يُظهر الشكل السابق توزيع أحجام الصفوف الدراسية الفعلية والملاحظة من قِبَل الطلاب، كما يُظهِر النتيجة، حيث نرى أنه في التوزيع المتحيِّز هناك عدد أقل من الصفوف الدراسية ذات العدد الطلابي القليل، وعدد أكبر من الصفوف الدراسية ذات العدد الطلابي الكبير، كما يكون متوسط التوزيع المتحِيّز هو 29.1، أي أعلى بحوالي 25% من المتوسط الفعلي.
</p>

<p>
	من الممكن عكس هذه العملية أيضًا، حيث ستفترض أنك تريد إيجاد توزيع أحجام الصفوف الدراسية في الكليّة، ولكن لم يتسنّ لك الحصول على بيانات موثوقة من العميد، لذا سيكون البديل هو اختيار عيّنة عشوائية من الطلّاب وسؤالهم عن عدد الطلاب في صفوفهم الدراسية.
</p>

<p>
	ستكون النتيجة متحيِّزةً للأسباب التي ناقشناها للتو، ولكن يمكنك استخدامها لتقدير التوزيع الفعلي. وستجعل الدالة التالية الـ Pmf غير متحيِّزة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_42" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">UnbiasPmf</span><span class="pun">(</span><span class="pln">pmf</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">):</span><span class="pln">
    new_pmf </span><span class="pun">=</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Copy</span><span class="pun">(</span><span class="pln">label</span><span class="pun">=</span><span class="pln">label</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">for</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> p </span><span class="kwd">in</span><span class="pln"> pmf</span><span class="pun">.</span><span class="typ">Items</span><span class="pun">():</span><span class="pln">
        new_pmf</span><span class="pun">.</span><span class="typ">Mult</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1.0</span><span class="pun">/</span><span class="pln">x</span><span class="pun">)</span><span class="pln">

    new_pmf</span><span class="pun">.</span><span class="typ">Normalize</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> new_pmf</span></pre>

<p>
	تشبه الدالة السابقة دالة <code>BiasPmf</code>، إلا أنّ الفارق الوحيد هو تقسيم <code>BiasPmf</code> كل احتمال على x بدلًا من إجراء عملية الجداء.
</p>

<h2>
	فهرسة إطار البيانات
</h2>

<p>
	سنلقي الآن نظرةً على تحديد الأسطر، حيث سننشئ بدايةً مصفوفة نمباي NumPy تحوي أعدادًا عشوائيةً سنستخدمها لتهيئة إطار بيانات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_44" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> pandas
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> array </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">random</span><span class="pun">.</span><span class="pln">randn</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">DataFrame</span><span class="pun">(</span><span class="pln">array</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df
          </span><span class="lit">0</span><span class="pln">         </span><span class="lit">1</span><span class="pln">
</span><span class="lit">0</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">  </span><span class="lit">0.300774</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.074350</span><span class="pln">  </span><span class="lit">0.039621</span><span class="pln">
</span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.369968</span><span class="pln">  </span><span class="lit">0.545897</span></pre>

<p>
	تُرَقَّم الأسطر والأعمدة بدءًا من الصفر في الحالة الافتراضية، لكن يمكنك تزويد الأعمدة بأسماء كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_46" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> columns </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'A'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'B'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">DataFrame</span><span class="pun">(</span><span class="pln">array</span><span class="pun">,</span><span class="pln"> columns</span><span class="pun">=</span><span class="pln">columns</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df
          A         B
</span><span class="lit">0</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">  </span><span class="lit">0.300774</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">-</span><span class="lit">0.074350</span><span class="pln">  </span><span class="lit">0.039621</span><span class="pln">
</span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1.369968</span><span class="pln">  </span><span class="lit">0.545897</span><span class="pln"> </span></pre>

<p>
	كما يمكنك إعطاء أسماء للأسطر، حيث تُدعى مجموعة أسماء الأسطر بالفهرس index، وتدعى أسماء الأسطر نفسها بالعناوين labels.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_48" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> index </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'d'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df </span><span class="pun">=</span><span class="pln"> pandas</span><span class="pun">.</span><span class="typ">DataFrame</span><span class="pun">(</span><span class="pln">array</span><span class="pun">,</span><span class="pln"> columns</span><span class="pun">=</span><span class="pln">columns</span><span class="pun">,</span><span class="pln"> index</span><span class="pun">=</span><span class="pln">index</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df
          A         B
a </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
b </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">  </span><span class="lit">0.300774</span><span class="pln">
c </span><span class="pun">-</span><span class="lit">0.074350</span><span class="pln">  </span><span class="lit">0.039621</span><span class="pln">
d </span><span class="pun">-</span><span class="lit">1.369968</span><span class="pln">  </span><span class="lit">0.545897</span></pre>

<p>
	وكما رأينا في <a data-ss1633772096="1" href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">المقال السابق</a>، تُحدِّد الفهرسة البسيطة عمودًا وتُعيد سلسلةً Series كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_51" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">[</span><span class="str">'A'</span><span class="pun">]</span><span class="pln">
a   </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">
b   </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">
c   </span><span class="pun">-</span><span class="lit">0.074350</span><span class="pln">
d   </span><span class="pun">-</span><span class="lit">1.369968</span><span class="pln">
</span><span class="typ">Name</span><span class="pun">:</span><span class="pln"> A</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">:</span><span class="pln"> float64</span></pre>

<p>
	يمكننا استخدام سمة <code>loc</code> لتحديد سطر عن طريق عنوانه، والتي تُعيد سلسلةً Series كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_55" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">loc</span><span class="pun">[</span><span class="str">'a'</span><span class="pun">]</span><span class="pln">
A   </span><span class="pun">-</span><span class="lit">0.14351</span><span class="pln">
B    </span><span class="lit">0.61605</span><span class="pln">
</span><span class="typ">Name</span><span class="pun">:</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">:</span><span class="pln"> float64</span></pre>

<p>
	إذا علِمت موقع السطر الذي من نمط integer، فيمكنك استخدام سمة <code>iloc</code> بدلًا من عنوانه، والتي تُعيد سلسلةً Series أيضًا، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_57" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">iloc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
A   </span><span class="pun">-</span><span class="lit">0.14351</span><span class="pln">
B    </span><span class="lit">0.61605</span><span class="pln">
</span><span class="typ">Name</span><span class="pun">:</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">:</span><span class="pln"> float64</span></pre>

<p>
	يمكن أن تأخذ السمة <code>loc</code> قائمةً من العناوين وتكون النتيجة في هذه الحالة إطار بيانات DataFrame، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_59" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> indices </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">loc</span><span class="pun">[</span><span class="pln">indices</span><span class="pun">]</span><span class="pln">
         A         B    
a </span><span class="pun">-</span><span class="lit">0.14351</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
c </span><span class="pun">-</span><span class="lit">0.07435</span><span class="pln">  </span><span class="lit">0.039621</span><span class="pln"> </span></pre>

<p>
	كما يمكنك في النهاية استخدام شريحة slice لتحديد مجالًا من الأسطر عن طريق عنوان العنوان بالصورة التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_62" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">[</span><span class="str">'a'</span><span class="pun">:</span><span class="str">'c'</span><span class="pun">]</span><span class="pln">
                                               A         B      
a </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
b </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">  </span><span class="lit">0.300774</span><span class="pln">
c </span><span class="pun">-</span><span class="lit">0.074350</span><span class="pln">  </span><span class="lit">0.039621</span></pre>

<p>
	أو عن طريق الموقع الذي من نمط integer:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2163_65" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
          A         B         
a </span><span class="pun">-</span><span class="lit">0.143510</span><span class="pln">  </span><span class="lit">0.616050</span><span class="pln">
b </span><span class="pun">-</span><span class="lit">1.489647</span><span class="pln">  </span><span class="lit">0.300774</span></pre>

<p>
	ستكون النتيجة في كلتا الحالتين إطار بيانات، لكن نلاحظ أنّ النتيجة الأولى تتضمّن نهاية الشريحة على عكس الثانية التي لا تحوي النهاية.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		نصيحة: إذا حوَت الأسطر على عناوين ليست من نمط صحيح وبسيط simple integers، فيُفضَّل استخدام العناوين دائمًا وتجنُّب المواقع التي نمطها integer.
	</p>
</blockquote>

<h2>
	تمارين
</h2>

<p>
	حلُّ هذه التمارين موجود في: <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/solutions/chap03soln.ipynb" rel="external nofollow">chap03soln.ipynb</a></code> و <code><a href="https://github.com/AllenDowney/ThinkStats2/blob/master/code/chap03soln.py" rel="external nofollow">chap03soln.py</a></code> في مستودع <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">ThinkStats2</a> على GitHub حيث ستجد كل الملفات والشيفرات. 
</p>

<h3>
	التمرين الأول
</h3>

<p>
	إذا سألنا الأطفال عن عدد الأطفال الموجودين في عائلتهم كما في مفارقة حجم الصف الدراسي، حيث من المحتمل أكثر أن يظهر في عيّنتك عدد كبير من العائلات التي لديها العديد من الأطفال، ولا يوجد احتمال ظهور عائلة لا تحتوي على أيّ أولاد في العيّنة؛ فاستخدم متغيِّر المستجيب <code>NUMKDHH</code> الموجود في المسح الوطني لنموّ الأسرة NSFG لبناء التوزيع الفعلي لعدد الأطفال تحت عمر 18 سنة في المنزل.
</p>

<p>
	احسب الآن التوزيع المتحيِّز الذي نراه إن سألنا الأطفال عن عدد الأطفال تحت عمر الثمانية عشر، مع حساب الأطفال أنفسهم الموجودين في منازلهم.
</p>

<p>
	ارسم التوزيع الحقيقي والمتحيِّز واحسب متوسطهم، مع العلم أنه يمكنك استخدام <code>chap03ex.ipynb</code> على أساس نقطة انطلاق من المستودع السابق.
</p>

<h3>
	التمرين الثاني
</h3>

<p>
	حسبنا في المقال السابق متوسط عيّنة عن طريق جمع العناصر وتقسيمها على n.
</p>

<p>
	إذا كانت لديك دالة كتلة احتمالية، فيمكنك حساب المتوسط لكن مع اختلاف طفيف في العملية:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium"><span style="text-decoration:overline">x</span> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-style:italic">p</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> <span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	حيث تكون x<sub>i</sub> هي القيم الفريدة في دالة الكتلة الاحتمالية وفي p<sub>i</sub> =PMF(x<sub>i</sub>)، وبالمثل يمكننا حساب التباين بالصورة التالية:
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">S</span><sup><span style="font-size:medium">2</span></sup><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-style:italic">p</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> (<span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − <span style="text-decoration:overline">x</span>)</span><sup><span style="font-size:medium">2</span></sup>
</td>
		</tr></tbody></table>
<p>
	اكتب دالتَين بحيث تكون الأولى باسم <code>PmfVar</code> والثانية باسم <code>PmfMean</code> تأخذان كائن Pmf وتحسبان المتوسط mean والتباين variance، ولاختبار هذه التوابع، تأكّد من أنها متوافقة مع التّوابع <code>Mean</code> و<code>Var</code> التي يزودنا بها Pmf.
</p>

<h3>
	التمرين الثالث
</h3>

<p>
	لقد كانت بدايتنا هي طرح السؤال "هل من المرجَّح أن تتأخر ولادة الأطفال الأوائل؟"، ولتناول هذا السؤال، حسبنا الفرق في المتوسطات بين مجموعات الأطفال babies، لكننا تجاهلنا احتمال أن يكون هناك فرق في موعد الولادة بين الأطفال الأوائل وبقية الأطفال للأم ذاتها. ولتناول هذه النسخة من السؤال، حدِّد المستجيبات اللواتي لديهن طفلين على الأقل واحسب الاختلافات الزوجية. فهل تؤدي هذه الصيغة من السؤال إلى ظهور نتيجة مختلفة؟
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>تلميح</strong>: استخدِم <code>nsfg.MakePregMap</code>.
	</p>
</blockquote>

<h3>
	التمرين الرابع
</h3>

<p>
	يبدأ جميع العدائين في الوقت ذاته في معظم سباقات الجري، فإذا كنت عدّاءً سريعًا، فستتخطى غالبًا الكثير من الأشخاص في بداية السباق، ولكن بعد عدّة أميال سيصبح جميع من حولك يركض بالسرعة نفسها.
</p>

<p>
	لاحظنا ظاهرةً غريبةً عندما ركضنا في سباق التتابع لمسافات طويلة -209 ميل- للمرة الأولى، فعندما تجاوزنا عدّاءً آخرًا، كنا أسرع منه بكثير في أغلب الأحيان، وعندما كان تجاوزنا عدّاء آخر، كان أسرع منا بكثير في أغلب الأحيان.
</p>

<p>
	اعتقدنا في البداية أنّ توزيع السرعات هو ثنائي النسق bimodal، وهذا يعني أنه كان هناك العديد من العدائين البطيئين والعديد من العدائين السريعين، وقلّة قليلة منهم يركضون سرعتنا ذاتها، ومن ثم أدركنا أننا كنا ضحية تحيُّز مشابه لأثر حجم الصف الدراسي.
</p>

<p>
	كان السباق غريبًا من ناحيتين هما: أنه قد كانت بداية السباق متداخلة، حيث بدأت الفِرق بأوقات مختلفة، كما تضمنت العديد من الفِرق متسابقِين بقدرات متنوعة.
</p>

<p>
	انتشر العدّاؤون نتيجةً لذلك على طول المضمار مع وجود علاقة طفيفة بين السرعة والموقع، وعندما انضممنا إلى السباق كان العدّاؤون بقربنا يشكِّلون -إلى حد كبير- عيّنةً عشوائيّةً من العدّائين في السباق.
</p>

<p>
	إذًا من أين أتى التحيُّز؟ كان احتمال تجاوزنا لعدّاءً أو تجاوز عدّاء لنا خلال الوقت الذي أمضيناه في المضمار؛ يتناسب مع الاختلاف في سرعاتنا، حيث أنّه من المرجَّح تجاوز عدّاء بطيء، ومن المرجَّح أن يتجاوزنا عدّاء سريع، ولكن من غير المرجَّح أن يرى العدّاؤون الذين يركضون بالسرعة ذاتها بعضهم البعض.
</p>

<p>
	اكتب دالّة باسم <code>ObservedPmf</code> تأخذ Pmf الذي يمثِّل التوزيع الفعلي لسرعات العدّائِين وسرعة العداء المراقِب، وتُعيد صنف Pmf جديد يمثل توزيع سرعات العدّائين تبعًا للمراقِب.
</p>

<p>
	يمكنك استخدام <code>relay.py</code> لاختبار دالتك، حيث يقرأ النتائج من سباق جيمس جويس رامبل James Joyce Ramble بطول مسار 10 كيلو متر في ديدهام في ماساتشوستس، ويحوِّل سرعة العدّاء إلى ميل في الساعة mph.
</p>

<p>
	احسب توزيع السرعات التي ستلاحظها أنت إذا ركضت بسباق تتابعي relay race بسرعة 7.5 ميل في الساعة مع مجموعة العدّائِين هذه.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة</strong>: حل هذا التمرين موجود في <code>relay_soln.py</code>.
	</p>
</blockquote>

<h2>
	المصطلحات الأساسية
</h2>

<ul>
<li>
		<strong>دالة الكتلة الاحتمالية Probability mass function- أو PMF اختصارًا-</strong>: تمثِّل التوزيع على أساس دالة تحوِّل القيم إلى احتمالاتها.
	</li>
	<li>
		<strong>الاحتمال probability</strong>: هو تردد يُعبَّر عنه على أساس كسر fraction من حجم العيّنة.
	</li>
	<li>
		<strong>التوحيد normalization</strong>: هو عملية تقسيم التردد على حجم العيّنة بهدف الحصول على احتمال.
	</li>
	<li>
		<strong>الفهرس index</strong>: هو عمود خاص في إطار بيانات البانداز pandas، بحيث يحتوي على تسميات الأسطر.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a data-ss1633772096="1" href="https://greenteapress.com/thinkstats2/html/thinkstats2004.html" rel="external nofollow">Chapter 3 Probability mass functions analysis</a> من كتاب <a data-ss1633772096="1" href="https://greenteapress.com/wp/think-stats-2e/" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a data-ss1633772096="1" href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/" rel="">التوزيعات الإحصائية في بايثون</a>
	</li>
	<li>
		<a data-ss1633772096="1" href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D9%83%D8%B4%D8%A7%D9%81%D9%8A%D8%A9-%D9%84%D8%A5%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B8%D8%B1%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-r1246/" rel="">تحليل البيانات الاستكشافية لإثبات النظريات الإحصائية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1303</guid><pubDate>Wed, 18 Aug 2021 15:00:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x648;&#x632;&#x64A;&#x639;&#x627;&#x62A; &#x627;&#x644;&#x625;&#x62D;&#x635;&#x627;&#x626;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D9%88%D8%B2%D9%8A%D8%B9%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1302/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/612934e4bd466_.png.acabfd56164672def193e6878d0853f1.png" /></p>

<p>
	سنتعرف في هذا المقال على التوزيعات الإحصائية في بايثون.
</p>

<h2>
	المدرجات التكرارية Histograms
</h2>

<p>
	يُعَدّ توزيع المتغير من أفضل الطرق المستخدمة لوصف متغير Variable، وهو إعطاء تقرير عن القيم Values الموجودة في مجموعة البيانات Dataset وعدد مرات ظهور هذه القيمة، كما يُعَدّ المدرَّج التكراري histogram التمثيل الأكثر شيوعًا، وهو عبارة عن مدرَّج بياني يُظهر تردد frequency كل قيمة، حيث يشير التردد في هذا السياق إلى عدد مرات ظهور كل قيمة.
</p>

<p>
	يُعَدّ القاموس Dictionary طريقةً فعالةً لحساب الترددات في لغة بايثون، فإذا كان لدينا تسلسل t من القيم كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_16" style="">
<span class="pln">hist </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> t</span><span class="pun">:</span><span class="pln">
    hist</span><span class="pun">[</span><span class="pln">x</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> hist</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	تكون النتيجة قاموسًا يربط بين القيم وتردداتها، كما يمكنك استخدام الصنف <code>Counter</code> المعرَّف في وحدة <code>collections</code> بدلًا من ذلك، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_18" style="">
<span class="kwd">from</span><span class="pln"> collections </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Counter</span><span class="pln">
counter </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Counter</span><span class="pun">(</span><span class="pln">t</span><span class="pun">)</span></pre>

<p>
	تكون النتيجة هنا كائن <code>Counter</code> وهو صنف فرعي من القاموس dictionary.
</p>

<p>
	يوجد خيار آخر وهو استخدام تابع pandas المعروف باسم <code>value_counts</code> والذي رأيناه في <a data-ss1630566694="1" href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D9%83%D8%B4%D8%A7%D9%81%D9%8A%D8%A9-%D9%84%D8%A5%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B8%D8%B1%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-r1246/" rel="">المقال السابق</a>، ولكن أنشأنا هنا صنفًا باسم <code>Hist</code> يمثِّل المدرَّجات التكرارية ويزودنا بالتوابع التي ستعمل على تلك المدرَّجات.
</p>

<h2>
	تمثيل المدرجات التكرارية
</h2>

<p>
	يقبل الباني Hist تسلسلًا sequence أو قاموسًا dictionary أو سلسلة pandas أو كائن Hist آخر، كما يمكنك تهيئة وتمثيل كائن Hist كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_21" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> thinkstats2
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">([</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist
</span><span class="typ">Hist</span><span class="pun">({</span><span class="lit">1</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">})</span></pre>

<p>
	توفِّر كائنات Hist التابع <code>Freq</code> الذي يقبل قيمةً على أساس وسيط ويُعيد ترددها، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_23" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Freq</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	يفعل عامِل القوس المربع bracket operator الشيء ذاته:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_25" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	يكون التردد 0 عند البحث عن قيمة غير موجودة، أي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_28" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Freq</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0</span></pre>

<p>
	يُعيد التابع <code>Values</code> قائمةً غير مرتَّبة بالقيم الموجودة في Hist.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_37" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Values</span><span class="pun">()</span><span class="pln">
</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">]</span></pre>

<p>
	ويمكن استخدام الدالة المبنية مسبقًا <code>sorted</code> للمرور على القيم بالترتيب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_30" style="">
<span class="kwd">for</span><span class="pln"> val </span><span class="kwd">in</span><span class="pln"> sorted</span><span class="pun">(</span><span class="pln">hist</span><span class="pun">.</span><span class="typ">Values</span><span class="pun">()):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">val</span><span class="pun">,</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Freq</span><span class="pun">(</span><span class="pln">val</span><span class="pun">))</span></pre>

<p>
	أو استخدم <code>items</code> للمرور على أزواج القيم وتردداتها، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_32" style="">
<span class="kwd">for</span><span class="pln"> val</span><span class="pun">,</span><span class="pln"> freq </span><span class="kwd">in</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Items</span><span class="pun">():</span><span class="pln">
     </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">val</span><span class="pun">,</span><span class="pln"> freq</span><span class="pun">)</span></pre>

<h2>
	الرسم البياني للمدرجات التكرارية
</h2>

<p style="text-align: center;">
	<img alt="الشكل 2.1.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75572" data-unique="tpktkh55x" src="https://academy.hsoub.com/uploads/monthly_2021_08/61293510ab520_2.1.jpg.7e7e26ff7a383f536c1ca8b6e990f11c.jpg"></p>

<p>
	يُظهِر الشكل السابق المدرَّج التكراري لوزن الولادات بالرطل.
</p>

<p>
	أُنشئت لهذه السلسلة تحديدًا وحدة باسم <code>thinkplot.py</code> توفِّر دوالًا لرسم المدرَّجات التكرارية، وكائنات أخرى مُعرَّفة في الوحدة <code>thinkstats2.py</code>، وهي مبنية على <code>pyplot</code> الذي هو جزء من حزمة <code>matplotlib</code>.
</p>

<p>
	جرّب الشيفرة التالية لرسم <code>hist</code> باستخدام <code>thinkplot</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_40" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> thinkplot
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">hist</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'value'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'frequency'</span><span class="pun">)</span></pre>

<p>
	يمكنك قراءة توثيق thinkplot <a data-ss1630566694="1" href="http://greenteapress.com/thinkstats2/thinkplot.html" rel="external nofollow">من الموقع </a>.
</p>

<p style="text-align: center;">
	<img alt="الشكل 2.2.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75573" data-unique="vgjlpm165" src="https://academy.hsoub.com/uploads/monthly_2021_08/612935124b9c0_2.2.jpg.df7bafb2ea8f9d20e17e79966d13cc97.jpg"></p>

<p>
	يُظهِر الشكل السابق المدرَّج التكراري لوزن الولادات بالأوقية.
</p>

<h2>
	متغيرات المسح الوطني لنمو الأسرة NSFG
</h2>

<p>
	توجد شيفرة هذا المقال في ملف <code>first.py</code>،  ويُفضَّل اكتشاف المتغيرات المخطَّط لاستخدامها واحدًا تلو الآخر عند البدء بالعمل مع مجموعة بيانات جديدة، وأفضل طريقة للبدء هي إلقاء نظرة على المدرَّجات االتكرارية.
</p>

<p>
	حوّلنا <code>agepreg </code>في القسم 1.6 من سنتي-سنوات centiyears إلى سنوات years، كما دمجنا <code>birthwgt_lb</code> و<code>birthwgt_oz</code> في كمية واحدة وهي <code>totalwgt_lb</code>.
</p>

<p>
	سنستخدِم في هذا القسم تلك المتغيرات لإظهار بعض ميزات المدرَّجات التكرارية.
</p>

<p style="text-align: center;">
	<img alt="الشكل 2.3.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75574" data-unique="uzlw2ug0d" src="https://academy.hsoub.com/uploads/monthly_2021_08/61293513c6f9f_2.3.jpg.b0b88783ae02adb9a500b5db9e815e78.jpg"></p>

<p>
	يُظهر الشكل السابق المدرَّج التكراري لعمر الأم في نهاية الحمل.
</p>

<p>
	سنبدأ بقراءة البيانات ونحدِّد سجلات الولادات الحية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_42" style="">
<span class="pln">    preg </span><span class="pun">=</span><span class="pln"> nsfg</span><span class="pun">.</span><span class="typ">ReadFemPreg</span><span class="pun">()</span><span class="pln">
    live </span><span class="pun">=</span><span class="pln"> preg</span><span class="pun">[</span><span class="pln">preg</span><span class="pun">.</span><span class="pln">outcome </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]</span></pre>

<p>
	يُعَدّ التعبير الموجود بين القوسين الهلاليَين سلسلةً بوليانيةً تُحدِّد الأسطر من إطار البيانات وتُعيد إطار بيانات جديد.
</p>

<p>
	سنرسم مدرَّجًا تكراريًا لـ <code>birthwgt_lb</code> للولادات الحية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_44" style="">
<span class="pln">    hist </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">live</span><span class="pun">.</span><span class="pln">birthwgt_lb</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'birthwgt_lb'</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">hist</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'pounds'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'frequency'</span><span class="pun">)</span><span class="pln"> </span></pre>

<p>
	ستُزال قيم <code>nan</code> -أي ليس عددًا- عندما يكون الوسيط الممرَّر إلى المدرَّج التكراري Hist سلسلة بانداز pandas؛ أما <code>label</code> فهي سلسلة نصية تظهر في العنوان التفسيري عندما يُرسم Hist.
</p>

<p style="text-align: center;">
	<img alt="الشكل 2.4.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75571" data-unique="nfktet6xs" src="https://academy.hsoub.com/uploads/monthly_2021_08/6129350f68028_2.4.jpg.170b9e9fa67361feaffd0aeb604cf2b3.jpg"></p>

<p>
	يُظهِر الشكل السابق المدرَّج التكراري لمدة الحمل مقاسةً بالأسابيع.
</p>

<p>
	يوضِّح الشكل الأول النتيجة، حيث تكون القيمة الأكثر شيوعًا والتي تدعى المنوال mode هي 7 أرطال، إذ يشبه التوزيع الجرس تقريبًا، وهو شكل التوزيع الطبيعي normal distribution الذي يسمى أيضًا بالتوزيع الغاوسي Gaussian distribution، ولكن على عكس التوزيع الطبيعي الحقيقي؛ يكون هذا التوزيع غير متناظر، حيث يملك ذيلًا tail يمتد من إلى اليسار أكثر من اليمين، ويوضِّح الشكل الثاني المدرَّج التكراري الخاص بالمتغير <code>birthwgt_oz</code>، وهو وزن الولادة بالأوقية، كما نتوقَّع أن يكون هذا التوزيع موحّدًا uniform، أي ستمتلك جميع القيم التردد نفسه نظريًا، إلا أنه في الواقع ستكون القيمة 0 أكثر شيوعًا من القيم الأخرى، في حين تكون القيمتان 1 و15 أقل شيوعًا، وذلك ربما لأن المستجيبين قرّبوا أوزان المواليد إلى أقرب قيمة صحيحة؛ أما الشكل الثالث فيوضّح المدرَّج التكراري الخاص بالمتغير <code>agepreg</code>، وهو عمر الأم في نهاية الحمل، ويكون المنوال هنا هو 21 سنة، كما يكون التوزيع على صورة جرس تقريبًا، ولكن هنا سيمتد الذيل إلى اليمين أكثر من اليسار، حيث أن معظم الأمهات في العشرينات من عمرهن وقليل منهن في الثلاثينات. يوضِّح الشكل الرابع المدرَّج التكراري الخاص بالمتغير <code>prglngth</code>، وهو مدة الحمل مقاسةً بالأسابيع، إذ تكون القيمة الأكثر شيوعًا هي 39 أسبوعًا، كما يكون الذيل الأيسر أطول من الأيمن، أي أن ولادة الأطفال باكرًا هي أمر شائع، لكن من النادر استمرار الحمل أكثر من 43 أسبوعًا، وإلا فسيتدخل الأطباء غالبًا.
</p>

<h2>
	القيم الشاذة Outliers
</h2>

<p>
	يمكننا تحديد القيم الأكثر تكرارًا وتحديد شكل التوزيع بسهولة عن طريق النظر إلى المدرَّجات التكرارية، إلا أن القيم النادرة الوجود لا تظهر دائمًا، كما يُستحسَن التحقق من وجود قيم شاذة، أي القيم المتطرفة التي يمكن أن تكون أخطاءً في القياس والتسجيل، أو تكون تقاريرًا دقيقةً ناتجةً عن أحداث نادرة.
</p>

<p>
	توفِّر Hist تابعَين باسم <code>Largest</code> و<code>Smallest</code>، حيث يأخذان عددًا صحيحًا n، ويُعيدان أكبر أو أصغر n قيمة من المدرَّج التكراري كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_46" style="">
<span class="pln">    </span><span class="kwd">for</span><span class="pln"> weeks</span><span class="pun">,</span><span class="pln"> freq </span><span class="kwd">in</span><span class="pln"> hist</span><span class="pun">.</span><span class="typ">Smallest</span><span class="pun">(</span><span class="lit">10</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">weeks</span><span class="pun">,</span><span class="pln"> freq</span><span class="pun">)</span></pre>

<p>
	تكون القيم العشرة القليلة في قائمة مدة حمل الولادات الحية هي [22, 21, 20, 19, 18, 17, 13, 9, 4, 0]، حيث أن القيم التي تقل عن 10 أسابيع بالتأكيد خاطئة، والتفسير الأكثر احتمالًا هو عدم ترميز الخرج بصورة صحيحة.
</p>

<p>
	القيم التي تزيد عن 30 أسبوعًا صحيحة غالبًا؛ أمّا القيم التي تتراوح بين 10 و30 أسبوع، فمن الصعب التأكّد من صحتها، فقد تكون بعض القيم خاطئة، ولكن تمثِّل بعضها أطفالًا خُدّج. وتكون القيم العليا بالنسبة للطرف الآخر من المجال هي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_48" style="">
<span class="pln">weeks  count
</span><span class="lit">43</span><span class="pln">     </span><span class="lit">148</span><span class="pln">
</span><span class="lit">44</span><span class="pln">     </span><span class="lit">46</span><span class="pln">
</span><span class="lit">45</span><span class="pln">     </span><span class="lit">10</span><span class="pln">
</span><span class="lit">46</span><span class="pln">     </span><span class="lit">1</span><span class="pln">
</span><span class="lit">47</span><span class="pln">     </span><span class="lit">1</span><span class="pln">
</span><span class="lit">48</span><span class="pln">     </span><span class="lit">7</span><span class="pln">
</span><span class="lit">50</span><span class="pln">     </span><span class="lit">2</span><span class="pln"> </span></pre>

<p>
	يقترح معظم الأطباء الولادة المحفَّزة إذا تجاوزت مدة الحمل 42 أسبوعًا، لذا ستكون بعض القيم التي تمثل مدةً طويلةً مدهشة، إذ تبدو مدة 50 أسبوع مستبعَدة طبيًا.
</p>

<p>
	تعتمد أفضل طريقة لمعالجة القيم الشاذة على "معرفة النطاق"، أي معلومات عن مصدر البيانات ومعنى هذه البيانات، كما تعتمد على التحليل الذي نخطط لإجرائه.
</p>

<p>
	السؤال الذي دعانا للبحث في هذا المثال هو ما إن كان الأطفال الأوائل يولدون باكرًا -أم متأخرًا-، وعندما يطرح أحدهم هذا السؤال، فهو مهتم بحالات الحمل المكتملة غالبًا، لذا سنركِّز في هذا التحليل على حالات الحمل التي استمرت لأكثر من 27 أسبوعًا.
</p>

<h2>
	الأطفال الأوائل First babies
</h2>

<p>
	أصبح بإمكاننا الآن موازنة توزيعات مدة حمل الأطفال الأوائل وغيرهم.
</p>

<p>
	قُسِّم إطار البيانات للولادات الحية باستخدام <code>birthord</code>، ومن ثم حساب مدرَّجهم التكراري، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_50" style="">
<span class="pln">    firsts </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">[</span><span class="pln">live</span><span class="pun">.</span><span class="pln">birthord </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]</span><span class="pln">
    others </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">[</span><span class="pln">live</span><span class="pun">.</span><span class="pln">birthord </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]</span><span class="pln">

    first_hist </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">firsts</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'first'</span><span class="pun">)</span><span class="pln">
    other_hist </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">others</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">,</span><span class="pln"> label</span><span class="pun">=</span><span class="str">'other'</span><span class="pun">)</span></pre>

<p>
	ثم رسمنا مدرَّجهم التكراري على المحاور نفسها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8524_52" style="">
<span class="pln">    width </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.45</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">PrePlot</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">first_hist</span><span class="pun">,</span><span class="pln"> align</span><span class="pun">=</span><span class="str">'right'</span><span class="pun">,</span><span class="pln"> width</span><span class="pun">=</span><span class="pln">width</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Hist</span><span class="pun">(</span><span class="pln">other_hist</span><span class="pun">,</span><span class="pln"> align</span><span class="pun">=</span><span class="str">'left'</span><span class="pun">,</span><span class="pln"> width</span><span class="pun">=</span><span class="pln">width</span><span class="pun">)</span><span class="pln">
    thinkplot</span><span class="pun">.</span><span class="typ">Show</span><span class="pun">(</span><span class="pln">xlabel</span><span class="pun">=</span><span class="str">'weeks'</span><span class="pun">,</span><span class="pln"> ylabel</span><span class="pun">=</span><span class="str">'frequency'</span><span class="pun">,</span><span class="pln">
                   xlim</span><span class="pun">=[</span><span class="lit">27</span><span class="pun">,</span><span class="pln"> </span><span class="lit">46</span><span class="pun">])</span></pre>

<p>
	تأخذ الدالة <code>thinkplot.PrePlot</code> عدد المدرَّجات التكرارية التي ستُرسم، حيث تُستخدم هذه المعلومة من أجل اختيار تجميعة مناسبة من الألوان.
</p>

<p style="text-align: center;">
	<img alt="الشكل 2.5.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="75575" data-unique="bigi24ts0" src="https://academy.hsoub.com/uploads/monthly_2021_08/61293515ba078_2.5.jpg.2fbf17b8d65506cd515a0da7b9ed2ddb.jpg"></p>

<p>
	يُظهِر الشكل السابق مدرَّجًا تكراريًا لمدة الحمل.
</p>

<p>
	تحاذي الدالة <code>thinkplot.Hist</code> القيم عادةًّ إلى الوسط أي باعتماد <code>'align='center</code>، لذا يتوضّع كل شريط فوق قيمته، كما تُستخدَم <code>'align='right</code> و<code>'align='left</code> لوضع الأشرطة المقابِلة على جانبي القيمة. وقد وضعنا <code>width=0.45</code> ليكون عرض الشريط 0.45، أي سيكون العرض الكلي للشريطَين هو 0.9 مع ترك بعض الفراغ بين كل زوج، وأخيرًا ضبطنا المحاور لإظهار البيانات الموجودة بين 27 و46 أسبوعًا فقط، حيث سيعرض الشكل السابق النتيجة.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		تُعَدّ المدرَّجات التكرارية مفيدةً لأنّ القيم الأكثر تكرارًا تظهر فيها بصورة واضحة وعلى الفور، ولكنها ليست الخيار الأفضل لموازنة توزيعين.
	</p>
</blockquote>

<p>
	كان عدد "الأطفال الأوائل" في هذا المثال أقل من عدد "الأطفال الآخرين"، لذا تعود بعض الفروق الواضحة بين المدرَّجين التكراريَين إلى أحجام العينة، حيث سنعالِج هذه المشكلة في المقال القادم باستخدام دوال الكتلة الاحتمالية.
</p>

<h2>
	تلخيص التوزيعات
</h2>

<p>
	يُعَدّ المدرَّج التكراري وصفًا كاملًا لتوزيع عينة ما، حيث أنه يمكننا إعادة بناء قيم العينة من خلال المدرَّج التكراري وحده، إلا أنه لا يمكننا معرفة ترتيب القيم.
</p>

<p>
	إذا كانت تفاصيل التوزيع هامة، فقد يكون من الضروري تمثيل مدرَّج تكراري، ولكن يمكننا تلخيص التوزيع غالبًا من خلال بعض الإحصائيات الوصفية، وتكون بعض الخصائص التي قد نرغب في تقديم تقرير عنها:
</p>

<ul>
<li>
		النزعة المركزية central tendency: هل تميل القيم للتجمُّع حول نقطة معيّنة؟
	</li>
	<li>
		المنوالات modes: هل يوجد أكثر من تجمُّع؟
	</li>
	<li>
		الانتشارspread: ما مقدار التباين variability الموجود في القيم؟
	</li>
	<li>
		الذيول tails: ما مدى سرعة انخفاض الاحتمالات عندما نبتعد عن المنوال؟
	</li>
	<li>
		القيم الشاذة outliers: هل توجد قيم متطرِّفة بعيدة عن المنوالات؟
	</li>
</ul>
<p>
	تُدعى الإحصائيات المصمَّمة للإجابة عن مثل هذه الأسئلة <strong>إحصائيات موجزة summary statistics</strong>، وأكثر الإحصائيات الموجزة شيوعًا هي المتوسط mean والتي تهدف إلى وصف النزعة المركزية للتوزيع.
</p>

<p>
	إن كانت لديك عيّنة تحوي <code>n</code> قيمة x<sub>i</sub> فإنّ المتوسط <code>x̄</code> هو مجموع القيم مقسومًا على عددها، وبمعنى آخر: 
</p>

<table class="display" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-size:medium"><span style="text-decoration:overline">x</span> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> <span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	تُستخدم عادةً الكلمتان المتوسط mean والمتوسط الحسابي average على سبيل الترادف، وقد يعتقد البعض أنهما تعنيان الشيء ذاته على الرغم من وجود فرق بينهما وهو:
</p>

<ul>
<li>
		متوسط العينة هو الإحصائية الموجزة التي تُحسَب بالمعادلة السابقة.
	</li>
	<li>
		المتوسط الحسابي هو أحد الإحصائيات الموجزة التي قد تختارها لوصف النزعة المركزية.
	</li>
</ul>
<p>
	يُمثّل المتوسط وصفًا جيدًا لمجموعة من القيم في بعض الأحيان. فمثلًا، تملك حبات التفاح جميعها الوزن نفسه تقريبًا -والتي تُباع في المتاجر الكبرى-، فإذا اشترينا ست تفاحات وكان الوزن الكلي هو 3 أرطال، فسيكون قولنا "تَزِن كل تفاحة نصف رطل" موجزًا منطقيًا.
</p>

<p>
	لكن القرع أكثر تنوّعًا، فبفرض أننا زرعنا عدة أنواع في الحديقة وحصدنا في يوم من الأيام 3 حبات قرع للزينة بحيث تَزِن كل حبة رطلًا واحدًا، وحبتي قرع للفطيرة بحيث تَزِن كل منها 3 أرطال، وحبة واحدة من نوع آتلانتيك جيانت Atlantic Giant تَزن 591 رطلًا. سيكون متوسط mean هذه العينة هو 100 رطل، لكن من الخطأ القول أنّ المتوسط الحسابي average هو 100 رطل، وبالتالي لا يوجد في هذا المثال متوسط حسابي ذو معنى لأنه لا يوجد قرع مثالي.
</p>

<h2>
	التباين variance
</h2>

<p>
	إذا لم يكن هناك عددًا واحدًا يُلخِّص أوزان القرع، فسيمكننا فعل ذلك باستخدام عددين هما المتوسط mean والتباين variance.
</p>

<p>
	التباين هو إحصائية موجزة تهدف إلى وصف التباين أو انتشار التوزيع.، وتكون الصيغة الرياضية لتباين مجموعة من القيم كما يلي:
</p>

<table class="display dcenter" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">S</span><sup><span style="font-size:medium">2</span></sup><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> (<span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − <span style="text-decoration:overline">x</span>)</span><sup><span style="font-size:medium">2</span></sup><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	يُسمّى<code>(x&lt;sub&gt;i&lt;/sub&gt;-x̄)</code> "الانحراف عن المتوسط"، لذا سيكون التباين هو متوسط مربع الانحراف، ويكون الجذر التربيعي للتباين هو الانحراف المعياري S.
</p>

<p>
	إذا كانت لديك خبرة سابقة في المجال، فربما صادفت صيغةً للتباين تحوي <code>n − 1</code> في المقام بدلًا من <code>n</code>، إذ تُستخدَم هذه الإحصائية لتقدير التباين في إحصاء السكان باستخدام عينة.
</p>

<p>
	تزوِّدنا بنى بيانات البانداز pandas بتوابع لحساب المتوسط والتباين والانحراف المعياري كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_57" style="">
<span class="pln">    mean </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">()</span><span class="pln">
    var </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">.</span><span class="pln">var</span><span class="pun">()</span><span class="pln">
    std </span><span class="pun">=</span><span class="pln"> live</span><span class="pun">.</span><span class="pln">prglngth</span><span class="pun">.</span><span class="pln">std</span><span class="pun">()</span></pre>

<p>
	يكون متوسط مدة الحمل بالنسبة للولادات الحية 38.6 أسبوعًا، وانحرافه المعياري 2.7 أسبوعًا، أي علينا أن نتوقع الانحرافات بمقدار بين أسبوعين وثلاثة أسابيع وهي أمر شائع، وبذلك يكون تباين مدة الحمل هو 7.3، وهو أمر يَصعُب تفسيره، خاصةً أنّ الوحدات هي مربع الأسابيع، ويُعَدّ التباين مفيدًا في بعض العمليات الحسابية لكنه ليس إحصائية موجزة جيدة.
</p>

<h2>
	حجم الأثر
</h2>

<p>
	حجم الأثر هو إحصائية موجزة تهدف إلى وصف حجم الأثر، إذ لن تتوقع ما هو قادم، فإذا أردنا وصف الفرق بين مجموعتين مثلًا، فسيكون أحد الخيارات الشائعة هو حساب الفرق بين المتوسطات.
</p>

<p>
	متوسط الحمل للأطفال الأوائل هو 38.601 ويكون لبقية الأطفال 38.523، وبالتالي يكون الفرق بينهما هو 0.078 أسبوع أي حوالي 13 ساعة، كما يكون الفارق هو 0.2% على أساس جزء من مدة الحمل الطبيعي.
</p>

<p>
	إذا افترضنا أنّ هذا التقدير دقيقًا، فلن يكون لهذا الفارق أيّ عواقب عملية، ومن غير المحتمل واقعيًا ملاحظة أحد أيّ اختلاف على الإطلاق بدون مراقبة عدد كبير من حالات الحمل.
</p>

<p>
	هناك طريقة أخرى لتوضيح حجم الأثر، وهي موازنة الفرق بين المجموعات مع التباين داخل المجموعات، حيث يهدف معامل كوهن د Cohen's d إلى فعل ذلك، ويُعرَّف بالصورة التالية:
</p>

<table class="display dcenter" style="direction: ltr; margin: auto;"><tbody><tr style="vertical-align:middle">
<td class="dcell">
				<span style="font-style:italic;font-size:medium">S</span><sup><span style="font-size:medium">2</span></sup><span style="font-size:medium"> = </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium">1</span>
							</td>
						</tr>
<tr>
<td class="hbar">
								 
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">n</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> </span>
			</td>
			<td class="dcell">
				<table class="display"><tbody>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:medium"> </span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-size:xx-large">∑</span>
							</td>
						</tr>
<tr>
<td class="dcell" style="text-align:center">
								<span style="font-style:italic;font-size:medium">i</span>
							</td>
						</tr>
</tbody></table>
</td>
			<td class="dcell">
				<span style="font-size:medium"> (<span style="font-style:italic">x</span></span><sub><span style="font-style:italic;font-size:medium">i</span></sub><span style="font-size:medium"> − <span style="text-decoration:overline">x</span>)</span><sup><span style="font-size:medium">2</span></sup><span style="font-size:medium"> </span>
			</td>
		</tr></tbody></table>
<p>
	يكون <code>x̄-1</code> و<code>x̄-2</code> متوسطي المجموعتين و<code>s</code> هي "الانحراف المعياري المجمَّع"، كما تكون شيفرة البايثون لحساب Cohen's d بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8524_59" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">CohenEffectSize</span><span class="pun">(</span><span class="pln">group1</span><span class="pun">,</span><span class="pln"> group2</span><span class="pun">):</span><span class="pln">
    diff </span><span class="pun">=</span><span class="pln"> group1</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> group2</span><span class="pun">.</span><span class="pln">mean</span><span class="pun">()</span><span class="pln">

    var1 </span><span class="pun">=</span><span class="pln"> group1</span><span class="pun">.</span><span class="pln">var</span><span class="pun">()</span><span class="pln">
    var2 </span><span class="pun">=</span><span class="pln"> group2</span><span class="pun">.</span><span class="pln">var</span><span class="pun">()</span><span class="pln">
    n1</span><span class="pun">,</span><span class="pln"> n2 </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">group1</span><span class="pun">),</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">group2</span><span class="pun">)</span><span class="pln">

    pooled_var </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n1 </span><span class="pun">*</span><span class="pln"> var1 </span><span class="pun">+</span><span class="pln"> n2 </span><span class="pun">*</span><span class="pln"> var2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n1 </span><span class="pun">+</span><span class="pln"> n2</span><span class="pun">)</span><span class="pln">
    d </span><span class="pun">=</span><span class="pln"> diff </span><span class="pun">/</span><span class="pln"> math</span><span class="pun">.</span><span class="pln">sqrt</span><span class="pun">(</span><span class="pln">pooled_var</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> d    </span></pre>

<p>
	يكون الفرق بين المتوسطات في هذا المثال هو 0.029 انحرافًا معياريًا الذي هو صغير جدًا، ولتوضيح ذلك بمثال آخر، سيكون الفرق في الطول بين النساء والرجال هو 1.7 انحرافًا معياريًّا، كما يمكنك الإطلاع <a data-ss1630566694="1" href="https://en.wikipedia.org/wiki/Effect_size" rel="external nofollow">هنا</a>.
</p>

<h2>
	التقارير الخاصة بالنتائج
</h2>

<p>
	رأينا عدة طرق لوصف الفرق في مدة الحمل بين الأطفال الأوائل وبقية الأطفال، فكيف يمكننا إعطاء تقارير بهذه النتائج؟
</p>

<p>
	تعتمد الإجابة على مَن يطرح السؤال، فقد يكون أحد العلماء مثلًا مهتمًا بأيّ تأثير حقيقي مهما كان صغيرًا؛ أما الطبيب فقد يكون مهتمًا بالتأثيرات ذات الأهمية السريرية فقط، أي أن الفروق التي تؤثِّر على القرارات العلاجية للمريض، هي حين قد تهتم المرأة الحامل بالنتائج التي تخصُّها مثل احتمالية الولادة الباكرة أو المتأخرة.
</p>

<p>
	كما تعتمد طريقة تقديم تقارير بالنتائج على أهدافك، فإذا كنت تحاول إثبات أهمية تأثير معيَّن، فقد تختار إحصائية موجزة تشدِّد على الفروقات؛ أما إذا كنت تحاول طمأنة مريض، فقد تختار إحصائيةً موجزة تضع الفروقات في السياق.
</p>

<p>
	يجب أن تأخذ قراراتك أخلاقيات المهنة بالحسبان، ولا بأس بأن تكون مُقنعًا، إذ عليك تصميم تقارير إحصائية وتقارير رسومية تروي القصة بوضوح، كما عليك بذل جهدك لجعل تقاريرك صادقة، وتعترف بالقيود والأمور التي ليست مؤكَّدة.
</p>

<h2>
	تمارين
</h2>

<h3>
	التمرين الأول
</h3>

<p>
	افترض أنه قد طُلب منك تلخيص ما تعلَّمته حول ما إذا كان الأطفال الأوائل يولدون متأخرين أم لا بناءً على النتائج الواردة في هذا المقال.
</p>

<p>
	ما هي الإحصائية الموجزة التي ستستخدِمها إن أردت عرض نتائجك في أخبار المساء؟ وما هي الإحصائية الموجزة التي ستستخدِمها إذا أردت طمأنة أم حامل قلقة حيال هذا الأمر؟
</p>

<p>
	تخيَّل أنك سيسل آدامز Cecil Adams وهو مؤلف كتاب The Straight Dope الموجود <a data-ss1630566694="1" href="www.straightdope.com" rel="">هنا</a>، وكانت مهمتك هي الإجابة عن هذا السؤال: "هل يولد الأطفال الأوائل متأخرين؟".
</p>

<p>
	اكتب فقرةً تستخدِم النتائج الموجودة في هذا المقال للإجابة عن السؤال بكل وضوح ودقة وشفافية.
</p>

<h3>
	التمرين الثاني
</h3>

<p>
	يجب أن تجد في المستودع repository الذي حمَّلته، ملفًا باسم <code>chap02ex.ipynb</code> افتحه أولًا.
</p>

<p>
	لقد مُلئت بعض الخلايا وعليك تنفيذها؛ أما الخلايا الأخرى فستزوِّدك بتعليمات حول التمارين، لذلك اتبع التعليمات واملأ الإجابات.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة</strong> حل هذا التمرين موجود في <code>chap02soln.ipynb</code>.
	</p>
</blockquote>

<p>
	ستجد في المستودع repository الذي حمَّلته ملفًا باسم <code>chap02ex.py</code>، حيث يمكنك استخدام هذا الملف على أساس نقطة انطلاق للتمارين اللاحقة.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة</strong>: حل هذا التمرين موجود في <code>chap02soln.py</code>.
	</p>
</blockquote>

<h3>
	التمرين الثالث
</h3>

<p>
	يكون منوال التوزيع هو القيمة الأكثر تكرارًا، كما يمكنك الاطلاع على <a data-ss1630566694="1" href="http://wikipedia.org/wiki/Mode_(statistics)" rel="external nofollow">Mode_(statistics)</a>.
</p>

<p>
	اكتب دالةً اسمها <code>Mode</code> بحيث تأخذ مدرَّجًا تكراريًا Hist وتُعيد القيمة الأكثر تكرارًا، واكتب دالةً اسمها <code>AllModes</code> تُعيد قائمةً من أزواج القيم وتردداتها مرتَّبةً تنازليًا حسب التردد.
</p>

<h3>
	التمرين الرابع
</h3>

<p>
	ابحث فيما إن كان وزن الأطفال الأوائل عادةً أخف وزنًا أو أثقل من البقية بالاعتماد على المتغير<code>totalwgt_lb</code>، واحسب Cohen’s d لقياس مقدار الفرق بين المجموعات، وكيف يمكن موازنتها مع الاختلاف في مدة الحمل؟
</p>

<h2>
	المفاهيم الأساسية
</h2>

<ul>
<li>
		<strong>التوزيع distribution</strong>: القيم التي تظهر في العينة وتردد كل منها.
	</li>
	<li>
		<strong>المدرَّج التكراري histogram</strong>: تحويل القيم إلى ترددات، أو رسم بياني يُظهِر هذا التحويل.
	</li>
	<li>
		<strong>التردد frequency</strong>: عدد المرات ظهور قيمة معيَّنة في العينة.
	</li>
	<li>
		<strong>المنوال mode</strong>: القيمة الأكثر تكرارًا في العينة أو إحدى القيم التي تملك أكبر تكرار.
	</li>
	<li>
		<strong>التوزيع الطبيعي normal distribution</strong>: معالجة مثالية للتوزيع الذي يشبه الجرس، أو ما يُعرَف بالتوزيع الغاوسي.
	</li>
	<li>
		<strong>التوزيع الموحَّد uniform distribution</strong>: هو التوزيع الذي يكون فيه التردد نفسه لكل القيم.
	</li>
	<li>
		<strong>الذيل tail</strong>: جزء من التوزيع الموجود في نهاية الطرف المرتفع ونهاية الطرف المنخفض.
	</li>
	<li>
		<strong>النزعة المركزية central tendency</strong>: صفة لعينة أو السكان، هي قيمة متوسطة أو نموذجية بديهيًا.
	</li>
	<li>
		<strong>القيمة الشاذة outlier</strong>: قيمة بعيدة عن النزعة المركزية.
	</li>
	<li>
		<strong>الانتشار spread</strong>: مقياس لكيفية انتشار القيم في التوزيع.
	</li>
	<li>
		<strong>إحصائية موجزة summary statistic</strong>: إحصائية تُحدِّد بعض جوانب التوزيع مثل النزعة المركزية أو الانتشار.
	</li>
	<li>
		<strong>التباين variance</strong>: إحصائية موجزة تُستخدَم غالبًا لقياس الانتشار.
	</li>
	<li>
		<strong>الانحراف المعياري standard deviation</strong>: هو الجذر التربيعي للتباين، ويستخدم أيضًا على أساس مقياس للانتشار.
	</li>
	<li>
		<strong>حجم الأثر effect size</strong>: إحصائية موجزة تهدف إلى تحديد حجم التأثير، مثل الفرق بين المجموعات.
	</li>
	<li>
		<strong>أهمية سريرية clinically significant</strong>: نتيجة مهمة من الناحية العملية مثل الفرق بين المجموعات.
	</li>
</ul>
<p>
	ترجمة -وبتصرف- للفصل <a data-ss1630566694="1" href="https://greenteapress.com/thinkstats2/html/thinkstats2003.html" rel="external nofollow">Chapter 2 Distributions analysis</a> من كتاب <a data-ss1630566694="1" href="https://greenteapress.com/wp/think-stats-2e/" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقال السابق: <a data-ss1630566694="1" href="https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D9%83%D8%B4%D8%A7%D9%81%D9%8A%D8%A9-%D9%84%D8%A5%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B8%D8%B1%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-r1246/" rel="">تحليل البيانات الاستكشافية لإثبات النظريات الإحصائية</a>
	</li>
	<li>
		<a data-ss1630566694="1" href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%84%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%AA%D8%AE%D8%B2%D9%8A%D9%86%D9%87%D8%A7-%D9%88%D8%A7%D8%AE%D8%AA%D9%84%D8%A7%D9%81%D9%87-%D8%B9%D9%86-%D9%86%D8%B8%D8%A7%D9%85-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r509/" rel="">تحليل نظام الملفات لإدارة البيانات وتخزينها واختلافه عن نظام قاعدة البيانات</a>
	</li>
	<li>
		<a data-ss1630566694="1" href="https://academy.hsoub.com/files/17-%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A-%D9%88%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9/" rel="">مدخل إلى الذكاء الاصطناعي وتعلم الآلة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1302</guid><pubDate>Wed, 04 Aug 2021 12:00:00 +0000</pubDate></item><item><title>&#x62A;&#x62D;&#x644;&#x64A;&#x644; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x643;&#x634;&#x627;&#x641;&#x64A;&#x629; &#x644;&#x625;&#x62B;&#x628;&#x627;&#x62A; &#x627;&#x644;&#x646;&#x638;&#x631;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x625;&#x62D;&#x635;&#x627;&#x626;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D9%83%D8%B4%D8%A7%D9%81%D9%8A%D8%A9-%D9%84%D8%A5%D8%AB%D8%A8%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B8%D8%B1%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A5%D8%AD%D8%B5%D8%A7%D8%A6%D9%8A%D8%A9-r1246/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_06/60c1b5e12cc17_--.png.7bb9a290ddc229dd189f63cb2d7cf32f.png" /></p>

<p>
	تقول الفرضية الأساسية لهذه السلسلة أنّ دمج البيانات مع الطرق العملية يمكنه الإجابة عن الأسئلة المطروحة وتوجيه القرارات في حالات الشك uncertainty.
</p>

<p>
	يطرح آلان بي داوني Allen B. Downey مثالًا استلهمه من سؤال سمعه عندما كانت زوجته حاملًا بطفلهما الأول، وهو: هل تتأخر ولادة الأطفال الأوائل؟ إذا توجهنا بسؤالنا هذا إلى غوغل، فسنجد الكثير من النّقاشات حوله؛ إذ يَعتقد البعض أنها حقيقة، ويَعتقد آخرون أنها خرافة، كما يقول البعض الآخر عكس الحالة أي يولد الأطفال الأوائل باكرًا.
</p>

<p>
	يلجأ المشاركون غالبًا في هذه النقاشات إلى تقديم بيانات تدعم اعتقادهم مثل:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		أنجبت اثنتان من صديقاتي طفلهما الأول منذ فترة قريبة، ومَرّ أسبوعان بعد الموعد المتوقَّع قبل حدوث المخاض أو التحريض.
	</p>

	<p>
		أنجبتُ طفلي الأول بعد أسبوعين من الموعد المتوقَّع، وأعتقد الآن أنّ طفلي الثاني سيأتي قبل الموعد بأسبوعين.
	</p>

	<p>
		لا أعتقد أنّ هذا صحيح لأن أختي أتت باكرًا وهي الطفلة الأولى في العائلة، وكذلك الأمر بالنسبة للكثير من أطفال أقربائنا.
	</p>
</blockquote>

<p>
	تُدعى التقارير هذه بالأدلة القولية anecdotal evidence، لأنها تستند إلى بيانات غير منشورة وغالبًا ما تكون تجارب شخصية، ولا حرج في استخدامها في الأحاديث العادية أي لا ننتقد أصحاب الأقوال السابقة، لكن قد نحتاج إلى أدلة أكثر إقناعًا وإلى إجابة أكثر وثوقية، وعندها لا يمكننا استخدام الأدلة غير الموثَّقة للأسباب التالية:
</p>

<ul>
<li>
		وجود عدد صغير من الحالات: إذا كان الحمل بالأطفال الأوائل أطول من بقية الأطفال، فسيكون الفارق صغيرًا غالبًا إذا ما وازنّاه بالاختلافات الطبيعية، وفي هذه الحالة علينا دراسة عدد كبير من حالات الحمل حتى نتأكد من وجود الفارق.
	</li>
	<li>
		الانحياز الاختياري Selection bias: قد يكون المشاركون في النقاشات التي تدور حول هذا السؤال مهتمين بالأمر بسبب تأخر ولادة أطفالهم الأوائل، وفي هذه الحالة ستجعل عملية اختيار البيانات النتائجَ متحيزة.
	</li>
	<li>
		الانحياز التأكيدي Confirmation bias: من المرجَّح أن يطرح الأشخاص الذين يعتقدون بصحّة هذه المقولة أمثلةً تؤكِّد أفكارهم، ومن المرجَّح أن يطرح الأشخاص الذين يعتقدون أنّ هذه المقولة خاطئة أمثلةً معاكسة.
	</li>
	<li>
		عدم الدقة: غالبًا ما تكون الأدلة القولية قصصًا شخصيةً، وغالبًا ما تكون خاطئةً ومحرَّفةً ومكرَّرةً بصورة غير دقيقة.
	</li>
</ul>
<p>
	إذًا، كيف يمكننا الوصول إلى نتيجة أفضل؟
</p>

<h2>
	نهج إحصائي
</h2>

<p>
	سنستخدِم أدوات الإحصاء لتحديد قيود الأدلة القولية، حيث تتضمّن هذه الأدوات ما يلي:
</p>

<ul>
<li>
		جمع البيانات: سنستخدِم بيانات مأخوذة من مسح كبير على مستوى الدولة، حيث صُمّم خصّيصًا لتوليد استنتاجات صحيحة إحصائيًا حول سكان الولايات المتحِدة الأمريكية.
	</li>
	<li>
		الإحصائيات الوصفية: سنولِّد إحصائيات مهمتها تلخيص البيانات بإيجاز، وتقييم الطرق المختلفة التي يمكن فيها عرض البيانات.
	</li>
	<li>
		تحليل البيانات الاستكشافية: سنبحث عن الأنماط المتكرّرة والفروق وميزات أخرى تعالج المسألة التي نناقشها، كما سنتحقق في الوقت ذاته من التناقضات ونحدِّد القيود.
	</li>
	<li>
		التخمين Estimation: سنستخدم بيانات مأخوذة من عيّنة لتخمين صفات عامة الشعب.
	</li>
	<li>
		اختبار الفرضيات: سنقيِّم التأثيرات الواضحة -مثل فرق بين مجموعتين من الأشخاص- فيما إذا كان قد حدث التأثير بمحض الصدْفة أم لا.
	</li>
</ul>
<p>
	يمكننا الوصول إلى استنتاجات أكثر تبريرًا واحتمالًا لأن تكون صحيحةً عن طريق اتباع هذه الخطوات بعناية لتجنب العثرات والمطبّات.
</p>

<h2>
	المسح الوطني لنمو الأسرة
</h2>

<p>
	بدأت المراكز الأمريكية منذ عام 1973 بإجراء المسح الوطني لنمو الأسرة NSFG للسيطرة على الأمراض والوقاية منها CDC، إذ يهدف هذا المسح إلى جمع معلومات عن الحياة الأسريّة والزواج والطلاق والحمل والعقم واستخدام وسائل منع الحمل وصحّة النساء والرجال.
</p>

<p>
	تُستخدَم نتائج المسح من أجل تخطيط الخدمات الصحية وبرامج التثقيف الصحي، ومن أجل إجراء دراسات إحصائية حول الأُسر والخصوبة والصحة، كما يمكنك الاطّلاع على صفحة المسح على <a href="http://cdc.gov/nchs/nsfg.htm" rel="external nofollow">الموقع الرسمي للمراكز</a>
</p>

<p>
	سنستخدم البيانات التي جمِّعت أثناء هذا المسح للتحقق من تأخر ولادة الأطفال الأوائل وللإجابة على أسئلة أخرى أيضًا، كما علينا فهم تصميم الدراسة من أجل استخدام هذه البيانات بفعالية.
</p>

<p>
	يُعَدّ المسح الوطني لنمو الأسرة دراسةً مقطعيةً cross-sectional study، أي يخزِّن لقطةً سريعةً عن مجموعة محدَّدة في فترة محدَّدة من الزمن، كما تُعَدّ الدراسة الطولية longtitudal study البديل الأكثر شيوعًا، حيث تراقب مجموعةً معيَّنةً بصورة متكررة على مدار فترة زمنية.
</p>

<p>
	أُجري المسح الوطني لنمو الأسرة سبع مرات، حيث تسمى كل عملية نشر بدورة cycle، كما سنستخدِم بيانات الدورة السادسة التي أجريت من شهر 1 من عام 2002 حتى شهر 3 من عام 2003.
</p>

<p>
	يتلخص هدف المسح في الوصول إلى استنتاجات حول السكان، إذ تتراوح أعمار السكان المستهدَفِين من المسح الوطني لنمو الأسرة بين 15 و44 عامًا وهم أشخاص من الولايات المتحدة الأمريكية.
</p>

<p>
	يجمع المسح المثالي بيانات من كل فرد، ولكن نادرًا ما يكون هذا متاحًا أو ممكنًا، وبدلًا من ذلك تُجمَع البيانات من مجموعة معيَّنة من السكان تدعى عيّنة sample، كما يُطلق على المشاركين في المسح اسم المستجيبون respondents.
</p>

<p>
	يكون الهدف من إجراء الدراسات مقطعيًا هو جعلها تمثيلية representative عمومًا، بمعنى أن يكون لكل فرد من أفراد السكان فرصةً متساويةً من المشاركة، وعلى الرغم من كون هذه الحالة المثالية صعبة التحقيق عمليًا، إلا أنّ الأشخاص الذين يجرون الاستطلاعات يحاولون الاقتراب منها قدر الإمكان، كما لا يُعَدّ NSFG مسحًا تمثيليًا، وبدلًا من ذلك يُفرَط في أخذ العينات oversampled عمدًا.
</p>

<p>
	يتعامل مصممو الدراسة مع ثلاث مجموعات وهي: الهسبانيون (حسب مكتب التعداد فإنّ الهسباني أو اللاتيني هو شخص من كوبا أو المكسيك أو بورتوريكو أو أمريكا الجنوبية أو الوسطى أو غيرها من الأصول الإسبانية بغض النظر عن العرق) والأفارقة الأمريكيون (هم مجموعة عرقية من أصول أفريقية تعيش في القارتين الأمريكيتين) والمراهقون بمعدَّلات أعلى من تمثيلهم الحقيقي في الولايات المتحدة الأمريكية، وذلك للتأكد من أنّ عدد المستجيبين في هذه المجموعات كبير بما يكفي لاستخلاص استدلالات إحصائية صحيحة.
</p>

<p>
	يتمثّل الجانب السلبي من الإفراط في أخذ العينات بطبيعة الحال في صعوبة استخلاص استنتاجات حول عامة السكان بناءً على إحصاءات من المسح، وسنعود إلى هذه النقطة في وقت لاحق.
</p>

<p>
	من المهم أن نكون على دراية بما يعرف بدليل الأسس والمعايير codebook عند التعامل مع هذا النوع من البيانات، إذ توثِّق هذه السلسلة تصميم الدراسة وأسئلة المسح وترميز إجابات المستجيبين، كما يتوفر دليل الأسس والمعايير ومرشِد المستخدِم لبيانات NSFG <a href="http://www.cdc.gov/nchs/nsfg/nsfg_cycle6.htm" rel="external nofollow">هنا</a>.
</p>

<h2>
	استيراد البيانات
</h2>

<p>
	تتوفر الشيفرة والبيانات المستخدَمة في هذه السلسلة <a href="https://github.com/AllenDowney/ThinkStats2" rel="external nofollow">github</a>، حيثسيكون لديك ملف باسم <code>ThinkStats2/code/nsfg.py</code> فور تنزيل الشيفرة، وإذا شغّلت هذا الملف فسيقرأ ملف البيانات ويشغّل بعض الاختبارات ويطبع رسالة "All tests passed" تشير إلى نجاح جميع الاختبارات، وسنرى فيما يلي مهمة هذا الملف.
</p>

<p>
	توجد بيانات الحمل الخاصة بالدورة السادسة من NSFG في ملف يدعى <code>2002FemPreg.dat.gz</code>، وهو ملف بيانات مضغوط بتنسيق نصي بسيط ASCII وأعمدة ذات عرض ثابت، كما يحتوي كل سطر من الملف على سجل record يحوي بيانات حمل واحد.
</p>

<p>
	تنسيق الملف موثَّق في ملف قاموس لبرنامج ستاتا Stata وهو <code>2002FemPreg.dct</code>، كما يُعَدّ ستاتا نظامًا برمجيًا إحصائيًا؛ أما "dictionary" أي القاموس في هذا السياق، فهو قائمة بأسماء وأنواع وفهارس المتغيرات التي تحدِّد في أيّ سطر يوجد كل متغير من المتغيرات.
</p>

<p>
	فيما يلي بعض الأسطر من ملف <code>2002FemPreg.dct</code>على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_15" style="">
<span class="pln">infile dictionary </span><span class="pun">{</span><span class="pln">
  _column</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">  str12  caseid    </span><span class="pun">%</span><span class="lit">12s</span><span class="pln">  </span><span class="str">"RESPONDENT ID NUMBER"</span><span class="pln">
  _column</span><span class="pun">(</span><span class="lit">13</span><span class="pun">)</span><span class="pln"> byte   pregordr   </span><span class="pun">%</span><span class="lit">2f</span><span class="pln">  </span><span class="str">"PREGNANCY ORDER (NUMBER)"</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يصف هذا القاموس متغيرين: المتغير الأول <code>caseid</code> وهو سلسلة مكونة من 12 محرفًا تمثل معرِّف المستجيب؛ أما المتغير الثاني<code>pregordr</code> وهو عدد صحيح مؤلَّف من بايت واحد one-byte integer بحيث يشير إلى الحمل الذي يصفه هذا السجل لهذا المستجيب.
</p>

<p>
	تحتوي الشيفرة التي حمَّلتها على <code>thinkstats2.py</code>، وهو وحدة بايثون تحتوي على العديد من الأصناف والدوال المستخدَمة في هذه السلسلة بما في ذلك الدوال القارئة لقاموس ستاتا وملف بيانات NSFG، وإليك كيفية استخدامها في<code>nsfg.py</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_17" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">ReadFemPreg</span><span class="pun">(</span><span class="pln">dct_file</span><span class="pun">=</span><span class="str">'2002FemPreg.dct'</span><span class="pun">,</span><span class="pln">
                dat_file</span><span class="pun">=</span><span class="str">'2002FemPreg.dat.gz'</span><span class="pun">):</span><span class="pln">
    dct </span><span class="pun">=</span><span class="pln"> thinkstats2</span><span class="pun">.</span><span class="typ">ReadStataDct</span><span class="pun">(</span><span class="pln">dct_file</span><span class="pun">)</span><span class="pln">
    df </span><span class="pun">=</span><span class="pln"> dct</span><span class="pun">.</span><span class="typ">ReadFixedWidth</span><span class="pun">(</span><span class="pln">dat_file</span><span class="pun">,</span><span class="pln"> compression</span><span class="pun">=</span><span class="str">'gzip'</span><span class="pun">)</span><span class="pln">
    </span><span class="typ">CleanFemPreg</span><span class="pun">(</span><span class="pln">df</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> df</span></pre>

<p>
	يأخذ <code>ReadStataDct</code> اسم ملف القاموس ويُعيد <code>dct</code>، الذي هو كائن من النوع <code>FixedWidthVariables</code> يحتوي على معلومات من ملف القاموس، كما يوفر <code>dct</code> التابع <code>ReadFixedWidth</code> الذي يقرأ ملف البيانات.
</p>

<h2>
	إطارات البيانات
</h2>

<p>
	النتيجة التي يُعيدها التابع <code>ReadFixedWidth</code> هي إطار بيانات DataFrame، وهو بنية البيانات الأساسيّة التي توفرها بانداز pandas التي هي حزمة بيانات وإحصائيات خاصة بلغة بايثون، كما ستُستَخدم في هذه السلسلة.
</p>

<p>
	يتألف إطار البيانات من سطر لكل سجل، وفي هذه الحالة يكون سطر لكل حمل وعمود لكل متغير، كما يتألف إطار البيانات من أسماء المتغيرات وأنواعها، ويوفر توابع مهمتها الوصول إلى البيانات وتعديلها.
</p>

<p>
	إذا طبعنا df فسنحصل على عرض مقطوع truncated view للأسطر والأعمدة، وعلى شكل إطار البيانات الذي يتألف من 13593 سطر/سجل، و244 عمود/متغير.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_21" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> nsfg
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df </span><span class="pun">=</span><span class="pln"> nsfg</span><span class="pun">.</span><span class="typ">ReadFemPreg</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">[</span><span class="lit">13593</span><span class="pln"> rows x </span><span class="lit">244</span><span class="pln"> columns</span><span class="pun">]</span></pre>

<p>
	عُرض جزء من الخرج وأخُفي الباقي لأنّ حجم إطار البيانات أكبر من أن يُعرض كاملًا، ويُظهر السطر الأخير عدد الأسطر والأعمدة، كما تُعيد سمة الأعمدة <code>columns</code> سلسلةً من أسماء الأعمدة بتنسيق سلاسل الترميز الموحَّد Unicode:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_25" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">columns
</span><span class="typ">Index</span><span class="pun">([</span><span class="pln">u</span><span class="str">'caseid'</span><span class="pun">,</span><span class="pln"> u</span><span class="str">'pregordr'</span><span class="pun">,</span><span class="pln"> u</span><span class="str">'howpreg_n'</span><span class="pun">,</span><span class="pln"> u</span><span class="str">'howpreg_p'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">])</span></pre>

<p>
	تكون نتيجة ما سبق Index أي فهرسًا، وهو بنية بيانات من حزمة البانداز pandas، كما سنشرح بنية الفهرس لاحقًا، لكننا سنتعامل معه حاليًا على أساس قائمة list:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_23" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">columns</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
</span><span class="str">'pregordr'</span></pre>

<p>
	للوصول إلى أحد أعمدة إطار البيانات، يمكننا استخدام اسم العمود على أساس مفتاح:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_27" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pregordr </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">[</span><span class="str">'pregordr'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">pregordr</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'pandas.core.series.Series'</span><span class="pun">&gt;</span></pre>

<p>
	تكون نتيجة ما سبق هي Series أي سلسلةً، وهي بنية بيانات في حزمة البانداز pandas أيضًا.
</p>

<p>
	تشبه السلسلة نوع القائمة list الموجودة في لغة البايثون مع بعض الميزات الإضافية، وسنحصل على الفهارس والقيم المقابلة لها عند طباعة السلسلة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_29" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pregordr
</span><span class="lit">0</span><span class="pln">     </span><span class="lit">1</span><span class="pln">
</span><span class="lit">1</span><span class="pln">     </span><span class="lit">2</span><span class="pln">
</span><span class="lit">2</span><span class="pln">     </span><span class="lit">1</span><span class="pln">
</span><span class="lit">3</span><span class="pln">     </span><span class="lit">2</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="lit">13590</span><span class="pln">    </span><span class="lit">3</span><span class="pln">
</span><span class="lit">13591</span><span class="pln">    </span><span class="lit">4</span><span class="pln">
</span><span class="lit">13592</span><span class="pln">    </span><span class="lit">5</span><span class="pln">
</span><span class="typ">Name</span><span class="pun">:</span><span class="pln"> pregordr</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Length</span><span class="pun">:</span><span class="pln"> </span><span class="lit">13593</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">:</span><span class="pln"> int64</span></pre>

<p>
	نلاحظ في هذا المثال أنّ الفهارس هي أعداد صحيحة موجودة بين العددين 0 و13592، ولكن يمكنها أن تكون أيًا من الأنواع القابلة للفرز عمومًا، كما تُعَدّ العناصر أعدادًا صحيحةً ويمكنها أن تكون أيّ نوع آخر أيضًا.
</p>

<p>
	يتضمن السطر الأخير اسم المتغير وطول السلسلة ونوع البيانات، حيث يُعَدّ <code>int64</code> أحد الأنواع التي توفرها مكتبة نمباي NumPy، وإذا جرّبنا هذا المثال على آلة تعمل بنظام 32-بِتّ، فقد نحصل على<code>int32</code>.
</p>

<p>
	يمكن الوصول إلى عناصر السلسلة باستخدام فهارس وشرائح من الأعداد الصحيحة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_31" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pregordr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pregordr</span><span class="pun">[</span><span class="lit">2</span><span class="pun">:</span><span class="lit">5</span><span class="pun">]</span><span class="pln">
</span><span class="lit">2</span><span class="pln">    </span><span class="lit">1</span><span class="pln">
</span><span class="lit">3</span><span class="pln">    </span><span class="lit">2</span><span class="pln">
</span><span class="lit">4</span><span class="pln">    </span><span class="lit">3</span><span class="pln">
</span><span class="typ">Name</span><span class="pun">:</span><span class="pln"> pregordr</span><span class="pun">,</span><span class="pln"> dtype</span><span class="pun">:</span><span class="pln"> int64</span></pre>

<p>
	تكون نتيجة عامِل الفهرس هي <code>int64</code>، ونتيجة الشريحة سلسلةً أخرى، كما يمكننا الوصول إلى أعمدة إطار البيانات عن طريق استخدام صيغة الاستدعاء النقطية، أي كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_33" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> pregordr </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">pregordr</span></pre>

<p>
	لا يمكن استخدام هذه الصيغة إلا إذا كان اسم العمود مُعرِّفًا صالحًا في بايثون، لذا يجب أن يبدأ بحرف ولا يمكن أن يحتوي على فراغات، …إلخ.
</p>

<h2>
	المتغيرات
</h2>

<p>
	وجدنا في مجموعة بيانات NSFG متغيرَين اثنين وهما <code>caseid</code> و<code>pregordr</code>، كما لاحظنا وجود 244 متغير في كامل مجموعة بيانات NSFG.
</p>

<p>
	سنستخدِم المتغيرات التالية للوصول إلى الاستنتاجات في هذه السلسلة:
</p>

<ul>
<li>
		<code>caseid</code> عدد صحيح يمثل معرِّف المستجيب.
	</li>
	<li>
		<code>prglngth</code> عدد صحيح يمثل مدة الحمل مقاسة بالأسابيع.
	</li>
	<li>
		<code>outcome</code>: رمز صحيح يمثِّل نتيجة الحمل، حيث يشير الرقم 1 إلى تمام الولادة والطفل حي.
	</li>
	<li>
		<code>pregordr</code>: عدد تسلسلي للحمل، إذ يكون رمز الحمل الأوّل للمستجيب هو 1، ورمز الحمل الثاني هو 2 وهكذا على سبيل المثال.
	</li>
	<li>
		<code>birthord</code>: عدد تسلسلي للولادات الحية، حيث يكون رمز الطفل الأول للمستجيب هو 1؛ أما بالنسبة للولادات غير الحية فيبقى الحقل فارغًَا.
	</li>
	<li>
		<code>birthwgt_lb</code> و<code>birthwgt_oz</code>: يمثِّلان وزن الطفل عند ولادته، مقدرًا بالرطل وبالأوقية.
	</li>
	<li>
		<code>agepreg</code>: عمر الأم في نهاية الحمل.
	</li>
	<li>
		<code>finalwgt</code>: الوزن الإحصائي المرتبط بالمستجيب، وهو قيمة عشرية تمثِّل عدد سكان الولايات المتحِدة الأمريكية الذين يمثلهم المستجيب.
	</li>
</ul>
<p>
	إذا قرأت دليل الأسس والمعايير بعناية، فسترى أنّ العديد من المتغيرات هي متغيرات محسوبة القيمة recodes، أي أنها ليست جزءًا من البيانات الأولية raw data التي جُمِعت أثناء المسح، بل حُسِبت باستخدام البيانات الأولية، فمثلًا، يساوي المتغير <code>prglngth</code> للولادات الحية المتغير الأولي<code>wksgest</code> -أي عدد أسابيع الحمل- إذا كان متوفرًا، وإلا فسيُقدَّر باستخدام <code>mosgest * 4.33</code> -أي عدد أشهر الحمل مضروب بمتوسط عدد الأسابيع في الشهر الواحد-.
</p>

<p>
	تستند عمليات إعادة الترميز غالبًا إلى المنطق الذي يتحقق من اتساق البيانات ودقتها، كما من الجيد عمومًا اللجوء إلى استخدام إعادة الترميز إذا كانت متاحةً وما لم يكن هناك سبب مقنع يجبرنا على معالجة البيانات الأولية بأنفسنا.
</p>

<h2>
	عمليات التحويل
</h2>

<p>
	يتعين علينا غالبًا عند استيراد هذا النوع من البيانات التحقق من الأخطاء والتعامل مع قيم خاصة وتحويل البيانات إلى صيغ مختلفة وإجراء العمليات الحسابية، حيث تُسمى هذه العمليات بتنقية تنظيف البيانات data cleaning.
</p>

<p>
	يحتوي<code>nsfg.py</code> على <code>CleanFemPreg</code>، وهو دالة تُنقي المتغيرات التي نُخطِّط لاستخدامها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_36" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">CleanFemPreg</span><span class="pun">(</span><span class="pln">df</span><span class="pun">):</span><span class="pln">
    df</span><span class="pun">.</span><span class="pln">agepreg </span><span class="pun">/=</span><span class="pln"> </span><span class="lit">100.0</span><span class="pln">

    na_vals </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">97</span><span class="pun">,</span><span class="pln"> </span><span class="lit">98</span><span class="pun">,</span><span class="pln"> </span><span class="lit">99</span><span class="pun">]</span><span class="pln">
    df</span><span class="pun">.</span><span class="pln">birthwgt_lb</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">na_vals</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span><span class="pln"> inplace</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span><span class="pln">
    df</span><span class="pun">.</span><span class="pln">birthwgt_oz</span><span class="pun">.</span><span class="pln">replace</span><span class="pun">(</span><span class="pln">na_vals</span><span class="pun">,</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">nan</span><span class="pun">,</span><span class="pln"> inplace</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span><span class="pln">

    df</span><span class="pun">[</span><span class="str">'totalwgt_lb'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_lb </span><span class="pun">+</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_oz </span><span class="pun">/</span><span class="pln"> </span><span class="lit">16.0</span><span class="pln">  </span></pre>

<p>
	يحتوي متغير <code>agepreg</code> على عمر الأم في نهاية الحمل، كما يُرمَّز <code>agepreg</code> في ملف البيانات ليكون رقمًا صحيحًا يعبر عن السنوات، وبالتالي يقسِّم السطر الأول كل عنصر من عناصر <code>agepreg</code> على 100، مما ينتج عنه قيمة عشرية تمثِّل السنوات، كما يحتوي المتغيران <code>birthwgt_lb</code> و<code>birthwgt_oz</code> على وزن الطفل بالرطل والأوقية على الترتيب، وذلك لحالات الحمل التي تنتهي بولادة حيّة، كما يَستخدِمان عدة رموز خاصة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_38" style="">
<span class="lit">97</span><span class="pln">      NOT ASCERTAINED
</span><span class="lit">98</span><span class="pln">      REFUSED
</span><span class="lit">99</span><span class="pln">      DON</span><span class="str">'T KNOW</span></pre>

<p>
	تكمن خطورة القيم الخاصة المرمَّزة على أساس أعداد في عدم معالجتها بصورة صحيحة، إذ يمكنها توليد نتائج وهمية، مثل طفل بوزن 99 رطل.
</p>

<p>
	يستبدل التابع <code>replace</code> هذه القيم لتكون <code>np.nan</code>، وهي قيمة عشرية خاصة تمثِّل "ليس عددًا" أي Not a Number، كما تطلب راية <code>inplace</code> من التابع <code>replace</code> تعديل السلسلة الموجودة عوضًا عن إنشاء سلسلة جديدة.
</p>

<p>
	تُعيد جميع العمليات الرياضية <code>nan</code> إذا كان أيًا من الوسطاء <code>nan</code> أي "ليس عددًا"، وذلك على أساس جزء من معيار معهد مهندسي الكهرباء والإلكترونيات IEEE للعدد العشري، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_40" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> numpy </span><span class="kwd">as</span><span class="pln"> np
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">nan </span><span class="pun">/</span><span class="pln"> </span><span class="lit">100.0</span><span class="pln">
nan</span></pre>

<p>
	لذا غالبًا ما تفي الحسابات باستخدام <code>nan</code> بالغرض وتعطي النتيجة المطلوبة، كما تعالِج معظم دوال البانداز pandas ظهور <code>nan</code> بصورة مناسبة، لكن سنواجه مشكلةً متكرِّرةً وهي التعامل مع بيانات ناقصة.
</p>

<p>
	يُنشِئ السطر الأخير من <code>CleanFemPreg</code> عمودًا جديدًا <code>totalwgt_lb</code>، ويدمج الوزن بالرطل والأوقية في كمية واحدة تقاس بالرطل.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة هامة</strong>: عند إضافة عمود جديد إلى إطار بيانات، فيجب استخدام صيغة القاموس بالشكل التالي:
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_42" style="">
<span class="pln">    </span><span class="com"># CORRECT</span><span class="pln">
    df</span><span class="pun">[</span><span class="str">'totalwgt_lb'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_lb </span><span class="pun">+</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_oz </span><span class="pun">/</span><span class="pln"> </span><span class="lit">16.0</span><span class="pln"> </span></pre>

<p>
	وليس الصيغة النقطية التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_44" style="">
<span class="pln">    </span><span class="com"># WRONG!</span><span class="pln">
    df</span><span class="pun">.</span><span class="pln">totalwgt_lb </span><span class="pun">=</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_lb </span><span class="pun">+</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_oz </span><span class="pun">/</span><span class="pln"> </span><span class="lit">16.0</span><span class="pln"> </span></pre>

<p>
	يضيف الإصدار الذي يحتوي على الصيغة النقطية سمةً إلى كائن إطار البيانات، ولكن لايُتعامَل مع هذه السمة على أنها عمود جديد.
</p>

<h2>
	التحقق
</h2>

<p>
	قد تظهر أخطاء عند تصدير البيانات من بيئة برمجية معينة واستيرادها إلى بيئة أخرى، وعندما نتعرَّف على مجموعة بيانات جديدة، فقد تفسر البيانات بصورة غير صحيحة، أو قد تفهم أمرًا ما بصورة خاطئة، فإذا خصصت وقتًا للتحقق من صحة البيانات، فستستطيع توفير الوقت لاحقًا وستتجنب الوقوع في أخطاء.
</p>

<p>
	تتمثَّل إحدى طرق التحقق من البيانات في حساب الإحصائيات الأساسية وموازنتها مع النتائج المنشورة، إذ يلخِّص بدليل الأسس والمعايير الخاص بالـ NSFG كل متغير مثلًا.
</p>

<p>
	إليك جدولًا بالخرج، حيث رُمِّز كل خرج حمل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_46" style="">
<span class="pln">value   label                  </span><span class="typ">Total</span><span class="pln">
</span><span class="lit">1</span><span class="pln">       LIVE BIRTH              </span><span class="lit">9148</span><span class="pln">
</span><span class="lit">2</span><span class="pln">       INDUCED ABORTION        </span><span class="lit">1862</span><span class="pln">
</span><span class="lit">3</span><span class="pln">       STILLBIRTH               </span><span class="lit">120</span><span class="pln">
</span><span class="lit">4</span><span class="pln">       MISCARRIAGE             </span><span class="lit">1921</span><span class="pln">
</span><span class="lit">5</span><span class="pln">       ECTOPIC PREGNANCY        </span><span class="lit">190</span><span class="pln">
</span><span class="lit">6</span><span class="pln">       CURRENT PREGNANCY        </span><span class="lit">352</span></pre>

<p>
	يوفر صنف السلسلة Series تابعًا باسم <code>value_counts</code> مهمته حساب عدد المرات التي تظهر فيها كل قيمة، فإذا حددنا سلسلة <code>outcome</code> من إطار البيانات،فيمكننا استخدام <code>value_counts</code> لموازنتها مع البيانات المنشورة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_48" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">outcome</span><span class="pun">.</span><span class="pln">value_counts</span><span class="pun">().</span><span class="pln">sort_index</span><span class="pun">()</span><span class="pln">
</span><span class="lit">1</span><span class="pln">    </span><span class="lit">9148</span><span class="pln">
</span><span class="lit">2</span><span class="pln">    </span><span class="lit">1862</span><span class="pln">
</span><span class="lit">3</span><span class="pln">     </span><span class="lit">120</span><span class="pln">
</span><span class="lit">4</span><span class="pln">    </span><span class="lit">1921</span><span class="pln">
</span><span class="lit">5</span><span class="pln">     </span><span class="lit">190</span><span class="pln">
</span><span class="lit">6</span><span class="pln">     </span><span class="lit">352</span></pre>

<p>
	تكون نتيجة <code>value_counts</code> سلسلةً؛ أما <code>()sort_index</code> فسيفرز السلسلة حسب الفهرس بحيث تظهر القيم بالترتيب. وسنجد أن القيم في <code>outcome </code>صحيحة عند موازنة النتائج بالجدول المنشور، وبالمثل يكون هذا هو الجدول المنشور لـ <code>birthwgt_lb</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_50" style="">
<span class="pln">value   label                  </span><span class="typ">Total</span><span class="pln">
</span><span class="pun">.</span><span class="pln">       INAPPLICABLE            </span><span class="lit">4449</span><span class="pln">
</span><span class="lit">0</span><span class="pun">-</span><span class="lit">5</span><span class="pln">     UNDER </span><span class="lit">6</span><span class="pln"> POUNDS          </span><span class="lit">1125</span><span class="pln">
</span><span class="lit">6</span><span class="pln">       </span><span class="lit">6</span><span class="pln"> POUNDS                </span><span class="lit">2223</span><span class="pln">
</span><span class="lit">7</span><span class="pln">       </span><span class="lit">7</span><span class="pln"> POUNDS                </span><span class="lit">3049</span><span class="pln">
</span><span class="lit">8</span><span class="pln">       </span><span class="lit">8</span><span class="pln"> POUNDS                </span><span class="lit">1889</span><span class="pln">
</span><span class="lit">9</span><span class="pun">-</span><span class="lit">95</span><span class="pln">    </span><span class="lit">9</span><span class="pln"> POUNDS OR MORE         </span><span class="lit">799</span></pre>

<p>
	وهذه هي عدد مرات ظهور القيم:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_52" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">birthwgt_lb</span><span class="pun">.</span><span class="pln">value_counts</span><span class="pun">(</span><span class="pln">sort</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">)</span><span class="pln">
</span><span class="lit">0</span><span class="pln">        </span><span class="lit">8</span><span class="pln">
</span><span class="lit">1</span><span class="pln">       </span><span class="lit">40</span><span class="pln">
</span><span class="lit">2</span><span class="pln">       </span><span class="lit">53</span><span class="pln">
</span><span class="lit">3</span><span class="pln">       </span><span class="lit">98</span><span class="pln">
</span><span class="lit">4</span><span class="pln">      </span><span class="lit">229</span><span class="pln">
</span><span class="lit">5</span><span class="pln">      </span><span class="lit">697</span><span class="pln">
</span><span class="lit">6</span><span class="pln">     </span><span class="lit">2223</span><span class="pln">
</span><span class="lit">7</span><span class="pln">     </span><span class="lit">3049</span><span class="pln">
</span><span class="lit">8</span><span class="pln">     </span><span class="lit">1889</span><span class="pln">
</span><span class="lit">9</span><span class="pln">      </span><span class="lit">623</span><span class="pln">
</span><span class="lit">10</span><span class="pln">     </span><span class="lit">132</span><span class="pln">
</span><span class="lit">11</span><span class="pln">      </span><span class="lit">26</span><span class="pln">
</span><span class="lit">12</span><span class="pln">      </span><span class="lit">10</span><span class="pln">
</span><span class="lit">13</span><span class="pln">       </span><span class="lit">3</span><span class="pln">
</span><span class="lit">14</span><span class="pln">       </span><span class="lit">3</span><span class="pln">
</span><span class="lit">15</span><span class="pln">       </span><span class="lit">1</span><span class="pln">
</span><span class="lit">51</span><span class="pln">       </span><span class="lit">1</span></pre>

<p>
	تُعَدّ الإحصاءات counts الخاصة بـ 6 و7 و8 أرطالًا صحيحةً، وإذا جمعنا الإحصاءات للأرقام بين 0-5، و9-95 فسنجد أنها صحيحة أيضًا. ولكن إذا نظرنا عن كثب، فسنلاحظ وجود خطأ في قيمة واحدة وهي الطفل بوزن 51 رطلًا، لذا سنضيف سطرًا إلى <code>CleanFemPreg</code> للتعامل مع هذا الخطأ:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_54" style="">
<span class="pln">df</span><span class="pun">.</span><span class="pln">loc</span><span class="pun">[</span><span class="pln">df</span><span class="pun">.</span><span class="pln">birthwgt_lb </span><span class="pun">&gt;</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="str">'birthwgt_lb'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> np</span><span class="pun">.</span><span class="pln">nan</span></pre>

<p>
	تستبدِل هذه التعليمة القيم غير الصالحة لتكون <code>np.nan</code>، حيث تُوفِّر السمة <code>loc</code> عدة طرق لتحديد الصفوف والأعمدة من إطار البيانات، إذ يكون أول تعبير محاط بقوسين في هذا المثال مُفهرس الصف؛ أما التعبير الثاني فسيحدد العمود.
</p>

<p>
	ينتج عن التعبير <code>df.birthwgt_lb &gt; 20</code> سلسلةً من النوع البولياني <code>bool</code>، حيث تشير القيمة الصحيحة True إلى صحة الشرط، كما ستحدِّد السلسلة البوليانية المستخدَمة على أساس فهرس العناصر التي تحقق الشرط فقط.
</p>

<h2>
	التفسير
</h2>

<p>
	يجب التفكير بمستويَين في آن معًا لنستطيع العمل مع البيانات بفعالية، وهما مستوى الإحصائيات ومستوى السياق.
</p>

<p>
	سنلقي نظرةً على تسلسل sequence نتائج بعض المستجيبين مثلًا، كما يتعين علينا إجراء بعض المعالجة من أجل جمع بيانات الحمل لكل مستجيب، وذلك لأن ملفات البيانات منظَّمة، وهذا مثال على دالة تفعل ذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_56" style="">
<span class="kwd">def</span><span class="pln"> </span><span class="typ">MakePregMap</span><span class="pun">(</span><span class="pln">df</span><span class="pun">):</span><span class="pln">
    d </span><span class="pun">=</span><span class="pln"> defaultdict</span><span class="pun">(</span><span class="pln">list</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> index</span><span class="pun">,</span><span class="pln"> caseid </span><span class="kwd">in</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">caseid</span><span class="pun">.</span><span class="pln">iteritems</span><span class="pun">():</span><span class="pln">
        d</span><span class="pun">[</span><span class="pln">caseid</span><span class="pun">].</span><span class="pln">append</span><span class="pun">(</span><span class="pln">index</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> d</span></pre>

<p>
	يُعَدّ <code>df</code> إطار بيانات يحتوي على بيانات الحمل، كما يحصي تابع <code>iteritems</code> الفهرس - أي عدد الصنف- ومعرِّف الحالة <code>caseid</code> لكل حمل؛ أما <code>d</code> فهو قاموس يعيّن لكل معرِّف حالة قائمةً من الفهارس، وفي حال عدم معرفتك السابقة بـ <code>defaultdict</code> فهو وحدة <code>collections</code> في بايثون. كما يمكننا البحث عن مستجيب والحصول على فهارس حمل خاصة به باستخدام <code>d</code>.
</p>

<p>
	يبحث المثال التالي عن مستجيب ويطبع قائمةً بنتائج الحمل الخاص به:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_58" style="">
<span class="pun">&gt;&gt;&gt;</span><span class="pln"> caseid </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10229</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> preg_map </span><span class="pun">=</span><span class="pln"> nsfg</span><span class="pun">.</span><span class="typ">MakePregMap</span><span class="pun">(</span><span class="pln">df</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> indices </span><span class="pun">=</span><span class="pln"> preg_map</span><span class="pun">[</span><span class="pln">caseid</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> df</span><span class="pun">.</span><span class="pln">outcome</span><span class="pun">[</span><span class="pln">indices</span><span class="pun">].</span><span class="pln">values
</span><span class="pun">[</span><span class="lit">4</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">1</span><span class="pun">]</span></pre>

<p>
	تُعَدّ <code>indices</code> قائمةً بفهارس حالات الحمل الموافقة للمستجيب صاحب المعرِّف <code>10229</code>.
</p>

<p>
	يؤدي استخدام هذه القائمة على أساس فهرس لـ <code>df.outcome</code> إلى تحديد الأصناف المشار إليها وإنتاج سلسلة، ولكننا حددنا سمة <code>values</code> بدلًا من طباعة السلسلة كاملة، والتي هي مصفوفة نمباي NumPy array، حيث يدل رمز الخرج <code>1</code> على أنّ الولادة حية، ويدل الرمز <code>4</code> على حدوث إجهاض -أي انتهى الحمل انتهاءً ذاتيًا وغالبًا بدون سبب طبي معروف-.
</p>

<p>
	يُعَدّ احتمال مصادفة مستجيب حصل معه هذا ممكنًا إحصائيًا، فالإجهاض أمر شائع، إذ أبلغ مستجيبون آخرون عن عدة حالات إجهاض أو أكثر، ولكن إذا نظرنا إلى مستوى السياق، فسنجد هذه البيانات تحكي قصة امرأة حملت ست مرات وانتهى كل حمل بإجهاض؛ أما الحالة السابعة والأخيرة فقد انتهت بولادة حية، وإذا فكرنا بهذه البيانات بتعاطف، فمن الطبيعي أن نتأثر بالقصة التي تحكيها.
</p>

<p>
	يمثِّل كل سجل في مجموعة بيانات NSFG فردًا قدَّم إجابات صادقة عن العديد من الأسئلة الشخصية والصعبة، ويمكننا بالطبع استخدام هذه البيانات للإجابة عن أسئلة إحصائية حول الحياة الأسرية والإنجاب والصحة، كما علينا في الوقت ذاته النظر في الأشخاص الذين تمثلهم هذه البيانات ونقدِّم لهم الاحترام والامتنان.
</p>

<h2>
	تمارين
</h2>

<h3>
	التمرين الأول
</h3>

<p>
	ستجد في المستودع repository الذي حمَّلته ملفًا باسم <code>chap01ex.ipynb</code> وهو IPython notebook أي مفكرة من نوع IPython، كما يمكنك تشغيل IPython notebook من سطر الأوامر command line بالصورة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_60" style="">
<span class="pln">$ ipython notebook </span><span class="pun">&amp;</span></pre>

<p>
	يجب عليك إذا ثُبِّت IPython تشغيل خادم يعمل في الخلفية وفتح متصفح ويب من أجل عرض المفكرة، وإذا لم تكن معتادًا على IPython، فمن الأفضل البدء من <a href="http://ipython.org/ipython-doc/stable/notebook/notebook.html." rel="external nofollow">IPython notebook</a>، والذي يجب لفتحه تشغيل ما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1076_63" style="">
<span class="pln">$ ipython notebook </span><span class="pun">&amp;</span></pre>

<p>
	يجب فتح نافذة متصفح ويب جديدة، وإن لم يحصل هذا، فستوفِّر رسالة بدء التشغيل محدِّد موارد مُوحَّد هو رابط URL، والذي يمكنك تحميله في المتصفح، وغالبًا ما يكون http://localhost:8888، كما يجب أن تُظهِر النافذة الجديدة قائمةً بكل الـ notebooks الموجودة في المستودع.
</p>

<p>
	افتح <code>chap01ex.ipynb</code>، حيث مُلِئت بعض الخلايا وعليك تنفيذها؛ أما الخلايا الأخرى فستزودك بتعليمات حول التمارين التي يجب عليك تجريبها.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة</strong>: حل هذا التمرين موجود في <code>chap01soln.ipynb</code>.
	</p>
</blockquote>

<h3>
	التمرين الثاني
</h3>

<p>
	ستجد في المستودع repository الذي حمَّلته ملفًا باسم <code>chap01ex.py</code>، اكتب دالةً تقرأ ملف المستجيب <code>2002FemResp.dat.gz</code> باستخدام هذا الملف على أساس نقطة انطلاق. يكون المتغير <code>pregnum</code> هو ترميز يشير إلى عدد المرات التي حدث فيها حمل مع المستجيب، وبالتالي اطبع عدد القيم value counts الخاصة بهذا المتغير ووازنها مع النتائج المنشورة في دليل الأسس والمعايير لـ NSFG.
</p>

<p>
	يمكنك التحقق من ملفات المستجيب والحمل عن طريق موازنة متغير <code>pregnum</code> مع عدد السجلات في ملف الحمل أيضًا، كما يمكنك استخدام <code>nsfg.MalePregMap</code> لإنشاء قاموس يصل بين كل <code>caseid</code> إلى قائمة من الفهارس في إطار بيانات الحمل.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة</strong>: حل هذا التمرين موجود في <code>chap01soln.py</code>.
	</p>
</blockquote>

<h3>
	التمرين الثالث
</h3>

<p>
	يُعَدّ العمل على مشروع يهمّك هو الطريقة الأفضل لتعلُّم الإحصاء، فهل ترغب بالتحقيق في سؤال مثل "هل تتأخر ولادة الأطفال الأوائل؟" فكِّر في أسئلة تجدها مثيرةً للاهتمام أو أفكار حول الحكمة التقليدية، أو مواضيع مثيرة للجدل، وانظر فيما إذا كنت تستطيع صياغة سؤال يفسح لك المجال أمام استقصاء إحصائي، وبعدها ابحث عن البيانات لكي تساعدك على تناول السؤال، وتُعَدّ الحكومات مصادر جيدة لأن البيانات من البحوث العامة غالبًا ما تكون متاحة مجانًا دون مقابل.
</p>

<p>
	إليك بعض المواقع الجيدة التي يمكنك البدء منها <a href="http://www.data.gov/" rel="external nofollow">data.gov</a> وفي المملكة المتحدة الموقع التالي <a href="https://data.gov.uk/" rel="external nofollow">gov.uk</a>.
</p>

<p>
	توجد اثنتان من مجموعات البيانات المفضلة لدينا، وهما <a href="http://www3.norc.org/gss+website" rel="external nofollow">المسح الاجتماعي العام</a> و<a href="http://www.europeansocialsurvey.org/" rel="external nofollow">المسح الاجتماعي الأوروبي</a>.
</p>

<p>
	إذا أجاب أحد ما عن سؤالك، فألق نظرةً عن كثب لترى ما إذا كان الجواب مبررًا، فقد تكون هناك أخطاء في البيانات أو التحليل تجعل النتيجة غير موثوقة، ويمكنك في هذه الحالة إجراء تحليل آخر على البيانات ذاتها أو البحث عن مصدر أفضل للبيانات.
</p>

<p>
	إذا وجدت ورقة بحث منشورة تتناول سؤالك، فيجب أن تكون قادرًا على الحصول على البيانات الأولية، حيث يتيح الكثير من المؤلفِين بياناتهم على الإنترنت، ولكن قد تضطر إلى التواصل مع المؤلفِين من أجل البيانات الحساسة، وتخبرهم بما تخطط له لاستخدام البيانات، أو ربما عليك الموافقة على شروط محدَّدة، لذلك كن مثابرًا.
</p>

<h2>
	المفاهيم الأساسية
</h2>

<ul>
<li>
		<strong>الأدلة القولية anecdotal evidence</strong>: أدلة جُمِّعت بصورة عرضية بدلًا من دراسة مصمَّمة بصورة جيدة، وغالبًا ما تكون شخصية.
	</li>
	<li>
		<strong>السكان population</strong>: مجموعة من أشخاص هم محط اهتمام دراستنا، وغالبًا ما تشير كلمة "سكّان" إلى مجموعة من الأشخاص؛ إلا أنه يمكن استخدام هذا المصطلح لمواضيع أخرى أيضًا.
	</li>
	<li>
		<strong>الدراسة المقطعية cross-sectional study</strong>: هي الدراسة التي تجمع البيانات عن السكان في نقطة محدَّدة من الزمن.
	</li>
	<li>
		<strong>دورة cycle</strong>: في الدراسة المقطعية التي تتكرر عدة مرات، يُدعى كل تكرار للدراسة بدورة.
	</li>
	<li>
		<strong>الدراسة الطولية longitudinal study</strong>: هي الدراسة التي تتبع السكان على طول فترة من الزمن، وتجمع البيانات من المجموعة ذاتها بصورة متكرِّرة.
	</li>
	<li>
		<strong>سجل record</strong>: في مجموعة البيانات، فإنّ السجل هو تجميعة من المعلومات حول شخص واحد أو موضوع معين.
	</li>
	<li>
		<strong>مستجيب respondent</strong>: هو الشخص الذي يستجيب للمسح الإحصائي.
	</li>
	<li>
		<strong>عيّنة sample</strong>: هي مجموعة فرعية من السكان الذين تُجمع البيانات منهم.
	</li>
	<li>
		<strong>تمثيلي representative</strong>: تكون العينة تمثيليةً إذا كان لكل فرد من السكّان فرصةً متساويةً ليكون في العينة.
	</li>
	<li>
		<strong>الإفراط في أخذ العينات oversampling</strong>: تعتمد هذه التقنية على زيادة تمثيل مجموعة فرعية من السكّان لتجنب الأخطاء الناجمة عن صغر أحجام العينات.
	</li>
	<li>
		<strong>البيانات الأولية raw data</strong>: هي القيم التي تُجمَع وتُسجَّل مع القليل من عمليات التحقّق أو الحساب أو التفسير إن وجدت.
	</li>
	<li>
		<strong>متغير محسوب القيمة recode</strong>: قيمة مولَّدة عن طريق حسابات على البيانات الأولية أو عن طريق تطبيق منطق آخر عليها.
	</li>
	<li>
		<strong>تنقية البيانات data cleaning</strong>: هي العمليات التي تشمل التحقق من البيانات وتحديد الأخطاء والتحويل بين أنواع البيانات والتمثيلات، …إلخ.
	</li>
</ul>
<p>
	ترجمة -بتصرف- للفصل الأول <a href="https://greenteapress.com/thinkstats2/html/thinkstats2002.html" rel="external nofollow">Chapter 1 Exploratory data analysis</a> من كتاب <a href="https://greenteapress.com/wp/think-stats-2e/" rel="external nofollow">Think Stats: Exploratory Data Analysis in Python</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D8%AA%D8%B7%D9%88%D9%8A%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r1271/" rel="">تطويع البيانات في جافاسكربت</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/databases/%D8%AA%D8%AD%D9%84%D9%8A%D9%84-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%84%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%AA%D8%AE%D8%B2%D9%8A%D9%86%D9%87%D8%A7-%D9%88%D8%A7%D8%AE%D8%AA%D9%84%D8%A7%D9%81%D9%87-%D8%B9%D9%86-%D9%86%D8%B8%D8%A7%D9%85-%D9%82%D8%A7%D8%B9%D8%AF%D8%A9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r509/" rel="">تحليل نظام الملفات لإدارة البيانات وتخزينها واختلافه عن نظام قاعدة البيانات</a>
	</li>
	<li>
		النسخة الكاملة  لكتاب <a href="https://academy.hsoub.com/files/17-%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A-%D9%88%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9/" rel="">مدخل إلى الذكاء الاصطناعي وتعلم الآلة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1246</guid><pubDate>Fri, 04 Jun 2021 12:00:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x631;&#x62D;&#x64A;&#x644; &#x634;&#x64A;&#x641;&#x631;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 2 &#x625;&#x644;&#x649; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B1%D8%AD%D9%8A%D9%84-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-2-%D8%A5%D9%84%D9%89-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r759/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db042929ef25_----2---3.jpg.f363ac970699ab16f2b315a3eb13109f.jpg" /></p>
<p>
	طُوِّرَت بايثون في أواخر الثمانينات، وأُطلقَت لأول مرة عام 1991. استُوحي اسمها من المجموعة الكوميدية البريطانية Monty Python، تُعدُّ بايثون خليفة للغة البرمجة ABC متعددة الأغراض. تضمنت بايثون في إصداراتها الأولى معالجة الاستثناءات، و<a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/" rel="">الدوال</a>، <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%B1%D8%A7%D8%AB%D8%A9-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r756/" rel="">والأصناف والوراثة</a>.
</p>
<style type="text/css">
table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; }</style>
<p>
	سيرشدك هذا الدرس إلى أفضل آليات وممارسات ترحيل الشيفرات من بايثون 2 إلى بايثون 3، وما إن كان عليك جعل الشيفرة متوافقة مع كلا الإصدارين.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32150" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db0429446d37_----2---3.jpg.1976a68b00ce54135667b5403409737a.jpg" rel="" data-fileext="jpg"><img alt="كيـفـيــة-تـرحـيـــل-شيفرة-بايثون-2-إلـى-بـايـثــــــون-3.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32150" data-unique="tep0jqgzq" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db042945c5e2_----2---3.thumb.jpg.bb2a3b52cc926d5190ac939a5ec68767.jpg"></a>
</p>

<h2>
	خلفية عامة
</h2>

<p>
	صدر الإصدار 2 من بايثون عام 2000، ليُدشِّن حقبةً جديدةً من التطوير تقوم على الشفافية والشمولية، إذ شمل هذا الإصدار العديد من الميزات البرمجية، واستمر في إضافة المزيد طوال مدة تطويره.
</p>

<p>
	يُعد إصدار <strong>بايثون 3</strong> مستقبل بايثون، وهو إصدار اللغة قيد التطوير حاليًا، فجاء في أواخر عام 2008، ليعالج العديد من عيوب التصميم الداخلية ويُعدِّلها. بيْد أنَّ اعتماد بايثون 3 كان بطيئًا بسبب عدم توافقه مع بايثون 2.
</p>

<p>
	في خضم ذلك، جاء الإصدار <strong>بايثون 2.7</strong> في عام 2010 ليكون آخر إصدارات بايثون ‎2.x وليُسِّهل على مستخدمي بايثون ‎2.x الانتقال إلى بايثون 3 من خلال توفير قدر من التوافق بين الاثنتين، فهذا هو الهدف الأساسي من إطلاقه.
</p>

<p>
	يمكنك معرفة المزيد حول إصدارات بايثون والاختيار من بينها من المقالة: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B9%D8%AA%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D9%85%D8%A7-%D8%A8%D9%8A%D9%86-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-2-%D9%88-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r483/" rel="">اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3</a>.
</p>

<h2>
	ابدأ ببايثون 2.7
</h2>

<p>
	للانتقال إلى بايثون 3، أو لدعم بايثون 2 وبايثون 3 معًا، يجب عليك التأكد من أنّ شيفرة بايثون 2 متوافقة تمامًا مع بايثون 2.7.
</p>

<p>
	يعمل العديد من المطورين حصريًا بشيفرات بايثون 2.7، أمَّا المبرمجون الذي يعملون بشيفرات أقدم، فعليهم أن يتأكدوا من أنّ الشيفرة تعمل جيدًا مع بايثون 2.7، وتتوافق معه.
</p>

<p>
	التأكُّد من توافق الشيفرة مع بايثون 2.7 أمرٌ بالغ الأهمية لأنه الإصدار الوحيد من بايثون 2 الذي ما يزال قيد الصيانة، وتُصحَّحُ ثغراته. فإذا كنت تعمل بإصدار سابق من بايثون 2، فستجد نفسك تتعامل مع مشكلات في شيفرة لم تعد مدعومة، ولم تعد ثغراتها تُصحَّح.
</p>

<p>
	هناك أيضًا بعض الأدوات التي تسِّهل ترحيل الشيفرة، مثل الحزمة <a href="https://pypi.python.org/pypi/pylint" rel="external nofollow">Pylint</a> التي تبحث عن الأخطاء البرمجية، لكن لا تدعمها إصدارات بايثون السابقة للإصدار 2.7.
</p>

<p>
	من المهم أن تضع في حسبانك أنَّه رغم أنَّ بايثون 2.7 ما زالت قيد الدعم والصيانة في الوقت الحالي، إلا أنَّها ستموت في النهاية. ستجد في <a href="http://legacy.python.org/dev/peps/pep-0373/" rel="external nofollow">PEP 373</a> تفاصيل الجدول الزمني لإصدار بايثون 2.7، وفي وقت كتابة هذا المقال، فإنّ أجل بايثون 2.7 حُدِّد في عام 2020 (يحتمل أن تكون قد ماتت وأنت تقرأ هذه السطور :-| ).
</p>

<h2>
	الاختبار
</h2>

<p>
	اختبار الشيفرة جزءٌ أساسيٌّ من عملية ترحيل شيفرة بايثون 2 إلى بايثون 3. فإذا كنت تعمل على أكثر من إصدار واحد من بايثون، فعليك أيضًا التحقُّق من أنَّ أدوات الاختبار التي تستخدمها تغطي جميع الإصدارات للتأكُّد من أنَّها تعمل كما هو متوقع.
</p>

<p>
	يمكنك إضافة حالات بايثون التفاعلية (interactive Python cases) إلى السلاسل النصية التوثيقية (docstrings) الخاصة بكافة الدوال والتوابع والأصناف والوحدات، ثم استخدام <a href="https://docs.python.org/3.6/library/doctest.html" rel="external nofollow">الوحدة <code>doctest</code></a> المضمنة للتحقق من أنها تعمل كما هو موضح، إذ يعدُّ ذلك جزءًا من عملية الاختبار.
</p>

<p>
	إلى جانب <code>doctest</code>، يمكنك استخدام <a href="https://pypi.python.org/pypi/coverage" rel="external nofollow">الحزمة <code>package.py</code></a> لتتبع وحدة الاختبار. ستراقب هذه الأداة برنامجك وتحدد الأجزاء التي تُنفِّذها من الشيفرة، والأجزاء التي يمكن تنفيذها ولكن لم تُنفَّذ. يمكن أن تطبع <code>Cover.py</code> تقارير في سطر الأوامر، أو تنتج مستند <a href="https://wiki.hsoub.com/HTML" rel="external">HTML</a>. تُستخدم عادةً لقياس فعالية الاختبارات، إذ توضح الأجزاء من الشيفرة التي اختُبِرت، والأجزاء التي لم تُختبَر.
</p>

<p>
	تَذكَّر أنه ليس عليك اختبار كل شيء، لكن تأكَّد من تغطية أيّ شيفرة غامضة أو غير عادية. للحصول على أفضل النتائج، يُنصح أن تشمل التغطية 80٪ من الشيفرة.
</p>

<h2>
	تعرف على الاختلافات بين بايثون 2 و بايثون 3
</h2>

<p>
	سيمكّنك التعرّف على الاختلافات بين بايثون 2 و بايثون 3 من استخدام الميزات الجديدة المتاحة، أو التي ستكون متاحة في بايثون 3.
</p>

<p>
	تتطرق مقالتنا حول "<a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B9%D8%AA%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D9%85%D8%A7-%D8%A8%D9%8A%D9%86-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-2-%D9%88-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r483/" rel="">اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3</a>" إلى بعض الاختلافات الرئيسية بين الإصدارين. يمكنك أيضًا مراجعة <a href="https://docs.python.org/3/" rel="external nofollow">توثيق بايثون الرسمي</a> لمزيد من التفاصيل.
</p>

<p>
	عند البدء في ترحيل الشيفرة، فهناك بعض التغييرات في الصياغة عليك تنفيذها فوريًا.
</p>

<ul>
	<li>
		<code>print</code> حلت الدالة print()<code>‎‎</code> في بايثون 3 مكان التعليمة <code>print</code> في بايثون 2:
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				"مرحبا بالعالم!" print
			</td>
			<td>
				("مرحبا بالعالم!")print
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		<code>exec</code> تغيَّرت التعليمة <code>exec</code> في بايثون 2 وأصبحت دالةً تسمح بمتغيرات محلية (locals) وعامة (globals) صريحة في بايثون 3:
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				exec code
			</td>
			<td>
				exec(code)‎
			</td>
		</tr>
		<tr>
			<td>
				exec code in globals
			</td>
			<td>
				exec(code, globals)‎
			</td>
		</tr>
		<tr>
			<td>
				exec code in (globals, locals)‎
			</td>
			<td>
				exec(code, globals, locals)‎
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		<code>/</code> و <code>//</code> تُجرِي بايثون 2 <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D8%AC%D8%B1%D8%A7%D8%A1-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%AD%D8%B3%D8%A7%D8%A8%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r730/" rel="">القسمة التقريبية</a> (floor division) بالعامل <code>/</code> ، بينما تخصص بايثون 3 العامل <code>//</code> لإجراء القسمة التقريبية:
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				‎5 / 2 = 2‎
			</td>
			<td>
				‎5 / 2 = 2.5‎
			</td>
		</tr>
		<tr>
			<td>
				 
			</td>
			<td>
				‎5 // 2 = 2‎
			</td>
		</tr>
	</tbody>
</table>

<p>
	لاستخدام هذين المعاملين في بايثون 2، <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r744/" rel="">استورد</a> <code>division</code> من الوحدة <code>__future__</code>:
</p>

<pre class="ipsCode">from __future__ import division
</pre>

<p>
	اقرأ المزيد عن قسمة الأعداد الصحيحة من المقالة: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%B9%D8%AA%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D9%84%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D9%85%D8%A7-%D8%A8%D9%8A%D9%86-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-2-%D9%88-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r483/" rel="">اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3</a>.
</p>

<ul>
	<li>
		<code>raise</code> في بايثون 3، يتطلب إطلاق الاستثناءات ذات الوسائط استخدام الأقواس، كما لا يمكن استخدام <a href="https://wiki.hsoub.com/Python/str" rel="external">السلاسل النصية</a> كاستثناءات:
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				raise Exception, args
			</td>
			<td>
				raise Exception
			</td>
		</tr>
		<tr>
			<td>
				 
			</td>
			<td>
				raise Exception(args)‎
			</td>
		</tr>
		<tr>
			<td>
				raise Exception, args, traceback
			</td>
			<td>
				raise Exception(args).with_traceback(traceback)‎
			</td>
		</tr>
		<tr>
			<td>
				raise "Error"‎
			</td>
			<td>
				raise Exception("Error")‎
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		<code>except</code> في بايثون 2، كان من الصعب إدراج الاستثناءات المُتعدِّدة، لكن ذلك تغيَّر في بايثون 3.
	</li>
</ul>

<p>
	لاحظ أنَّ <code>as</code> تُستخدَم صراحةً مع <code>except</code> في بايثون 3:
</p>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				except Exception, variable:‎
			</td>
			<td>
				except AnException as variable:‎
			</td>
		</tr>
		<tr>
			<td>
				 
			</td>
			<td>
				except (OneException, TwoException) as variable:‎
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		<code>def</code> في بايثون 2، يمكن للدوال أن تقبل سلاسل مثل <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-tuples-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r507/" rel="">الصفوف</a> أو <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%A6%D9%85-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r733/" rel="">القوائم</a>. أمَّا في بايثون 3، فقد أزيل هذا الأمر.
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				def function(arg1, (x, y)):‎
			</td>
			<td>
				def function(arg1, x_y): x, y = x_y
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		<code>expr</code> لم تعد صياغة علامة الاقتباس المائلة <code>`` في بايثون 2 صالحة، واستخدم بدلًا عنها repr()</code>‎<code>أو</code>str.format()‎` في بايثون 3.
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				`x = `355/113``
			</td>
			<td>
				`x = repr(355/113):`
			</td>
		</tr>
	</tbody>
</table>

<p>
	 
</p>

<ul>
	<li>
		تنسيق السلاسل النصية (String Formatting) لقد تغيرت صياغة تنسيق السلاسل النصية من بايثون 2 إلى بايثون 3.
	</li>
</ul>

<table>
	<tbody>
		<tr>
			<th>
				بايثون 2
			</th>
			<th>
				بايثون 3
			</th>
		</tr>
		<tr>
			<td>
				`"%d %s" % (i, s)`
			</td>
			<td>
				`"{} {}".format(i, s)`
			</td>
		</tr>
		<tr>
			<td>
				`"%d/%d=%f" % (355, 113, 355/113)`
			</td>
			<td>
				`"{:d}/{:d}={:f}".format(355, 113, 355/113)`
			</td>
		</tr>
	</tbody>
</table>

<p>
	تعلم كيفية استخدام تنسيقات السلاسل النصية في بايثون 3 من مقالة <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A2%D9%84%D9%8A%D8%A9-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D8%B3%D9%84%D8%A7%D8%B3%D9%84-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r492/" rel="">كيفية استخدام آلية تنسيق السلاسل النصية في بايثون 3</a>.
</p>

<ul>
	<li>
		<p>
			<code>class</code> ليست هناك حاجة لتمرير <code>object</code> في بايثون 3.
		</p>

		<ul>
			<li>
				بايثون 2
			</li>
		</ul>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_7" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="pln">object</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<ul>
	<li>
		<ul>
			<li>
				 بايثون 3
			</li>
		</ul>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_10" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<p>
	 
</p>

<ul>
	<li>
		في بايثون 3، تُضبَط الأصناف العليا (metaclasses) بالكلمة مفتاحية <code>metaclass</code>.

		<ul>
			<li>
				بايثون 2:
			</li>
		</ul>
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_12" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">:</span><span class="pln">
    __metaclass__ </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MyMeta</span></pre>

<p>
	 
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_14" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="typ">MyBase</span><span class="pun">):</span><span class="pln">
    __metaclass__ </span><span class="pun">=</span><span class="pln"> </span><span class="typ">MyMeta</span></pre>

<ul>
	<li>
		<ul>
			<li>
				 بايثون 3:
			</li>
		</ul>
	</li>
</ul>

<div aria-label="pre widget" contenteditable="false" role="region" tabindex="-1">
	 
</div>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_16" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="pln">metaclass</span><span class="pun">=</span><span class="pln">type</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_20" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">MyClass</span><span class="pun">(</span><span class="typ">MyBase</span><span class="pun">,</span><span class="pln"> metaclass</span><span class="pun">=</span><span class="typ">MyMeta</span><span class="pun">):</span><span class="pln"> 
    </span><span class="kwd">pass</span></pre>

<h2>
	تحديث الشيفرة
</h2>

<p>
	هناك أدَاتان رئيّسيتان لتَحديث الشيفرة تلقائيًا إلى بايثون 3 مع الحفاظ على توافقيّتها مع بايثون 2 وهما: <a href="http://python-future.org/automatic_conversion.html" rel="external nofollow">future</a> و <a href="https://python-modernize.readthedocs.io/en/latest/" rel="external nofollow">modernize</a>. تختلف آليَتا عمل هاتين الأداتين، إذ تحاول <code>future</code> نقل أفضل ممارسات بايثون 3 إلى بايثون 2، في حين أنّ <code>modernize</code> تسعى إلى إنشاء شيفرات موحدة لبايثون تتوافق مع 2 و 3 وتستخدم الوحدة <code>six</code> لتحسين التوافقية.
</p>

<p>
	يمكن أن تساعدك هاتان الأداتان في إعادة كتابة الشيفرة وتحديد ورصد المشاكل المحتملة وتصحيحها.
</p>

<p>
	يمكنك تشغيل الأداة عبر مجموعة unittest لفحص الشيفرة والتحقق منها بصريًا، والتأكد من أنّ المراجعات التلقائية التي أُجريَت دقيقة. وبمجرد انتهاء الاختبارات، يمكنك تحويل الشيفرة.
</p>

<p>
	بعد هذا، ستحتاج على الأرجح إلى إجراء مراجعة يدوية، وخاصة استهداف الاختلافات بين بايثون 2 و 3 المذكورة في القسم أعلاه.
</p>

<p>
	إن أردت استخدام <code>future</code>، فعليك إضافة عبارة الاستيراد التالية في جميع وحدات بايثون 2.7:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1401_22" style=""><span class="kwd">from</span><span class="pln"> __future__ </span><span class="kwd">import</span><span class="pln"> print_function</span><span class="pun">,</span><span class="pln"> division</span><span class="pun">,</span><span class="pln"> absolute_imports</span><span class="pun">,</span><span class="pln"> unicode_literals</span></pre>

<p>
	رغم أن هذا لن يعفيك من إعادة كتابة الشيفرة، إلا أنه سيضمن لك أن تتماشى شيفرة بايثون 2 مع صياغة بايثون 3.
</p>

<p>
	أخيرًا، يمكنك استخدام <a href="https://pypi.python.org/pypi/pylint" rel="external nofollow">الحزمة <code>pylint</code></a> لتحديد ورصد أي مشكلات محتملة أخرى في الشيفرة. تحتوي هذه الحزمة على مئات القواعد التي تغطي مجموعة واسعة من المشكلات التي قد تطرأ، بما فيها قواعد <a href="https://www.python.org/dev/peps/pep-0008/" rel="external nofollow">الدليل PEP 8</a>، بالإضافة إلى أخطاء الاستخدام.
</p>

<p>
	قد تجد أنّ بعض أجزاء شيفرتك تربك <code>pylint</code> وأدوات الترحيل التلقائي الأخرى. حاول تبسيطها، أو استخدم <a href="https://docs.python.org/3/library/unittest.html" rel="external nofollow">unittest</a>.
</p>

<h2>
	التكامل المستمر (Continuous Integration)
</h2>

<p>
	إذا أردت أن تجعل شفرتك متوافقة مع عدة إصدارات من بايثون، فستحتاج إلى تشغيل الإطار unittest باستمرار وفق مبدأ التكامل المستمر (وليس يدويًا)، أي أن تفعل ذلك أكبر عدد ممكن من المرات أثناء عملية التطوير.
</p>

<p>
	إذا كنت تستخدم <a href="https://pypi.python.org/pypi/six" rel="external nofollow">الحزمة <code>six</code></a> لصيانة التوافقية بين بايثون 2 و 3، فستحتاج إلى استخدام عدة بيئات عمل لأجل الاختبار.
</p>

<p>
	إحدى حزم إدارة البيئة التي قد تكون مفيدة لك هي <a href="https://pypi.python.org/pypi/tox" rel="external nofollow">الحزمة <code>tox</code></a>، إذ ستفحص تثبيتات الحزمة مع مختلف إصدارات بايثون، وإجراء الاختبارات في كل بيئة من بيئات عملك، كما يمكن أن تكون بمثابة واجهة عمل للتكامل المستمر.
</p>

<h2>
	خلاصة
</h2>

<p>
	من المهم أن تعلم أنه مع ازدياد تركيز المطورين على بايثون 3، فستصبح اللغة أكثر دقةً وتماشيًا مع احتياجات المبرمجين، وسيضعف دعم بايثون 2.7. إذا قرَّرت أن تجعل شيفرتك متوافقة مع كل من بايثون 2 و بايثون 3، فقد تواجه صعوبة في ذلك لأنَّ بايثون 2 ستتلقى دعمًا أقل مع مرور الوقت.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-port-python-2-code-to-python-3" rel="external nofollow">How To Port Python 2 Code to Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-logging-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r546/" rel="">كيف تستخدم التسجيل Logging في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D9%85%D9%8A%D8%B2%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعرف على أبرز مميزات لغة بايثون</a><br>
		 
	</li>
</ul>
]]></description><guid isPermaLink="false">759</guid><pubDate>Wed, 27 Nov 2019 14:02:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x627;&#x644;&#x62A;&#x633;&#x62C;&#x64A;&#x644; Logging &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-logging-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r546/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db03a32cea3e_---Logging--.jpg.592843baa97e442f74eb1889c82a165c.jpg" /></p>

<p>
	تأتي وحدة التسجيل (logging) مبدئيا توزيعة بايثون المعيارية وتقدم حلا لمتابعة الأحداث التي تحصُل أثناء عمل البرمجية. تستطيع إضافة استدعاءات التسجيل للشيفرة البرمجية الخاصة بك للإشارة لما تحقق من أحداث.<br>
	تسمح لك وحدة التسجيل بإعداد كل من التسجيلات التشخيصية التي تسجل الأحداث المقترنة بعمليات التطبيق، بالإضافة إلى تسجيلات التدقيق التي تسجل الأحداث الخاصة بحركات المستخدم بهدف تحليلها. وحدة التسجيل هذه مختصة في حفظ السجلات في ملفات.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32148" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db03a34f3ae6_---Logging--.jpg.7df1cef013562468b48d988e25423bc1.jpg" rel=""><img alt="كــيــــف-تـسـتــخــــــدم-التسجيل-Logging-فـــي-بــايــثــــــــــــــون.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32148" data-unique="gek5il87i" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db03a3515589_---Logging--.thumb.jpg.ca7dc4eab03f8d22ed118ccd1d1e8d64.jpg"></a>
</p>

<h2 id="لماذا-نستخدم-وحدة-التسجيل">
	لماذا نستخدم وحدة التسجيل؟
</h2>

<p>
	تحافظ وحدة التسجيل على سجل الأحداث التي تحدث خلال عمل البرنامج، مما يجعل من رؤية مخرجات البرنامج المتعلقة بأحداثه أمراً متاحاً.<br>
	قد يكون استخدام الأمر<code>print</code> أمرا مألوفا لك خلال الشيفرة البرمجية لفحص الأحداث. يقدم الأمر <code>print</code> طريقة بدائية لإجراء عملية التنقيح الخاصة بحل المشاكل خلال عمل البرمجية. بينما يعد تضمين تعليمات <code>print</code> خلال الشيفرة البرمجية طريقة لمعرفة مسار تنفيذ البرنامج والحالة الحالية له، إلا أن هذه الطريقة اُثبت أنها أقل قدرة على الصيانة من استخدام وحدة التسجيل في بايثون، وذلك للأسباب التالية:
</p>

<ul>
<li>
		باستخدام تعليمات <code>print</code> يصبح من الصعب التفرقة بين مخرجات البرنامج الطبيعية وبين مخرجات التنقيح لتشابههما.
	</li>
	<li>
		عندما تنتشر تعليمات <code>print</code> خلال الشيفرة البرمجية، فإنه لا توجد طريقة سهلة لتعطيل التعليمات الخاصة بالتنقيح.
	</li>
	<li>
		من الصعب إزالة كافة تعليمات <code>print</code> عندما تنتهي من عملية التنقيح.
	</li>
	<li>
		لا توجد سجلات تشخيصية للأحداث.
	</li>
</ul>
<p>
	من الجيد البدء بالتعود على استخدام وحدة التسجيل المعيارية في بايثون خلال كتابة الشيفرة البرمجية بما أنها طريقة تتلاءم أكثر مع التطبيقات التي يكبر حجمها عن سكريبتات بايثون بسيطة، وكذلك بما أنها تقدم طريقة أفضل للتنقيح.
</p>

<h2 id="طباعة-رسائل-التنقيح-في-وحدة-التحكم">
	طباعة رسائل التنقيح في وحدة التحكم
</h2>

<p>
	إذا كنت متعودا على استخدام تعليمات <code>print</code> لرؤية ما يحدث في برنامجك خلال العمل، فمن المحتمل مثلا أنك تعودت على رؤية برنامج يُعرف صنفًاClass وينشئ منه عناصر كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> price</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">price </span><span class="pun">=</span><span class="pln"> price
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Pizza created: {} (${})"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">price</span><span class="pun">))</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> make</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Made {} {} pizza(s)"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> eat</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Ate {} pizza(s)"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

pizza_01 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="str">"artichoke"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">15</span><span class="pun">)</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">make</span><span class="pun">()</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span><span class="pln">

pizza_02 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="str">"margherita"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">make</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span></pre>

<p>
	توجد في الشيفرة السابقة الدالة<code>__init__</code> التي تستخدم لتعريف خصائص<code>name</code> و<code>price</code> للصنف<code>Pizza</code>. كما تحتوي على الدالتين <code>make</code> لصنع البيتزا، و<code>eat</code> لأكلها وتأخذان المعطى <code>quantity</code> ذا القيمة الافتراضية <code>1</code>.<br>
	لنشغل البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs avrasm"><span class="pun">&gt;&gt;</span><span class="pln"> python pizza</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<p>
	وسنحصل على المخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs bash"><span class="typ">Output</span><span class="pln">
</span><span class="typ">Pizza</span><span class="pln"> created</span><span class="pun">:</span><span class="pln"> artichoke </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$15</span></span><span class="pun">)</span><span class="pln">
</span><span class="typ">Made</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> artichoke pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Ate</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Pizza</span><span class="pln"> created</span><span class="pun">:</span><span class="pln"> margherita </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$12</span></span><span class="pun">)</span><span class="pln">
</span><span class="typ">Made</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> margherita pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Ate</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span></code></pre>

<p>
	تسمح لنا تعليمات <code>print</code> برؤية أن البرنامج يعمل، ولكننا نستطيع أن نستخدم وحدة التسجيل لذات الغرض بدلا من ذلك.<br>
	لنقم بإزالة تعليمات <code>print</code> من الشيفرة البرمجية، ونستورد الوحدة باستخدام الأمر <code>import logging</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs python"><span class="hljs-keyword"><span class="kwd">import</span></span><span class="pln"> logging


</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Pizza</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">__init__</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">value </span><span class="pun">=</span><span class="pln"> value
</span><span class="pun">...</span></code></pre>

<p>
	المستوى التلقائي للتسجيل في وحدة التسجيل هو مستوى التحذير (WARNING)، وهو مستوى فوق مستوى التنقيح (DEBUG). بما أننا سنستخدم الوحدة بغرض التنقيح في هذا المثال، سنحتاج الى تعديل إعدادات التسجيل لتصبح بمستوى التنقيح <code>logging.DEBUG</code> بحيث تعود معلومات التنقيح لنا من خلال لوحة التحكم. ونقوم بإعداد ذلك بإضافة ما يلي بعد تعليماتة الاستيراد:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs r"><span class="kwd">import</span><span class="pln"> logging

logging</span><span class="pun">.</span><span class="pln">basicConfig</span><span class="pun">(</span><span class="pln">level</span><span class="pun">=</span><span class="pln">logging</span><span class="pun">.</span><span class="pln">DEBUG</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">():</span><span class="pln">
</span><span class="hljs-keyword"><span class="pun">...</span></span></code></pre>

<p>
	هذا المستوى المتمثل ب<code>logging.DEBUG</code> يشير لقيد رقمي قيمته <code>10</code>.<br>
	سنستبدل الآن جميع تعليمات <code>print</code> بتعليمات <code>logging.debug()</code>، <code>(logging.DEBUG</code> ثابت بينما <code>logging.debug()</code> دالة). نستطيع أن نمرر لهذه الدالة نفس المدخلات النصية لتعليماتة print كما هو موجود بالأسفل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs python"><span class="hljs-keyword"><span class="kwd">import</span></span><span class="pln"> logging

logging</span><span class="pun">.</span><span class="pln">basicConfig</span><span class="pun">(</span><span class="pln">level</span><span class="pun">=</span><span class="pln">logging</span><span class="pun">.</span><span class="pln">DEBUG</span><span class="pun">)</span><span class="pln">


</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Pizza</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">__init__</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> price</span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">price </span><span class="pun">=</span><span class="pln"> price
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Pizza created: {} (${})"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">price</span><span class="pun">))</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">make</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Made {} {} pizza(s)"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">eat</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Ate {} pizza(s)"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

pizza_01 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"artichoke"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">15</span></span><span class="pun">)</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">make</span><span class="pun">()</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span><span class="pln">

pizza_02 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"margherita"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">12</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span></code></pre>

<p>
	لهذا الحد، نستطيع تشغيل البرنامج عبر تنفيذ الأمر <code>python pizza.py</code> وسنحصل على المخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs ruby"><span class="hljs-constant"><span class="typ">Output</span></span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> artichoke </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$15</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> artichoke pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> margherita </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$12</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> margherita pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span></code></pre>

<p>
	لاحظ أن مستوى التسجيل في المخرج السابق هو <code>DEBUG</code> بالإضافة لكلمة <code>root</code> والتي تشير لمستوى المُسجل (logger) الذي يتم استخدامه. يعني ما سبق أن وحدة التسجيل logging من الممكن أن يتم استخدامها لإعداد أكثر من مُسجل بأسماء مختلفة.<br>
	فمثلا، نستطيع إنشاء مسجلين باسمين مختلفين ومخرجات مختلفة كما هو موضح بالأسفل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs avrasm"><span class="pln">logger1 </span><span class="pun">=</span><span class="pln"> logging</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">getLogger</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">"module_1"</span></span><span class="pun">)</span><span class="pln">
logger2 </span><span class="pun">=</span><span class="pln"> logging</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">getLogger</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">"module_2"</span></span><span class="pun">)</span><span class="pln">

logger1</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">debug</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">"Module 1 debugger"</span></span><span class="pun">)</span><span class="pln">
logger2</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">debug</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">"Module 2 debugger"</span></span><span class="pun">)</span><span class="pln">

</span><span class="typ">Output</span><span class="pln">
</span><span class="hljs-label"><span class="pln">DEBUG</span><span class="pun">:</span></span><span class="pln">module_1</span><span class="pun">:</span><span class="typ">Module</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="kwd">debugger</span><span class="pln">
</span><span class="hljs-label"><span class="pln">DEBUG</span><span class="pun">:</span></span><span class="pln">module_2</span><span class="pun">:</span><span class="typ">Module</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> </span><span class="kwd">debugger</span></code></pre>

<p>
	بعد أن أصبحت لدينا المعرفة اللازمة لكيفية استخدام الوحدة logging لطباعة الرسائل على وحدة التحكم، دعونا نكمل شرح الوحدة ونتعرف على كيفية استخدام الوحدة في طباعة الرسائل إلى ملف خارجي.
</p>

<h2 id="التسجيل-في-ملف">
	التسجيل في ملف
</h2>

<p>
	الغرض الأساسي للتسجيل هو حفظ البيانات في ملف وليس إظهار معلومات التسجيل على وحدة التحكم. يتيح لك التسجيل في ملف حفظ بيانات التسجيل مع مرور الوقت واستخدامها في عملية التحليل والمتابعة ولتحديد ما تحتاجه من تغيير على الشيفرة البرمجية.<br>
	لجعل عملية التسجيل تحفظ التسجيلات في ملف، علينا أن نعدّل <code>logging.basicConfig()</code> بحيث تحتوي على معطى لاسم الملف (<code>filename</code>)، وليكن مثلا <code>test.log</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs python"><span class="hljs-keyword"><span class="kwd">import</span></span><span class="pln"> logging

logging</span><span class="pun">.</span><span class="pln">basicConfig</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">=</span><span class="hljs-string"><span class="str">"test.log"</span></span><span class="pun">,</span><span class="pln"> level</span><span class="pun">=</span><span class="pln">logging</span><span class="pun">.</span><span class="pln">DEBUG</span><span class="pun">)</span><span class="pln">


</span><span class="hljs-class"><span class="hljs-keyword"><span class="kwd">class</span></span><span class="pln"> </span><span class="hljs-title"><span class="typ">Pizza</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">__init__</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> price</span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">price </span><span class="pun">=</span><span class="pln"> price
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Pizza created: {} (${})"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">price</span><span class="pun">))</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">make</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Made {} {} pizza(s)"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

    </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">eat</span></span><span class="hljs-params"><span class="pun">(</span><span class="kwd">self</span><span class="pun">,</span><span class="pln"> quantity</span><span class="pun">=</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">:</span></span><span class="pln">
        logging</span><span class="pun">.</span><span class="pln">debug</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Ate {} pizza(s)"</span></span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">quantity</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">self</span><span class="pun">.</span><span class="pln">name</span><span class="pun">))</span><span class="pln">

pizza_01 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"artichoke"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">15</span></span><span class="pun">)</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">make</span><span class="pun">()</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span><span class="pln">

pizza_02 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"margherita"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">12</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">()</span></code></pre>

<p>
	الشيفرة البرمجية هنا هي نفسها الموجودة سابقا عدا أننا أضفنا اسم الملف الذي سنقوم بحفظ التسجيلات فيه. بمجرد تشغيلنا للشيفرة السابقة، سنجد في نفس المسار الملف <code>test.log</code>. لنفتحه باستخدام محرر النصوص nano (أو أي محرر نصوص من اختيارك):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs ruby"><span class="hljs-variable"><span class="pln">$ </span></span><span class="pln">nano test</span><span class="pun">.</span><span class="pln">log</span></code></pre>

<p>
	وسيكون محتويات الملف كالتالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs ruby"><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> artichoke </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$15</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> artichoke pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> margherita </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$12</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> margherita pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span></code></pre>

<p>
	المخرج السابق هو نفسه الذي حصلنا عليه في القسم السابق من المقال، غير أنه الآن في ملف باسم <code>test.log</code> وليس على الطرفية.<br>
	لنغلق المحرر، ونجر بعض التعديلات التالية على المتغيرين <code>pizza_01</code> و <code>pizza_02</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs r"><span class="hljs-keyword"><span class="pun">...</span></span><span class="pln">
</span><span class="hljs-comment"><span class="com"># Modify the parameters of the pizza_01 object</span></span><span class="pln">
pizza_01 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"Sicilian"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">18</span></span><span class="pun">)</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span><span class="pln">
pizza_01</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">(</span><span class="hljs-number"><span class="lit">4</span></span><span class="pun">)</span><span class="pln">

</span><span class="hljs-comment"><span class="com"># Modify the parameters of the pizza_02 object</span></span><span class="pln">
pizza_02 </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Pizza</span><span class="pun">(</span><span class="hljs-string"><span class="str">"quattro formaggi"</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">16</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">make</span><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span><span class="pln">
pizza_02</span><span class="pun">.</span><span class="pln">eat</span><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span></code></pre>

<p>
	عند تنفيذ الشيفرة بعد حفظ التعديلات، ستُضاف التسجيلات الجديدة للملف وسيكون محتواه كالتالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs ruby"><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> artichoke </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$15</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> artichoke pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> margherita </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$12</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> margherita pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> </span><span class="hljs-constant"><span class="typ">Sicilian</span></span><span class="pln"> </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$18</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln"> </span><span class="hljs-constant"><span class="typ">Sicilian</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-symbol"><span class="pln">created</span><span class="pun">:</span></span><span class="pln"> quattro formaggi </span><span class="pun">(</span><span class="hljs-variable"><span class="pln">$16</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> quattro formaggi pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-constant"><span class="pln">DEBUG</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-symbol"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> pizza</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span></code></pre>

<p>
	تُعد البيانات الموجودة في الملف مفيدة، ولكننا نستطيع جعلها أكثر إعلاماً بإضافة بعض الإعدادات. بشكل أساسي، فإننا نريد أن نجعل السجلات مفصلة أكثر بإضافة الوقت الذي أنشئ السجل فيه.<br>
	نستطيع إضافة المعطى المسمى <code>format</code> ونضيف له النص <code>%(asctime)s</code> الذي يشير للوقت، كذلك، للإبقاء على ظهور مستوى التسجيل في السجلات، لابد أن نضيف النص <code>%(levelname)s</code> بالإضافة للسجل نفسه <code>%(message)s</code>.<br>
	لابد من الفصل بين كل خيار في المعطى <code>format</code> بالعلامة <code>:</code> كما هو موضح بالأسفل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs lasso"><span class="hljs-keyword"><span class="kwd">import</span></span><span class="pln"> logging

logging</span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">basicConfig</span><span class="pun">(</span><span class="pln">
    filename</span><span class="hljs-subst"><span class="pun">=</span></span><span class="hljs-string"><span class="str">"test.log"</span></span><span class="pun">,</span><span class="pln">
    level</span><span class="hljs-subst"><span class="pun">=</span></span><span class="pln">logging</span><span class="hljs-built_in"><span class="pun">.</span></span><span class="pln">DEBUG</span><span class="pun">,</span><span class="pln">
    format</span><span class="hljs-subst"><span class="pun">=</span></span><span class="hljs-string"><span class="str">"%(asctime)s:%(levelname)s:%(message)s"</span></span><span class="pln">
    </span><span class="pun">)</span><span class="pln">
</span><span class="hljs-attribute"><span class="pun">...</span></span><span class="hljs-attribute"><span class="pun">...</span></span><span class="hljs-built_in"><span class="pun">.</span></span></code></pre>

<p>
	عندما ننفذ الشيفرة السابقة، سنحصل على تسجيلات جديدة في ملف <code>test.log</code> تتضمن الوقت الذي أنشئ فيه التسجيل بالإضافة لمستوى التسجيل ورسالة التسجيل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2879_7" style="">
<code class="hljs css"><span class="hljs-tag"><span class="typ">Output</span></span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">created</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-tag"><span class="typ">Sicilian</span></span><span class="pln"> </span><span class="pun">(</span><span class="pln">$18</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="hljs-tag"><span class="typ">Sicilian</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">created</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">quattro</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">formaggi</span></span><span class="pln"> </span><span class="pun">(</span><span class="pln">$16</span><span class="pun">)</span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">quattro</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">formaggi</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="hljs-tag"><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">root</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">created</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-tag"><span class="typ">Sicilian</span></span><span class="pln"> </span><span class="pun">(</span><span class="pln">$18</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="hljs-tag"><span class="typ">Sicilian</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Pizza</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">created</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">quattro</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">formaggi</span></span><span class="pln"> </span><span class="pun">(</span><span class="pln">$16</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Made</span></span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">quattro</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">formaggi</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span><span class="pln">
</span><span class="lit">2017</span><span class="hljs-tag"><span class="pun">-</span><span class="lit">05</span><span class="pun">-</span><span class="lit">01</span></span><span class="pln"> </span><span class="lit">16</span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">28</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="lit">54</span></span><span class="pun">,</span><span class="lit">593</span><span class="hljs-pseudo"><span class="pun">:</span><span class="pln">DEBUG</span></span><span class="hljs-pseudo"><span class="pun">:</span><span class="typ">Ate</span></span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pizza</span></span><span class="pun">(</span><span class="hljs-tag"><span class="pln">s</span></span><span class="pun">)</span></code></pre>

<p>
	تبعا لاحتياجاتك، من الممكن أن تضيف إعدادات أخرى للمسجل بحيث تجعل التسجيلات التي يتم حفظها في الملف مرتبطة بك نوعا ما.<br>
	التنقيح بواسطة التسجيل في ملفات خارجية يتيح لك فهما شاملا لبرنامج بايثون مع مرور الوقت، معطيا الفرصة لحل المشاكل التي تظهر وتغيير ما تحتاج تغييره في الشيفرة البرمجية استنادا لما لديك من بيانات تسجيلات تاريخية وأحداث وحركات تمت خلال عمل البرنامج.
</p>

<h2 id="جدول-بمستويات-التسجيل">
	جدول بمستويات التسجيل
</h2>

<p>
	تستطيع نسب مستوى الأهمية للحدث الذي يتم تسجيله بواسطة المُسجل وذلك بإضافة مستوى الخطورة (Severity Level). مستويات الخطورة موضحة في الجدول الذي بالأسفل.<br>
	تتمثل مستويات التسجيل تقنيا بأرقام (ثوابت)، بفرق قيمة بين كل مستوى ب 10، تبدأ من المستوى<code>NOTEST</code> ذي القيمة 0.<br>
	تستطيع أن تُعرف مستويات خاصة بك مرتبطة بالمستويات المعرفة مسبقا. إذا عَرَّفْتَ مستوى بنفس القيمة الرقمية، فإنك تستبدل اسم المستوى المرتبط بتلك القيمة.
</p>

<center>
	<tbodey></tbodey><table border="1"><tbody>
<tr>
<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					المستوى
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					القيمة الرقمية
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					الدالة
				</td>
				<td style="background-color: rgb(236, 240, 241); padding: 5px 10px; text-align: center;">
					الاستخدام
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					CRITICAL
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					50
				</td>
				<td style="padding: 5px 10px; text-align: center; dir: ltr;">
					()logging.critical
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					اظهار الأخطاء الخطيرة، البرنامج قد لا يستمر بالعمل
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					ERROR
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					40
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					()logging.error
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					إظهار مشكلة خطيرة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					WARNING
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					30
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					()logging.warning
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					الإشارة لحدث غير متوقع حصل أو قد يصحل
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					INFO
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					20
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					()logging.info
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					الإشارة أن الحدث حصل كما هو متوقع
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					DEBUG
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					10
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					()logging.debug
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					فحص المشاكل، وإظهار معلومات تفصيلية
				</td>
			</tr>
</tbody></table>
</center>

<h2>
	خاتمة
</h2>

<p>
	الوحدة logging هي وحدة ضمن التوزيعة المعيارية لبايثون، وتقدم حلا لمتابعة الأحداث التي تحدث خلال عمل البرمجية مع إمكانية تسجيل هذه الأحداث في ملفات خارجية أو إظهارها على الطرفية. وهذا يتيح لك فهما شاملا لبرنامج بايثون مع مرور الوقت.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة – بتصرّف – للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3" rel="external nofollow" style="background-color: rgb(255, 255, 255);">How To Use Logging in Python 3</a> لصاحبته Lisa Tagliaferri.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B1%D8%AD%D9%8A%D9%84-%D8%B4%D9%8A%D9%81%D8%B1%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-2-%D8%A5%D9%84%D9%89-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r759" rel="">كيفية ترحيل شيفرة بايثون 2 إلى بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D9%86-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A-r758" rel="">كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">546</guid><pubDate>Sat, 23 Nov 2019 14:03:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x646;&#x642;&#x64A;&#x62D; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x645;&#x646; &#x633;&#x637;&#x631; &#x627;&#x644;&#x623;&#x648;&#x627;&#x645;&#x631; &#x627;&#x644;&#x62A;&#x641;&#x627;&#x639;&#x644;&#x64A;</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D9%86-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A-r758/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db03c033898e_-------.jpg.e3ef3dc21d5a277cf68d09b1d217044e.jpg" /></p>

<p>
	التنقيح (debugging) هو جزء من عملية تطوير البرمجيات، ويروم البحث عن الأخطاء والمشاكل في الشيفرة، والتي تحول دون تنفيذ البرنامج تنفيذًا صحيحًا.
</p>

<p>
	الوحدة <code>code</code> هي إحدى الأدوات المفيدة التي يمكن استخدامها لمحاكاة المترجم (interpreter) التفاعلي، إذ توفر هذه الوحدة فرصةً لتجربة الشيفرة التي تكتبها.
</p>

<p>
	قبل أن تكمل هذا المقال، أنصحك بمطالعة المقال السابق عن منقح بايثون: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D9%82%D8%AD-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r542/" rel="">كيف تستخدم منقح بايثون</a>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32149" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db03c0496d36_-------.jpg.f09e8ba4ecf59b0e35e60f561537b800.jpg" rel=""><img alt="كـيـفـيــة-تـنـقيـــح-شيفـرات-بايثــون-من-سطر-الأوامر-الـتـفـــــــــــــاعــلـــي.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32149" data-unique="zytqjhv1l" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db03c04ac7a4_-------.thumb.jpg.0e9390031ff9df9d00c8e5af9eca2477.jpg"></a>
</p>

<h2>
	فهم الوحدة <code>code</code>
</h2>

<p>
	بدلاً من تفحص الشيفرة باستخدام منقح، يمكنك <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r744/" rel="">إضافة الوحدة</a> <code>code</code> لوضع نقاط لإيقاف تنفيذ البرنامج، والدخول في الوضع التفاعلي لتفحص ومتابعة كيفية عمل الشيفرة. الوحدة <code>code</code> هي جزء من مكتبة بايثون القياسية.
</p>

<p>
	هذه الوحدة مفيدةٌ لأنَّها ستمكنك من استخدام مترجم دون التضحية بالتعقيد والاستدامة التي توفرها ملفات البرمجة. فيمكنك عبر استخدام الوحدة <code>code</code> تجنب استخدام الدالة <code>print()‎‎‎</code> في شيفرتك لأجل التنقيح، لأنها طريقة غير عملية.
</p>

<p>
	لاستخدام هذه الوحدة في تنقيح الأخطاء، يمكنك استخدام الدالة interact()<code>‎</code> الخاصة بالوحدة <code>code</code>، والتي توقف تنفيذ البرنامج عند استدعائها، وتوفر لك <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B3%D8%B7%D8%B1-%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A-r716/" rel="">سطر أوامر تفاعلي</a> حتى تتمكن من فحص الوضع الحالي لبرنامجك.
</p>

<p>
	تُكتَب هذه الدالة هكذا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8300_7" style="">
<span class="pln">code</span><span class="pun">.</span><span class="pln">interact</span><span class="pun">(</span><span class="pln">banner</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> readfunc</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> local</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">,</span><span class="pln"> exitmsg</span><span class="pun">=</span><span class="kwd">None</span><span class="pun">)</span></pre>

<p>
	تُنفِّذ هذه الدالة <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop" rel="external nofollow">حلقة اقرأ-قيِّم-اطبع</a> (تختصر إلى REPL، أي Read–eval–print loop، وتنشئ نسخة من الصنف <code>InteractiveConsole</code>، والذي يحاكي سلوك مترجم بايثون التفاعلي.
</p>

<p>
	هذه هي المعاملات الاختيارية:
</p>

<ul>
<li>
		<code>banner</code>: يمكن أن تعطيه <a href="https://wiki.hsoub.com/Python/str" rel="external">سلسلة نصية</a> لتعيين موضع إطلاق المترجم.
	</li>
	<li>
		<code>readfunc</code>: يمكن استخدامه مثل التابع <a href="https://docs.python.org/3/library/code.html#code.InteractiveConsole.raw_input" rel="external nofollow"><code>InteractiveConsole.raw_input‎()‎</code></a>.
	</li>
	<li>
		<code>local</code>: سيعينّ فضاء الأسماء (namespace) الافتراضي لحلقة المترجم (interpreter loop).
	</li>
	<li>
		<code>exitmsg</code>: يمكن إعطاؤه سلسلة نصية لتعيين موضع توقف المترجم.
	</li>
</ul>
<p>
	مثلًا، يمكن استخدام المعامل <code>local</code> بهذا الشكل:
</p>

<ul>
<li>
		<code>local=locals()‎</code> لفضاء أسماء محلي.
	</li>
	<li>
		<code>local=globals()‎</code> لفضاء أسماء عام.
	</li>
	<li>
		<code>local=dict(globals(), **locals())‎</code> لاستخدام كل من فضاء الأسماء العام، وفضاء الأسماء المحلي الحالي.
	</li>
</ul>
<p>
	المعامل <code>exitmsg</code> جديد، ولم يظهر حتى إصدار بايثون 3.6، لذلك إن كنت تستخدم إصدارًا أقدم، فحدّثه، أو لا تستخدم المعامل <code>exitmsg</code>.
</p>

<p>
	ضع الدالة interact()‎‎ حيث تريد إطلاق المترجم التفاعلي في الشيفرة.
</p>

<h2>
	كيفية استخدام الوحدة <code>code</code>
</h2>

<p>
	لتوضيح كيفية استخدام الوحدة <code>code</code>، سنكتب بُريمجًا عن الحسابات المصرفية يسمى <code>balances.py</code>. سنعيّن المعامل المحلي عند القيمة <code>locals()‎‎‎</code> لجعل فضاء الأسماء محليًّا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8300_9" style="">
<span class="com"># `code`  استيراد الوحدة </span><span class="pln">
</span><span class="kwd">import</span><span class="pln"> code

bal_a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2324</span><span class="pln">
bal_b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
bal_c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">409</span><span class="pln">
bal_d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2</span><span class="pln">

account_balances </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">bal_a</span><span class="pun">,</span><span class="pln"> bal_b</span><span class="pun">,</span><span class="pln"> bal_c</span><span class="pun">,</span><span class="pln"> bal_d</span><span class="pun">]</span><span class="pln">


</span><span class="kwd">def</span><span class="pln"> display_bal</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> balance </span><span class="kwd">in</span><span class="pln"> account_balances</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> balance </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Account balance of {} is below 0; add funds now."</span><span class="pln">
                  </span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">balance</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">elif</span><span class="pln"> balance </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Account balance of {} is equal to 0; add funds soon."</span><span class="pln">
                  </span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">balance</span><span class="pun">))</span><span class="pln">

        </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Account balance of {} is above 0."</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">balance</span><span class="pun">))</span><span class="pln">

</span><span class="com"># لبدء المترجم بفضاء أسماء محلي interact()‎‎‎ استخدام</span><span class="pln">
code</span><span class="pun">.</span><span class="pln">interact</span><span class="pun">(</span><span class="pln">local</span><span class="pun">=</span><span class="pln">locals</span><span class="pun">())</span><span class="pln">

display_bal</span><span class="pun">()</span></pre>

<p>
	لقد استدعينا الدالة <code>code.interact()‎‎‎</code> مع المعامل local=locals()<code>‎</code> لاستخدام فضاء الأسماء المحلي كقيمة افتراضية داخل حلقة المترجم.
</p>

<p>
	لنُنفِّذ البرنامج أعلاه باستخدام الأمر <code>python3</code> إذا لم نكن تعمل في بيئة افتراضية، أو الأمر <code>python</code> خلاف ذلك:
</p>

<pre class="ipsCode">
python balances.py
</pre>

<p>
	بمجرد تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
&gt;&gt;&gt;
</pre>

<p>
	سيتم وضع المؤشر في نهاية السطر <code>‎&gt;&gt;&gt;‎</code>، كما لو أنك في سطر الأوامر التفاعلي.
</p>

<p>
	من هنا، يمكنك استدعاء الدالة <code>print()‎</code> لطباعة المتغيرات والدوال وغير ذلك:
</p>

<pre class="ipsCode">
&gt;&gt;&gt; print(bal_c)
409
&gt;&gt;&gt; print(account_balances)
[2324, 0, 409, -2]
&gt;&gt;&gt; print(display_bal())
Account balance of 2324 is 0 or above.
Account balance of 0 is equal to 0, add funds soon.
Account balance of 409 is 0 or above.
Account balance of -2 is below 0, add funds now.
None
&gt;&gt;&gt; print(display_bal)
&lt;function display_bal at 0x104b80f28&gt;
&gt;&gt;&gt;
</pre>

<p>
	نرى أنه باستخدام فضاء الأسماء المحلي، يمكننا طباعة المتغيرات، واستدعاء الدالة. يُظهر الاستدعاء الأخير للدالة <code>print()‎</code> أنّ الدالة <code>display_bal</code> موجودة في ذاكرة الحاسوب.
</p>

<p>
	بعد أن تنتهي من العمل على المترجم، يمكنك الضغط على <code>CTRL + D</code> في الأنظمة المستندة إلى *نكس، أو <code>CTRL + Z</code> في أنظمة ويندوز لمغادرة سطر الأوامر ومتابعة تنفيذ البرنامج.
</p>

<p>
	إذا أردت الخروج من سطر الأوامر دون تنفيذ الجزء المتبقي من البرنامج، فاكتب <code>quit()‎‎‎</code>، وسيتوقف البرنامج.
</p>

<p>
	في المثال التالي، سنستخدم المُعاملين <code>banner</code> و <code>exitmsg</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8300_12" style="">
<span class="com"># لبدء المترجم interact()‎‎‎ استخدم الدالة</span><span class="pln">
code</span><span class="pun">.</span><span class="pln">interact</span><span class="pun">(</span><span class="pln">banner</span><span class="pun">=</span><span class="str">"Start"</span><span class="pun">,</span><span class="pln"> local</span><span class="pun">=</span><span class="pln">locals</span><span class="pun">(),</span><span class="pln"> exitmsg</span><span class="pun">=</span><span class="str">"End"</span><span class="pun">)</span><span class="pln">

display_bal</span><span class="pun">()</span></pre>

<p>
	عند تنفيذ البرنامج، ستحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Start
&gt;&gt;&gt;
</pre>

<p>
	يتيح لك استخدام المعامل <code>banner</code> تعيين عدة نقاط داخل شيفرتك، مع القدرة على تحديدها. على سبيل المثال، يمكن أن يكون لديك معامل <code>banner</code> يطبع السلسلة النصية <code>"In for-loop"</code> مع معامل <code>exmsg</code> يطبع <code>"Out of for-loop"</code>، وذلك حتى تعرف مكانك بالضبط في الشيفرة.
</p>

<p>
	من هنا، يمكننا استخدام المترجم كالمعتاد. بعد كتابة <code>CTRL + D</code> للخروج من المترجم، ستحصل على رسالة الخروج، وسيتم تنفيذ الدالة:
</p>

<pre class="ipsCode">
End
Account balance of 2324 is 0 or above.
Account balance of 0 is equal to 0, add funds soon.
Account balance of 409 is 0 or above.
Account balance of -2 is below 0, add funds now.
</pre>

<p>
	سيتم تنفيذ البرنامج بالكامل بعد الجلسة التفاعلية.
</p>

<p>
	بمجرد الانتهاء من استخدام الوحدة <code>code</code> لتنقيح الشيفرة، يجب عليك إزالة دوال الوحدة <code>code</code> وعبارة الاستيراد حتى يُنفَّذ البرنامج مثل المعتاد.
</p>

<h2>
	خلاصة
</h2>

<p>
	تُستخدَم الوحدة <code>code</code> لإطلاق سطر الأوامر التفاعلي لتفحُّص الشيفرة خطوةً بخطوة بقصد فهم سلوكها، وتعديل الشيفرة إن لزم الأمر. لقراءة المزيد حول هذا الموضوع، يمكنك مطالعة <a href="https://docs.python.org/3/library/code.html" rel="external nofollow">التوثيق الرسمي للوحدة code</a>.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-debug-python-with-an-interactive-console" rel="external nofollow">How To Debug Python with an Interactive Console</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%AA%D8%B3%D8%AC%D9%8A%D9%84-logging-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r546/" rel="">كيف تستخدم التسجيل Logging في بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D9%82%D8%AD-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r542/" rel="">كيف تستخدم منقح بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">758</guid><pubDate>Wed, 20 Nov 2019 14:07:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x645;&#x646;&#x642;&#x62D; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D9%82%D8%AD-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r542/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db0393587fe2_----3.jpg.b238972ed50a5fc8b5a767fa3d2dac2c.jpg" /></p>

<p>
	نعني بالتنقيح Debugging في مجال تطوير البرمجيات، عملية إيجاد وحل المشاكل التي تمنع البرمجية من العمل على نحو سليم.<br>
	يُقدم مُنقح <a href="https://academy.hsoub.com/programming/python/" rel="">بايثون</a> بيئة تنقيح لبرامج بايثون، ويدعم إعداد نقاط الفصل (Breakpoints)، التدرج خلال الشيفرة البرمجية (Stepping) سطرًا بسطر والعديد من المزايا.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32147" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db03939d329e_----3.jpg.04b3d8f8756aa6a122ac346225bab053.jpg" rel=""><img alt="كيـف-تستخدم-منقح-بايثون-3.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32147" data-unique="6yh8j1rgp" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db03939e8432_----3.thumb.jpg.5c27b059db3f6f44a340dcec87503c08.jpg"></a>
</p>

<h2 id="التفاعل-مع-منقح-بايثون">
	التفاعل مع مُنقح بايثون
</h2>

<p>
	يأتي مُنقح بايثون مرفقًا مع توزيعة بايثون المعيارية على هيئة وحدة بايثون باسم pdb، ومن الممكن أن يُستخدم في الشيفرة البرمجية كعنصر من الصنف Pdb، ولمزيد من المعلومات تستطيع قراءة التوثيق الرسمي للوحدة pdb.<br>
	سوف نبدأ العمل باستخدام برنامج صغير يحتوي على متغيرين ودالة تحتوي على حلقة تكرار بالإضافة لسطر استدعاء الدالة من خلال التركيبة <code>if __name__ == '__main__':</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<span class="pln">num_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span class="lit">600</span><span class="pun">,</span><span class="pln"> </span><span class="lit">700</span><span class="pun">]</span><span class="pln">
alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'x'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'y'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'z'</span><span class="pun">]</span><span class="pln">


</span><span class="kwd">def</span><span class="pln"> nested_loop</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> number </span><span class="kwd">in</span><span class="pln"> num_list</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> alpha_list</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">'__main__'</span><span class="pun">:</span><span class="pln">
    nested_loop</span><span class="pun">()</span></pre>

<p>
	نستطيع الآن تشغيل البرنامج السابق من خلال مُنقح بايثون في الطرفية باستخدام الأمر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pln">python </span><span class="pun">-</span><span class="pln">m pdb looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<p>
	يستورد الخيار <code>m-</code> في الأمر أي وحدة بايثون وتشغيلها كبرنامج. في هذه الحالة نقوم باستيراد الوحدة pdb وتمريرها كما هو مكتوب في الأمر.<br>
	عند تنفيذ الأمر السابق سوف تحصل على المُخرج التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> num_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-number"><span class="lit">500</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">600</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">700</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span></code></pre>

<p>
	يحتوي السطر الأول في المُخرج على اسم الملف الحالي الذي نقوم بتنقيحه – بالمسار الكامل -، ومن ثم يوجد رقم سطر الشيفرة التي يقف عليها مؤشر المُنقح (في هذه الحالة 1، ولكن في حالة وجود تعليق أو سطر غير تنفيذي سيكون الرقم أكبر من ذلك). السطر الثاني عبارة عن سطر الشيفرة الذي يتم تنفيذه.<br>
	يُقدم مُنقح بايثون وحدة تحكم (Console) تفاعلية لإجراء عملية التنقيح وتستطيع استخدام أمر المساعدة<code>help</code> للتعرف على الأوامر المتاحة في المُنقح، وأيضا من الممكن أن تستخدم صيغة المساعدة مع الأمر<code>help command</code> للتعرف أكثر على تفاصيل أمر معين.<br>
	سيعيد المُنقح عمله مرة أخرى تلقائيا عندما يصل لنهاية البرنامج. إذا أردت الخروج من وحدة تحكم المُنقح، أدخل الأمر<code>quit</code> أو<code>exit</code>. إذا أردت إعادة تشغيل عملية التنقيح مرة أخرى وفي أي مكان من البرنامج، أدخل الأمر<code>run</code>.
</p>

<h2 id="استخدام-المنقح-للتدرج-خلال-البرنامج">
	استخدام المُنقح للتدرج خلال البرنامج
</h2>

<p>
	عند العمل على تنقيح البرامج باستخدام مُنقح بايثون، فإنك غالبا ستستخدم أوامر <code>step</code>، <code>list</code> و<code>next</code> للمرور على الشيفرة البرمجية. خلال هذا الجزء من المقال سنتناول هذه الأوامر.<br>
	من خلال نافذة الأوامر، نستطيع إدخال الأمر<code>list</code> للحصول على السياق المحيط للسطر الحالي.<br>
	فمثلا، من السطر الأول في البرنامج <code>looping.py</code> الذي عرضناه في الأعلى <code>— num_list = [500, 600, 700] —</code> سيكون تنفيذ الأمر<code>list</code> معه بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> list
  </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-function"><span class="pln">  </span><span class="pun">-&gt;</span></span><span class="pln"> num_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-number"><span class="lit">500</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">600</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">700</span></span><span class="pun">]</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">     alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'x'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'z'</span></span><span class="pun">]</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">     </span><span class="kwd">def</span><span class="pln"> nested_loop</span><span class="pun">():</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">         </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> number </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">num_list</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">             </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">8</span></span><span class="pln">             </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">alpha_list</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">9</span></span><span class="pln">                 </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
 </span><span class="hljs-number"><span class="lit">10</span></span><span class="pln">     
 </span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">     </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">'__main__'</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	السطر الحالي يشار إليه بالعلامة <code>-&gt;</code> في بدايته وهو في حالتنا هذه السطر الأول من البرنامج.<br>
	بحكم أن البرنامج الذي نستخدمه هنا صغير نسبيا، فإننا تقريبا نحصل على كافة الأسطر في البرنامج عند استخدامالأمر <code>list</code>. بدون تزويد معطيات مع الأمر <code>list</code>، نحصل من استخدام الأمر على 11 سطراً من الشيفرة البرمجية محيطة بالسطر الحالي في المُنقح، ولكننا نستطيع تحديد الأسطر التي نريد عرضها بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs python"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> list </span><span class="hljs-number"><span class="lit">3</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
  </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">     </span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
  </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">         </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> number </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> num_list</span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">             </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	في الأمر السابق قمنا بعرض الأسطر 3-7 باستخدام الأمر <code>list 3,7</code>.<br>
	للمرور خلال البرنامج سطرا بسطر، نستخدم الأمر<code>step</code> أو <code>next</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'x'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'z'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span></code></pre>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">next</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'x'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'z'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	الفرق بين الأمر<code>step</code> والأمر<code>next</code> أن الأمر<code>step</code> سوف يتوقف مع استدعاء دالة، بينما الأمر <code>next</code> يُنفذ الدالة عند استدعائها. يتجلى الفرق بين الأمرين عند التعامل مع الدوال.<br>
	في مثالنا المستخدم، سيقوم الأمر<code>step</code> بالتعداد خلال حلقات التكرار بمجرد الدخول في استدعاء الدالة <code>nested_loop()</code> بحيث يظهر تماما ما تقوم به حلقة التكرار من طباعة رقم ومن ثم الدخول في حلقة تكرار طباعة الحروف المقترنة بالرقم ومن ثم العودة لطباعة رقم جديد وهكذا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> nested_loop</span><span class="pun">():</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">11</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">'__main__'</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">12</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> nested_loop</span><span class="pun">()</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">--</span><span class="typ">Call</span><span class="pun">--</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> nested_loop</span><span class="pun">():</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> number </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">num_list</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">7</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="hljs-number"><span class="lit">500</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">alpha_list</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">9</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
x
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">alpha_list</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">9</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> step
y
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">alpha_list</span></span><span class="pun">:</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span></code></pre>

<p>
	الأمر<code>next</code>، بدلا من ذلك، سيستدعي الدالة دون الدخول في خطوات تنفيذها خطوة-بخطوة.<br>
	لنخرج من المُنقح ونعد تشغيله مرة أخرى:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pln">python </span><span class="pun">-</span><span class="pln">m pdb looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<p>
	الآن لنستخدم الأمر<code>next</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs haskell"><span class="pun">(</span><span class="hljs-type"><span class="typ">Pdb</span></span><span class="pun">)</span><span class="pln"> </span><span class="kwd">next</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/</span><span class="hljs-type"><span class="str">Users</span></span><span class="str">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)&lt;</span><span class="hljs-module"><span class="hljs-keyword"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-container"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> nested_loop</span><span class="hljs-container"><span class="pun">()</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-container"><span class="pun">(</span><span class="hljs-type"><span class="typ">Pdb</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="kwd">next</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-container"><span class="pun">(</span><span class="lit">11</span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-keyword"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-container"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">'__main__'</span><span class="pun">:</span><span class="pln">
</span><span class="hljs-container"><span class="pun">(</span><span class="hljs-type"><span class="typ">Pdb</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="kwd">next</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-container"><span class="pun">(</span><span class="lit">12</span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-keyword"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-container"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> nested_loop</span><span class="hljs-container"><span class="pun">()</span></span><span class="pln">
</span><span class="hljs-container"><span class="pun">(</span><span class="hljs-type"><span class="typ">Pdb</span></span><span class="pun">)</span></span><span class="pln"> </span><span class="kwd">next</span><span class="pln">
</span><span class="lit">500</span><span class="pln">
x
y
z
</span><span class="lit">600</span><span class="pln">
x
y
z
</span><span class="lit">700</span><span class="pln">
x
y
z
</span><span class="hljs-comment"><span class="pun">--</span><span class="typ">Return</span><span class="pun">--</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-container"><span class="pun">(</span><span class="lit">12</span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-keyword"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-container"><span class="pun">()</span></span><span class="pun">-&gt;</span><span class="kwd">None</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> nested_loop</span><span class="hljs-container"><span class="pun">()</span></span><span class="pln">
</span><span class="hljs-container"><span class="pun">(</span><span class="hljs-type"><span class="typ">Pdb</span></span><span class="pun">)</span></span><span class="pln">  </span></span></code></pre>

<p>
	أثناء عملك في تنقيح الشيفرة البرمجية الخاصة بك، قد تريد فحص قيمة متغير، وهو ما تستطيع تنفيذه باستخدام الأمر<code>pp</code> والذي يقوم بطباعة القيمة باستخدام وحدة <code>pprint</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs css"><span class="pun">(</span><span class="hljs-tag"><span class="typ">Pdb</span></span><span class="pun">)</span><span class="pln"> </span><span class="hljs-tag"><span class="pln">pp</span></span><span class="pln"> </span><span class="hljs-tag"><span class="pln">num_list</span></span><span class="pln">
</span><span class="hljs-attr_selector"><span class="pun">[</span><span class="lit">500</span><span class="pun">,</span><span class="pln"> </span><span class="lit">600</span><span class="pun">,</span><span class="pln"> </span><span class="lit">700</span><span class="pun">]</span></span><span class="pln">
</span><span class="pun">(</span><span class="hljs-tag"><span class="typ">Pdb</span></span><span class="pun">)</span></code></pre>

<p>
	أغلب الأوامر في مُنقح pdb لديها اختصارات، فمثلا، الأمر<code>step</code> له اختصار هو<code>s</code> ولأمر<code>next</code> يوجد<code>n</code>.<br>
	يسرد أمر المساعدة <code>help</code> كافة الاختصارات لكل الأوامر. بالإضافة لذلك، تستطيع استدعاء الأمر الأخير بالضغط على زر الإدخال (Enter) في لوحة المفاتيح.
</p>

<h2 id="نقاط-الفصل">
	نقاط الفصل
</h2>

<p>
	من المؤكد أنك ستعمل على برامج أكبر من المثال المستخدم هنا، لذلك، غالبا ستحتاج أن تتوقف عند وظيفة معينة أو سطر محدد أثناء تنقيحك للشيفرة البرمجية، وذلك بدلا من المرور على كافة أسطر البرنامج. ستتمكن باستخدام الأمر<code>break</code> لإعداد نقاط الفصل من تشغيل البرنامج حتى نقطة معينة مسبقا فيه تـسمى نقطة فصل Break point.<br>
	عندما تضيف نقطة فصل، سيعطيها المُنقح رقما خاصا بها. الأرقام المُعطاة لنقاط الفصل تكون أرقاماً متعاقبة وتبدأ من 1، وتستطيع الإشارة لنقاط الفصل باستخدام أرقامها أثناء عملك في المُنقح.
</p>

<p>
	تُضاف نقاط الفصل في أسطر معينة باستخدام الصيغة التالية <code>&lt;program_file&gt;:&lt;line_number&gt;</code> كما هو موضح بالأسفل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">break</span></span><span class="pln"> looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span></code></pre>

<p>
	اكتب الأمر<code>clear</code> ومن ثم <code>y</code> لإزالة نقاط الفصل الحالية. تستطيع بعد ذلك إضافة نقطة فصل في مكان تعريف الدالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">break</span></span><span class="pln"> looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">nested</span></span><span class="pln">_loop
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	تستطيع كذلك إضافة شرط لنقطة الفصل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">break</span></span><span class="pln"> looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pun">,</span><span class="pln"> number </span><span class="pun">&gt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">500</span></span><span class="pln">
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln">  </span></code></pre>

<p>
	لو أدخلنا الآن الأمر<code>continue</code>، فإن البرنامج سيتوقف عندما تكون قيمة المتغير<code>number</code> أكبر من 500.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="hljs-number"><span class="lit">500</span></span><span class="pln">
x
y
z
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">7</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	للحصول على قائمة بنقاط الفصل المُعدة حاليا للعمل، استخدم الأمر<code>break</code> فقط (دون معطيات) وسوف تحصل على معلومات نقاط الفصل التي قمت بإعدادها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs livecodeserver"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pln">
</span><span class="typ">Num</span><span class="pln"> </span><span class="typ">Type</span><span class="pln">         </span><span class="typ">Disp</span><span class="pln"> </span><span class="typ">Enb</span><span class="pln">   </span><span class="typ">Where</span><span class="pln">
</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">   </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln">   keep yes   </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
    stop only </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">500</span></span><span class="pln">
    </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln"> already hit </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> times
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	نستطيع تعطيل نقطة فصل من البرنامج باستخدام الأمر<code>disable</code> ومن ثم ندخل رقم نقطة الفصل. في هذه الجلسة (المثال المشروح) قمنا بإضافة نقطة فصل أخرى ومن ثم عطلنا النقطة الأولى:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs livecodeserver"><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pln"> looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> disable </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Disabled</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pln">
</span><span class="typ">Num</span><span class="pln"> </span><span class="typ">Type</span><span class="pln">         </span><span class="typ">Disp</span><span class="pln"> </span><span class="typ">Enb</span><span class="pln">   </span><span class="typ">Where</span><span class="pln">
</span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">   </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln">   keep </span><span class="kwd">no</span><span class="pln">    </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
    stop only </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">500</span></span><span class="pln">
    </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln"> already hit </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> times
</span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">   </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln">   keep yes   </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	لتفعيل نقطة الفصل نستخدم الأمر<code>enable</code>، ولإزالة نقطة الفصل نستخدم الأمر<code>clear</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs livecodeserver"><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> enable </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Enabled</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">clear</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">
</span><span class="typ">Deleted</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">breakpoint</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">at</span></span><span class="pln"> </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">looping</span><span class="pun">.</span><span class="pln">py</span><span class="pun">:</span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span></code></pre>

<p>
	تقدّم لك نقاط الفصل في pdb قدرة كبيرة في التحكم، فمثلا، من الإضافات أنك تستطيع تجاهل نقطة الفصل خلال الدورة الحالية من البرنامج باستخدام الأمر<code>ignore</code> أو تنفيذ حدث معين عند الوصول لنقطة فصل معينة باستخدام الأمر<code>command</code>.<br>
	تستطيع كذلك إضافة نقاط فصل مؤقتة بواسطة الأمر<code>tbreak</code>، بحيث يقوم المُنقح بحذفها تلقائيا عند الوصول إليها وتنفيذها للمرة الأولى (لإضافة نقطة فصل مؤقتة في السطر رقم 3، ندخل الأمر<code>tbreak 3</code> ).
</p>

<h2 id="تضمين-المنقح-في-الشيفرة-البرمجية">
	تضمين المُنقح في الشيفرة البرمجية
</h2>

<p>
	تستطيع تشغيل جلسة تنقيح في الشيفرة البرمجية مباشرة وذلك باستيراد الوحدة pdb إضافة الدالة <code>pdb.set_trace</code> قبل السطر الذي تريد أن تبدأ الجلسة من عنده.<br>
	في مثالنا المستخدم خلال هذا المقال، سوف نقوم باستيراد الوحدة pdb واضافة الدالة المذكورة قبل البدء بحلقة التكرار الداخلية في الدالة <code>nested_loop</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs python"><span class="hljs-comment"><span class="com"># Import pdb module</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="kwd">import</span></span><span class="pln"> pdb

num_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-number"><span class="lit">500</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">600</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">700</span></span><span class="pun">]</span><span class="pln">
alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'x'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'z'</span></span><span class="pun">]</span><span class="pln">


</span><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">nested_loop</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> number </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> num_list</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">

        </span><span class="hljs-comment"><span class="com"># Trigger debugger at this line</span></span><span class="pln">
        pdb</span><span class="pun">.</span><span class="pln">set_trace</span><span class="pun">()</span><span class="pln">
        </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> alpha_list</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">'__main__'</span></span><span class="pun">:</span><span class="pln">
    nested_loop</span><span class="pun">()</span></code></pre>

<p>
	بإضافة المُنقح في الشيفرة البرمجية الخاصة بك، فأنت لست بحاجة لتشغيل الشيفرة بطريقة معينة أو أن تتذكر إعدادات نقاط الفصل، وستتمكن من تشغيل البرنامج بطريقة عادية وتفعيل المُنقح من خلال التنفيذ.
</p>

<h2 id="تعديل-مسار-عمل-البرنامج">
	تعديل مسار عمل البرنامج
</h2>

<p>
	يتيح لك مُنقح بايثون تغيير مسار التنفيذ (Execution Flow) خلال زمن التنفيذ باستخدام الأمر<code>jump</code>، وهذا يعني أنك تستطيع أن تقفز إلى الأمام خلال البرنامج لمنع بعض الشيفرة البرمجية من التنفيذ أو العودة لتنفيذ جزء من الشيفرة مرة أخرى.<br>
	سوف نعمل على شرح هذه النقطة باستخدام برنامج صغير يقوم بإنشاء متغير من نوع قائمة (List) من الأحرف النصية موجودة ضمن المتغير النصي <code>sammy = "sammy"</code> :
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs python"><span class="hljs-function"><span class="hljs-keyword"><span class="kwd">def</span></span><span class="pln"> </span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pun">:</span></span><span class="pln">
    sammy_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
    sammy </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">"sammy"</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> sammy</span><span class="pun">:</span><span class="pln">
        sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">"__main__"</span></span><span class="pun">:</span><span class="pln">
    print_sammy</span><span class="pun">()</span></code></pre>

<p>
	إذا قمنا بتشغيل البرنامج بطريقة عادية باستخدام <code>python letters_list.py</code> فإننا سوف نحصل على النتيجة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs bash"><span class="typ">Output</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">]</span></code></pre>

<p>
	لنستعرض كيفية استخدام مُنقح بايثون في تغيير مسار عمل البرنامج السابق بحيث نقوم بالقفز قُدما خلال الشيفرة البرمجية للبرنامج أثناء التشغيل بعد الدورة الأولى من حلقة التكرار:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs avrasm"><span class="pln">python </span><span class="pun">-</span><span class="pln">m pdb letter_list</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> print_sammy</span><span class="pun">():</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> list
  </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-function"><span class="pln">  </span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> print_sammy</span><span class="pun">():</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">         sammy_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">         sammy </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">"sammy"</span></span><span class="pln">
  </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">         </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">sammy</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">             sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">             </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">8</span></span><span class="pln">     </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">"__main__"</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">9</span></span><span class="pln">         print_sammy</span><span class="pun">()</span><span class="pln">
 </span><span class="hljs-number"><span class="lit">10</span></span><span class="pln">     
 </span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">     
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">break</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="hljs-attribute"><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> pp letter
</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> jump </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> pp letter
</span><span class="hljs-string"><span class="str">'a'</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> disable </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Disabled</span><span class="pln"> breakpoint </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="hljs-attribute"><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">]</span></code></pre>

<p>
	قمنا خلال جلسة التنقيح السابقة بوضع نقطة فصل عند السطر رقم 5 لمنع الشيفرة البرمجية من الاستمرار، ومن ثم قمنا بطباعة بعض الأحرف والاستمرار من خلال الأمر<code>continue</code> لإظهار ماذا يحدث. ثم استخدمنا الأمر<code>jump</code> لتجاهل السطر 6. عند هذه النقطة، المتغير<code>letter</code> يساوي القيمة <code>a</code> ولكننا تجاهلنا السطر الذي يقوم بإضافة هذه القيمة للقائمة. بعد ذلك قمنا بتعطيل نقطة الفصل وتركنا البرنامج يستمر في التنفيذ. في النهاية، فإن الحرف<code>a</code> لم يُضف للقائمة <code>sammy_list</code>.<br>
	لنعد تشغيل جلسة التنقيح، ونستخدم المُنقح في العودة للخلف خلال التشغيل بهدف إعادة تنفيذ جملة الإضافة للقائمة sammy_list والتي تم تنفيذها خلال التكرار الأول من حلقة التكرار:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4422_7" style="">
<code class="hljs coffeescript"><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">)</span></span><span class="pun">&lt;</span><span class="hljs-title"><span class="kwd">module</span></span><span class="pun">&gt;</span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> print_sammy</span><span class="pun">():</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> list
  </span><span class="hljs-number"><span class="lit">1</span></span><span class="hljs-function"><span class="pln">  </span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> print_sammy</span><span class="pun">():</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">         sammy_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">         sammy </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">"sammy"</span></span><span class="pln">
  </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">         </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> </span><span class="hljs-attribute"><span class="pln">sammy</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">             sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">             </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">     
  </span><span class="hljs-number"><span class="lit">8</span></span><span class="pln">     </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-string"><span class="str">"__main__"</span></span><span class="pun">:</span><span class="pln">
  </span><span class="hljs-number"><span class="lit">9</span></span><span class="pln">         print_sammy</span><span class="pun">()</span><span class="pln">
 </span><span class="hljs-number"><span class="lit">10</span></span><span class="pln">     
 </span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">     
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">break</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="typ">Breakpoint</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="hljs-attribute"><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> pp letter
</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> jump </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> sammy_list</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">&gt;</span><span class="pln"> </span><span class="str">/Users/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="pln">py</span><span class="hljs-function"><span class="hljs-params"><span class="pun">(</span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">)</span></span><span class="hljs-title"><span class="pln">print_sammy</span></span><span class="hljs-params"><span class="pun">()</span></span><span class="pln">
</span><span class="pun">-&gt;</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sammy_list</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> pp letter
</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> disable </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Disabled</span><span class="pln"> breakpoint </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> at </span><span class="pun">/</span><span class="typ">Users</span><span class="pun">/</span><span class="pln">sammy</span><span class="pun">/</span><span class="pln">letter_list</span><span class="pun">.</span><span class="hljs-attribute"><span class="pln">py</span></span><span class="pun">:</span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="pun">(</span><span class="typ">Pdb</span><span class="pun">)</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'s'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'m'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'y'</span></span><span class="pun">]</span></code></pre>

<p>
	خلال جلسة التنقيح السابقة، قمنا بإضافة نقطة فصل عند السطر 6، وقمنا بالعودة للخلف للسطر 5 بعد الاستمرار.طبعنا ما تحتويه القائمة خلال التنفيذ وذلك لكي نظهر أن الحرف <code>s</code> قد أٌضيف مرتين. وبعد ذلك قمنا بتعطيل نقطة الفصل وجعلنا البرنامج يستمر في التنفيذ.<br>
	النتيجة الظاهرة توضح أن الحرف <code>s</code> أضيف مرتين في بداية القائمة <code>sammy_list</code>.<br>
	يمنع المنقّح بعض استخدامات الأمر<code>jump</code> ، وخاصة عندما يُعدَّل مسار البرنامج للأمام أو الخلفمن خلال جمل لم تُعرَّف. فمثلا، لا تستطيع القفز إلى دوال قبل أن تعرّف المعطيات الخاصة بها، وكذلك لا تستطيع الدخول في وسط جملة <code>try:except</code> أو الخروج من كتلة الشيفرة البرمجية لـ <code>finally</code>.<br>
	ملخص ما نستطيع ذكره عن الأمر<code>jump</code>، أنك من خلال استخدامه في مُنقح بايثون تستطيع تغيير مسار التنفيذ خلال التنقيح لمعرفة هل هذا التغيير مفيد ضمن ظروف ومعطيات محددة أم لا، وكذلك يساعدك في فهم أصل أو مكان الخلل والمشاكل التي تظهر خلال تنفيذ البرنامج.
</p>

<h2 id="جدول-أوامر-المنقح-pdb">
	جدول أوامر المنقح pdb
</h2>

<p>
	هنا نلخص لكم أوامر المُنقح pdb مع شرح بسيط عما يقدمه كل أمر لكي يساعدك على التذكر خلال تنقيح البرامج على بايثون:
</p>

<center>
	<table border="1"><tbody>
<tr>
<td style="background-color: rgb(255, 175, 75); padding: 5px 10px; text-align: center;">
					الأمر
				</td>
				<td style="background-color: rgb(255, 175, 75); padding: 5px 10px; text-align: center;">
					الاختصار
				</td>
				<td style="background-color: rgb(255, 175, 75); padding: 5px 10px; text-align: center;">
					العمل
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					help
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					h
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					يقدم قائمة بالأوامر المتاحة أو شرحا لأمر معين
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					jump
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					j
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					تحديد السطر القادم للتنفيذ
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					list
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					l
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					طباعة السياق (ما حول السطر الحالي) للتعرف أكثر على محيط التنفيذ الحالي
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					next
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					n
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					الاستمرار في التنفيذ حتى السطر القادم الذي تصل فيه الدالة الحالية أو تعود
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					step
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					s
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					تنفيذ السطر الحالي والتوقف عند أول فرصة متاحة
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					pp
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					pp
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					طباعة متغير أو تعبير معين
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					quit أو exit
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					q
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					الخروج من البرنامج
				</td>
			</tr>
<tr>
<td style=" padding: 5px 10px; text-align: center;">
					return
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					r
				</td>
				<td style=" padding: 5px 10px; text-align: center;">
					الاستمرار في التنفيذ حتى تعود الدالة الحالية
				</td>
			</tr>
</tbody></table>
</center>

<p>
	تستطيع أن تقرأ أكثر عن الأوامر وكيفية العمل مع المنقح من خلال الاطلاع على التوثيق الرسمي في بايثون.
</p>

<h2 id="خاتمة">
	خاتمة
</h2>

<p>
	يعد تنقيح البرمجيات خطوة مهمة في أي مشروع لبناء وتطوير برمجية. يقدم مُنقح بايثون بيئة تفاعلية تستطيع الاستفادة منها في تنقيح أي برنامج بايثون.<br>
	الأوامر المتاحة خلال المنقح تتيح لك وقف البرنامج الخاص بك، والاطلاع على قيم متغيراته خلال التنفيذ وتعديلها إذا رغبت، وكذلك التحكم في مسارات التنفيذ وغيره من الخصائص التي تساعدك في فهم ما يقوم به برنامجك بشكل كامل ولكي تضع يدك على المشاكل والقضايا التي تظهر خلال التنفيذ.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">حول تعلم البرمجة في بايثون 3</a>.<br>
	ترجمة – بتصرّف – للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-the-python-debugger" rel="external nofollow">How To Use the Python Debugger</a> لصاحبته Lisa Tagliaferri.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%85%D9%86-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%AA%D9%81%D8%A7%D8%B9%D9%84%D9%8A-r758" rel="">كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r757" rel="">كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">542</guid><pubDate>Sat, 16 Nov 2019 14:01:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x637;&#x628;&#x64A;&#x642; &#x627;&#x644;&#x62A;&#x639;&#x62F;&#x62F;&#x64A;&#x629; &#x627;&#x644;&#x634;&#x643;&#x644;&#x64A;&#x629; (Polymorphism) &#x639;&#x644;&#x649; &#x627;&#x644;&#x623;&#x635;&#x646;&#x627;&#x641; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r757/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db0389b2af29_----Polymorphism--.jpg.baa811620a551990aa517b61da4f6aea.jpg" /></p>

<p>
	التعددية الشكلية (Polymorphism) هي القدرة على استخدام واجهة موحدة لعدة أشكال مختلفة، مثل <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r720/" rel="">أنواع البيانات</a> أو <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754/" rel="">الأصناف </a>. هذا يسمح <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/" rel="">للدوال</a> باستخدام كيانات من أنواع مختلفة.
</p>

<p>
	بالنسبة للبرامج الكائنية في بايثون، هذا يعني أنه يمكن استخدام كائن معين ينتمي إلى صنف مُعيَّن كما لو كان ينتمي إلى صنف مختلف. تسمح التعددية الشكلية بكتابة شيفرات مرنة ومجرّدَة وسهلة التوسيع والصيانة.
</p>

<p>
	سوف تتعلم في هذا الدرس كيفية تطبيق التعددية الشكلية على أصناف بايثون.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32146" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db0389ca8b38_----Polymorphism--.jpg.48d7397ef79e205702ae9399a8288bac.jpg" rel=""><img alt="كـيـفـيــــة-تطـبـيـــق-التعددية-الشكلية-Polymorphism-عـلـــى-الأصــنــــــاف.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32146" data-unique="wk02i580x" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db0389cbeb32_----Polymorphism--.thumb.jpg.93a2e0f0b798909e72c3d39f7b69714d.jpg"></a>
</p>

<h2>
	ما هي التعددية الشكلية؟
</h2>

<p>
	التعددية الشكلية هي إحدى السمات الأساسية للأصناف في بايثون، وتُستخدَم عندما تكون هناك توابع لها نفس الأسماء في عدة أصناف، أو أصناف فرعية. يسمح ذلك للدوال باستخدام كائنات من أيٍّ من تلك الأصناف والعمل عليها دون الاكتراث لنوعها.
</p>

<p>
	يمكن تنفيذ التعددية الشكلية عبر [الوراثة](رابط المقالة السابقة)، أو باستخدام توابعِ الأصناف الفرعية، أو إعادة تعريفها (overriding).
</p>

<p>
	يستخدم بايثون نظام أنواع (typing) خاص، يسمى «<a href="https://en.wikipedia.org/wiki/Duck_typing" rel="external nofollow">نظام التحقق من الأنواع: البطة نموذجًا</a>» (Duck Typing)، وهو حالة خاصة من أنظمة التحقق من الأنواع الديناميكية (Dynamic Typing). يستخدم هذا النظامُ التعدُّديةَ الشكلية، بما في ذلك <a href="https://en.wikipedia.org/wiki/Late_binding" rel="external nofollow">الربط المتأخر</a>، <a href="https://en.wikipedia.org/wiki/Dynamic_dispatch" rel="external nofollow">والإيفاد الديناميكي</a>. يعتمد هذا النظام على «نموذج البطة» بناءً على اقتباسٍ للكاتب جيمس ويتكومب رايلي:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"عندما أرى طائرًا يمشي مثل بطة، ويسبح مثل بطة، وصوته كصوت البطة، فسأعدُّ هذا الطير بطةً"
	</p>
</blockquote>

<p>
	خُصِّص هذا المفهوم من قبل مهندس الحاسوب الإيطالي أليكس مارتيلي (Alex Martelli) في رسالة إلى مجموعة comp.lang.python، يقوم نظام التحقق من الأنواع هذا الذي يعتمد البطة نموذجًا على تعريف الكائن من منظور ملاءمة الغرض الذي أُنشِئ لأجله. عند استخدام نظام أنواع عادي، فإنّ ملاءمة الكائن لغرض مُعيَّن يتحدد بنوع الكائن فقط، ولكن في نموذج البطة، يَتحدَّد ذلك بوجود التوابع والخاصيات الضرورية لذلك الغرض بدلًا من النوع الحقيقي للكائن. بمعنى آخر، إذا أردت أن تعرف إن كان الكائن بطةً أم لا، فعليك التحقق مما إذا كان ذلك الكائن يمشي مشي البطة، وصوته كصوت البطة، بدلًا من أن تسأل عما إذا كان الكائن بطةً.
</p>

<p>
	عندما تحتوي عدة أصناف أو أصناف فرعية على توابع لها نفس الأسماء، ولكن بسلوكيات مختلفة، نقول إنّ تلك الأصناف متعددة الأشكال (polymorphic) لأنها تستعمل واجهة موحدة يمكن استخدامها مع كيانات من أنواع مختلفة. يمكن للدوال تقييم ومعالجة هذه التوابع متعدِّدة الأشكال دون معرفة أصنافها.
</p>

<h2>
	إنشاء أصناف متعددة الأشكال
</h2>

<p>
	للاستفادة من التَعدُّدية الشكلية، سننشئ صنفين مختلفين لاستخدامهما مع كائنين مختلفين. يحتاج هذان الصنفان المختلفان واجهة موحدة يمكن استخدامها بطريقة تعدُّدية الشكل (polymorphically)، لذلك سنعرّف فيهما توابع مختلفة، ولكن لها نفس الاسم.
</p>

<p>
	سننشئ صنفًا باسم <code>‎Shark‎</code> وصنفُا آخر باسم <code>‎Clownfish‎</code>، وسيُعرِّف كل منهما التوابع <code>‎swim()‎</code> و <code>‎swim_backwards()‎</code> و <code>‎skeleton()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_6" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"القرش يسبح."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> swim_backwards</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"لا يمكن للقرش أن يسبح إلى الوراء، لكن يمكنه أن يغوص إلى الوراء."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> skeleton</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"هيكل القرش مصنوع من الغضروف."</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"سمكة المهرج تسبح."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> swim_backwards</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"يمكن لسمكة المهرج أن تسبح إلى الخلف."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> skeleton</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"هيكل سمكة المهرج مصنوع من العظام."</span><span class="pun">)</span></pre>

<p>
	في الشيفرة أعلاه، لدى الصنفين <code>‎Shark‎</code> و <code>‎Clownfish‎</code> ثلاث توابع تحمل نفس الاسم بيْد أنّ وظائف تلك التوابع تختلف من صنف لآخر.
</p>

<p>
	دعنا نستنسخ (instantiate) من هذين الصنفين كائنين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_8" style="">
<span class="pun">...</span><span class="pln">
sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">
sammy</span><span class="pun">.</span><span class="pln">skeleton</span><span class="pun">()</span><span class="pln">

casey </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">()</span><span class="pln">
casey</span><span class="pun">.</span><span class="pln">skeleton</span><span class="pun">()</span></pre>

<p>
	عند تنفيذ البرنامج باستخدام الأمر <code>‎python polymorphic_fish.py‎</code>، يمكننا أن نرى أنّ كل كائن يتصرف كما هو متوقع:
</p>

<pre class="ipsCode">
هيكل القرش مصنوع من الغضروف.
هيكل سمكة المهرج مصنوع من العظام.
</pre>

<p>
	الآن وقد أصبح لدينا كائنان يستخدمان نفس الواجهة، فبمقدورنا استخدام هذين الكائنين بنفس الطريقة بغض النظر عن نوعيهما.
</p>

<h2>
	التعددية الشكلية في توابع الأصناف
</h2>

<p>
	لإظهار كيف يمكن لبايثون استخدام الصنفين المختلفين اللذين عرّفناهما أعلاه بنفس الطريقة، سننشئ أولاً حلقة <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/" rel="">for</a>، والتي ستمر على <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-tuples-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r507/" rel="">صف</a> من الكائنات. ثم سنستدعي التوابع بغض النظر عن نوع الصنف الذي ينتمي إليه كل كائن. إلا أننا سنفترض أنّ تلك التوابع موجودة في كل تلك الأصناف.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_10" style="">
<span class="pun">...</span><span class="pln">
sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">

casey </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">()</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> fish </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">,</span><span class="pln"> casey</span><span class="pun">):</span><span class="pln">
    fish</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
    fish</span><span class="pun">.</span><span class="pln">swim_backwards</span><span class="pun">()</span><span class="pln">
    fish</span><span class="pun">.</span><span class="pln">skeleton</span><span class="pun">()</span></pre>

<p>
	لدينا كائنان، <code>‎sammy‎</code> من الصنف <code>‎Shark‎</code>، و <code>‎casey‎</code> من الصنف <code>‎Clownfish‎</code>. تمر حلقة <code>‎for‎</code> على هذين الكائنين، وتستدعي التوابع <code>‎swim()‎</code> و <code>‎swim_backwards()‎</code> و <code>‎skeleton()‎</code> على كل منها.
</p>

<p>
	عند تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
القرش يسبح.
لا يمكن للقرش أن يسبح إلى الوراء، لكن يمكنه أن يغوص إلى الوراء.
هيكل القرش مصنوع من الغضروف.
سمكة المهرج تسبح.
يمكن لسمكة المهرج أن تسبح إلى الخلف.
هيكل سمكة المهرج مصنوع من العظام.
</pre>

<p>
	مرت الحلقة <code>‎for‎</code> على الكائن <code>‎sammy‎</code> من الصنف <code>‎Shark‎</code>، ثم على الكائن <code>‎casey‎</code> المنتمي إلى الصنف <code>‎Clownfish‎</code>، لذلك نرى التوابع الخاصة بالصنف <code>‎Shark‎</code> قبل التوابع الخاصة بالصنف <code>‎Clownfish‎</code>.
</p>

<p>
	يدلُّ هذا على أنَّ بايثون تستخدم هذه التوابع دون أن تعرف أو تعبأ بتحديد نوع الصنف الخاص بالكائنات. وهذا مثال حي على استخدام التوابع بطريقة مُتعدِّدَة الأشكال.
</p>

<h2>
	التعددية الشكلية في الدوال
</h2>

<p>
	يمكننا أيضًا إنشاء دالة تقبل أيّ شيء، وهذا سيسمح باستخدام التعددية الشكلية.
</p>

<p>
	لننشئ دالة تسمى <code>‎in_the_pacific()‎</code>، والتي تأخذ كائنًا يمكننا تسميته <code>‎fish‎</code>. رغم أننا سنستخدم الاسم <code>‎fish‎</code>، إلا أنه يمكننا استدعاء أي كائن في هذه الدالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_13" style="">
<span class="pun">…</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> in_the_pacific</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">):</span></pre>

<p>
	بعد ذلك، سنجعل الدالة تستخدم الكائن <code>‎fish‎</code> الذي مرّرناه إليها. وفي هذه الحالة، سنستدعي التابع <code>‎swim()‎</code> المعرّف في كل من الصنفين <code>‎Shark‎</code> و <code>‎Clownfish‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_15" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> in_the_pacific</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">):</span><span class="pln">
    fish</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span></pre>

<p>
	بعد ذلك، سننشئ نسخًا (instantiations) من الصنفين <code>‎Shark‎</code> و <code>‎Clownfish‎</code> لنمرّرهما بعد ذلك إلى نفس الدالة <code>‎in_the_pacific()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7065_17" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> in_the_pacific</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">):</span><span class="pln">
    fish</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">

sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">

casey </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">()</span><span class="pln">

in_the_pacific</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">)</span><span class="pln">
in_the_pacific</span><span class="pun">(</span><span class="pln">casey</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
القرش يسبح.
سمكة المهرج تسبح.
</pre>

<p>
	رغم أننا مرّرنا كائنًا عشوائيًا (<code>‎fish‎</code>) إلى الدالة <code>‎in_the_pacific()‎</code> عند تعريفها، إلا أننا ما زلنا قادرين على استخدامها استخدامًا فعالًا، وتمرير نسخ من الصنفين <code>‎Shark‎</code> و <code>‎Clownfish‎</code> إليها. استدعى الكائنُ <code>‎casey‎</code> التابعَ <code>‎swim()‎</code> المُعرَّف في الصنف <code>‎Clownfish‎</code>، فيما استدعى الكائنُ <code>‎sammy‎</code> التابعَ <code>‎swim()‎</code> المُعرَّف في الصنف <code>‎Shark‎</code>.
</p>

<h2>
	خلاصة
</h2>

<p>
	تسمح التعدُّدية الشكلية باستخدام الكائنات بغض النظر عن نوعها، وهذا يوفر لبايثون مرونة كبيرة، وقابلية لتوسيع الشيفرة الكائنية.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-apply-polymorphism-to-classes-in-python-3" rel="external nofollow">How To Apply Polymorphism to Classes in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%85%D9%86%D9%82%D8%AD-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r542/" rel="">كيف تستخدم منقح بايثون</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%B1%D8%A7%D8%AB%D8%A9-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r756/" rel="">وراثة الأصناف في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">757</guid><pubDate>Wed, 13 Nov 2019 14:05:00 +0000</pubDate></item><item><title>&#x648;&#x631;&#x627;&#x62B;&#x629; &#x627;&#x644;&#x623;&#x635;&#x646;&#x627;&#x641; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%88%D8%B1%D8%A7%D8%AB%D8%A9-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r756/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db0206e42002_-.jpg.03bf0742900827030292fb90a4e36b61.jpg" /></p>

<p>
	تُسِّهل البرمجة الكائنية كتابة شيفرات قابلة لإعادة الاستخدام وتجنب التكرار في مشاريع التطوير. إحدى الآليات التي تحقق بها البرمجة الكائنية هذا الهدف هي مفهوم الوراثة (inheritance)، التي بفضلها يمكن لصنفٍ فرعي (subclass) استخدام الشيفرة الخاصة بصنف أساسي (base class، ويطلق عليه «صنف أب» أيضًا) موجود مسبقًا.
</p>

<p>
	سيستعرض هذا الدرس بعض الجوانب الرئيسية لمفهوم الوراثة في بايثون، بما في ذلك كيفية إنشاء الأصناف الأساسية (parent classes) والأصناف الفرعية (child classes)، وكيفية إعادة تعريف (override) التوابع والخاصيات، وكيفية استخدام التابع <code>‎super()‎</code>، وكيفية الاستفادة من الوراثة المتعددة (multiple inheritance).
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32145" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db020670ce64_-.jpg.7171c70d44f3d210da3ab2dba08a547d.jpg" rel=""><img alt="وراثة-الأصناف.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32145" data-unique="daa8ctq68" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db0206722527_-.thumb.jpg.f692d05596cfd369fca87eed4096c846.jpg"></a>
</p>

<h2>
	ما هي الوراثة؟
</h2>

<p>
	تقوم <strong>الوراثة</strong> على استخدام شيفرة صنف معين في صنف آخر أي يرث صنف يراد إنشاؤه شيفرة صنف آخر. يمكن تمثيل مفهوم الوراثة في البرمجة بالوراثة في علم الأحياء تمامًا، فالأبناء يرثون خاصيات معينة من آبائهم. ويمكن لطفل أن يرث طول والده أو لون عينيه بالإضافة إلى خاصيات أخرى جديدة خاصة فيه. كما يتشارك الأطفال نفس اسم العائلة الخاصة بآبائهم.
</p>

<p>
	ترث <strong>الأصناف الفرعية</strong> (subclasses، تُسمى أيضًا *<em>الأصناف الأبناء</em> [child classes]) التوابع والمتغيرات من *<em>الأصناف الأساسية</em>* (base classes، تسمى أيضًا<strong>الأصناف الآباء</strong> [parent classes]).
</p>

<p>
	مثلًا، قد يكون لدينا صنف أساسي يسمى <code>‎Parent‎</code> يحتوي <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r755/" rel="">متغيرات الأصناف</a> <code>‎last_name‎</code> و <code>‎height‎</code> و <code>‎eye_color‎</code>، والتي سيرثها الصنف الابن <code>‎Child‎</code>.
</p>

<p>
	لمَّا كان الصنف الفرعي <code>‎Child‎</code> يرث الصنف الأساسي <code>‎Parent‎</code>، فبإمكانه إعادة استخدام شيفرة <code>‎Parent‎</code>، مما يسمح للمبرمج بكتابة شيفرة أوجز، وتقليل التكرار.
</p>

<h2>
	الأصناف الأساسية
</h2>

<p>
	تشكل الأصناف الأساسية أساسًا يمكن أن تستند إليه الأصناف الفرعية المُتفرِّعة منها، إذ تسمح الأصناف الأساسية بإنشاء أصناف فرعية عبر الوراثة دون الحاجة إلى كتابة نفس الشيفرة في كل مرة. يمكن تحويل أي صنف إلى صنف أساسي، إذ يمكن استخدامه لوحده، أو جعله قالبًا (نموذجًا).
</p>

<p>
	لنفترض أّنّ لدينا صنفًا أساسيًا باسم <code>‎Bank_account‎</code>، وصنفين فرعيين مُشتقين منه باسم <code>‎Personal_account‎</code> و <code>‎Business_account‎</code>. ستكون العديد من التوابع مشتركة بين الحسابات الشخصية (Personal<em>account) والحسابات التجارية (Business</em>account)، مثل توابع سحب وإيداع الأموال، لذا يمكن أن تنتمي تلك التوابع إلى الصنف الأساسي <code>‎Bank_account‎</code>. سيكون للصنف <code>‎Business_account‎</code> توابع خاصة به، مثل تابع مخصص لعملية جمع سجلات ونماذج الأعمال، بالإضافة إلى متغير <code>‎employee_identification_number‎</code> موروث من الصنف الأب.
</p>

<p>
	وبالمثل، قد يحتوي الصنف <code>‎Animal‎</code> على التابعين <code>‎eating()‎</code> و <code>‎sleeping()‎</code>، وقد يتضمن الصنف الفرعي <code>‎Snake‎</code> تابعين إضافيين باسم <code>‎hissing()‎</code> و <code>‎slithering()‎</code> خاصين به.
</p>

<p>
	دعنا ننشئ صنفًا أساسيًا باسم <code>‎Fish‎</code> لاستخدامه لاحقًا أساسًا لأصناف فرعية تمثل أنواع الأسماك. سيكون لكل واحدة من تلك الأسماك أسماء أولى وأخيرة، بالإضافة إلى خصائص مميزة خاصة بها.
</p>

<p>
	سننشئ ملفًا جديدًا يسمى <code>‎fish.py‎</code> ونبدأ <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754/" rel="">بالباني</a>، والذي سنعرّف داخله متغيري الصنف <code>‎first_name‎</code> و <code>‎last_name‎</code> لكل كائنات الصنف <code>‎Fish‎</code>، أو أصنافه الفرعية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_6" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Fish</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> first_name</span><span class="pun">,</span><span class="pln"> last_name</span><span class="pun">=</span><span class="str">"Fish"</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> first_name
        self</span><span class="pun">.</span><span class="pln">last_name </span><span class="pun">=</span><span class="pln"> last_name</span></pre>

<p>
	القيمة الافتراضية للمتغير <code>‎last_name‎</code> هي السلسلة النصية <code>‎"Fish"‎</code>، لأننا نعلم أنّ معظم الأسماك سيكون هذا هو اسمها الأخير.
</p>

<p>
	لنُضف بعض التوابع الأخرى:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_8" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Fish</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> first_name</span><span class="pun">,</span><span class="pln"> last_name</span><span class="pun">=</span><span class="str">"Fish"</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> first_name
        self</span><span class="pun">.</span><span class="pln">last_name </span><span class="pun">=</span><span class="pln"> last_name

    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The fish is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> swim_backwards</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The fish can swim backwards."</span><span class="pun">)</span></pre>

<p>
	لقد أضفنا التابعين <code>‎swim()‎</code> و <code>‎swim_backwards()‎</code> إلى الصنف <code>‎Fish‎</code> حتى يتسنى لكل الأصناف الفرعية استخدام هذه التوابع.
</p>

<p>
	ما دام أنّ معظم الأسماك التي ننوي إنشاءها ستكون <a href="https://ar.wikipedia.org/wiki/%D8%A3%D8%B3%D9%85%D8%A7%D9%83_%D8%B9%D8%B8%D9%85%D9%8A%D8%A9" rel="external nofollow">عظمية</a> (أي أنّ لها هيكلا عظميًا) وليس <a href="https://ar.wikipedia.org/wiki/%D8%A3%D8%B3%D9%85%D8%A7%D9%83_%D8%BA%D8%B6%D8%B1%D9%88%D9%81%D9%8A%D8%A9" rel="external nofollow">غضروفية</a> (أي أن لها هيكلًا غضروفيًا)، فيمكننا إضافة بعض الخاصيات الإضافية إلى التابع <code>‎__init__()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_10" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Fish</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> first_name</span><span class="pun">,</span><span class="pln"> last_name</span><span class="pun">=</span><span class="str">"Fish"</span><span class="pun">,</span><span class="pln">
                 skeleton</span><span class="pun">=</span><span class="str">"bone"</span><span class="pun">,</span><span class="pln"> eyelids</span><span class="pun">=</span><span class="kwd">False</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> first_name
        self</span><span class="pun">.</span><span class="pln">last_name </span><span class="pun">=</span><span class="pln"> last_name
        self</span><span class="pun">.</span><span class="pln">skeleton </span><span class="pun">=</span><span class="pln"> skeleton
        self</span><span class="pun">.</span><span class="pln">eyelids </span><span class="pun">=</span><span class="pln"> eyelids

    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The fish is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> swim_backwards</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The fish can swim backwards."</span><span class="pun">)</span></pre>

<p>
	لا يختلف بناء الأصناف الأساسية عن بناء أي صنف آخر، إلا أننا نصممها لتستفيد منها الأصناف الفرعية المُعرّفة لاحقًا.
</p>

<h2>
	الأصناف الفرعية
</h2>

<p>
	الأصناف الفرعية هي أصناف ترث كل شيء من الصنف الأساسي. هذا يعني أنّ الأصناف الفرعية قادرة على الاستفادة من توابع ومتغيرات الصنف الأساسي.
</p>

<p>
	على سبيل المثال، سيتمكن الصنف الفرعي <code>‎Goldfish‎</code> المشتق من الصنف <code>‎Fish‎</code> من استخدام التابع <code>‎swim()‎</code> المُعرّف في <code>‎Fish‎</code> دون الحاجة إلى التصريح عنه.
</p>

<p>
	يمكننا النظر إلى الأصناف الفرعية على أنها أقسام من الصنف الأساسي. فإذا كان لدينا صنف فرعي يسمى <code>‎Rhombus‎</code> (معيّن)، وصنف أساسي يسمى <code>‎Parallelogram‎</code> (متوازي الأضلاع)، يمكننا القول أنّ المعين (<code>‎Rhombus‎</code>) هو متوازي أضلاع (<code>‎Parallelogram‎</code>).
</p>

<p>
	يبدو السطر الأول من الصنف الفرعي مختلفًا قليلًا عن الأصناف غير الفرعية، إذ يجب عليك تمرير الصنف الأساسي إلى الصنف الفرعي كمعامل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_12" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span></pre>

<p>
	الصنف <code>‎Trout‎</code> هو صنف فرعي من <code>‎Fish‎</code>. يدلنا على هذا الكلمةُ <code>‎Fish‎</code> المُدرجة بين قوسين.
</p>

<p>
	يمكننا إضافة توابع جديدة إلى الأصناف الفرعية، أو إعادة تعريف التوابع الخاصة بالصنف الأساسي، أو يمكننا ببساطة قبول التوابع الأساسية الافتراضية باستخدام الكلمة المفتاحية <code>‎pass‎</code>، وهو ما سنفعله في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_14" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<p>
	يمكننا الآن إنشاء كائن من الصنف <code>‎Trout‎</code> دون الحاجة إلى تعريف أي توابع إضافية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_16" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">pass</span><span class="pln">

terry </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">(</span><span class="str">"Terry"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> terry</span><span class="pun">.</span><span class="pln">last_name</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">skeleton</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">eyelids</span><span class="pun">)</span><span class="pln">
terry</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
terry</span><span class="pun">.</span><span class="pln">swim_backwards</span><span class="pun">()</span></pre>

<p>
	لقد أنشأنا كائنًا باسم <code>‎terry‎</code> من الصنف <code>‎Trout‎</code>، والذي سيستخدم جميع توابع الصنف <code>‎Fish‎</code> وإن لم نعرّفها في الصنف الفرعي <code>‎Trout‎</code>. يكفي أن نمرر القيمة <code>‎"Terry"‎</code> إلى المتغير <code>‎first_name‎</code>، أما المتغيرات الأخرى فقد جرى تهيئتها سلفًا.
</p>

<p>
	عند تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_18" style="">
<span class="typ">Terry</span><span class="pln"> </span><span class="typ">Fish</span><span class="pln">
bone
</span><span class="kwd">False</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> fish </span><span class="kwd">is</span><span class="pln"> swimming</span><span class="pun">.</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> fish can swim backwards</span><span class="pun">.</span></pre>

<p>
	لننشئ الآن صنفًا فرعيًا آخر يعرّف تابعًا خاصا به. سنسمي هذا الصنف <code>‎Clownfish‎</code>. سيسمح التابع الخاص به بالتعايش مع شقائق النعمان البحري:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_20" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> live_with_anemone</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The clownfish is coexisting with sea anemone."</span><span class="pun">)</span></pre>

<p>
	دعنا ننشئ الآن كائنًا آخر من الصنف <code>‎Clownfish‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_24" style="">
<span class="pun">...</span><span class="pln">
casey </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Clownfish</span><span class="pun">(</span><span class="str">"Casey"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">casey</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> casey</span><span class="pun">.</span><span class="pln">last_name</span><span class="pun">)</span><span class="pln">
casey</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
casey</span><span class="pun">.</span><span class="pln">live_with_anemone</span><span class="pun">()</span></pre>

<p>
	عند تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_26" style="">
<span class="typ">Casey</span><span class="pln"> </span><span class="typ">Fish</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> fish </span><span class="kwd">is</span><span class="pln"> swimming</span><span class="pun">.</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> clownfish </span><span class="kwd">is</span><span class="pln"> coexisting </span><span class="kwd">with</span><span class="pln"> sea anemone</span><span class="pun">.</span></pre>

<p>
	تُظهر المخرجات أنّ الكائن <code>‎casey‎</code> المستنسخ من الصنف <code>‎Clownfish‎</code> قادر على استخدام التابعين <code>‎__init__()‎</code> و <code>‎swim()‎</code> الخاصين بالصنف <code>‎Fish‎</code>، إضافة إلى التابع <code>‎live_with_anemone()‎</code> الخاص بالصنف الفرعي.
</p>

<p>
	إذا حاولنا استخدام التابع <code>‎live_with_anemone()‎</code> في الكائن <code>‎Trout‎</code>، فسوف يُطلق خطأ:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_28" style="">
<span class="pln">terry</span><span class="pun">.</span><span class="pln">live_with_anemone</span><span class="pun">()</span><span class="pln">
</span><span class="typ">AttributeError</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Trout'</span><span class="pln"> object has no attribute </span><span class="str">'live_with_anemone'</span></pre>

<p>
	ذلك أنَّ التابع <code>‎live_with_anemone()‎</code> ينتمي إلى الصنف الفرعي <code>‎Clownfish‎</code> فقط، وليس إلى الصنف الأساسي <code>‎Fish‎</code>.
</p>

<p>
	ترث الأصناف الفرعية توابع الصنف الأساسي الذي اشتُقَّت منه، لذا يمكن لكل الأصناف الفرعية استخدام تلك التوابع.
</p>

<h2>
	إعادة تعريف توابع الصنف الأساسي
</h2>

<p>
	في المثال السابق عرّفنا الصنف الفرعي <code>‎Trout‎</code> الذي استخدم الكلمة المفتاحية <code>‎pass‎</code> ليرث جميع سلوكيات الصنف الأساسي <code>‎Fish‎</code>، وعرّفنا كذلك صنفًا آخر <code>‎Clownfish‎</code> يرث جميع سلوكيات الصنف الأساسي، ويُنشئ أيضًا تابعًا خاصًا به. قد نرغب في بعض الأحيان في استخدام بعض سلوكيات الصنف الأساسي، ولكن ليس كلها. يُطلَق على عملية تغيير توابع الصنف الأساسي «إعادة التعريف» (Overriding).
</p>

<p>
	عند إنشاء الأصناف الأساسية أو الفرعية، فلا بد أن تكون لك رؤية عامة لتصميم البرنامج حتى لا تعيد تعريف التوابع إلا عند الضرورة.
</p>

<p>
	سننشئ صنفًا فرعيًا <code>‎Shark‎</code> مشتقًا من الصنف الأساسي <code>‎Fish‎</code>، الذي سيمثل الأسماك العظمية بشكل أساسي، لذا يتعين علينا إجراء تعديلات على الصنف <code>‎Shark‎</code> المخصص في الأصل للأسماك الغضروفية. من منظور تصميم البرامج، إذا كانت لدينا أكثر من سمكة غير عظمية واحدة، فيُستحب أن ننشئ صنفًا خاصًا بكل نوع من هذين النوعين من الأسماك.
</p>

<p>
	تمتلك أسماك القرش، على عكس الأسماك العظمية، هياكل مصنوعة من الغضاريف بدلاً من العظام. كما أنّ لديها جفونًا، ولا تستطيع السباحة إلى الوراء، كما أنها قادرة على المناورة للخلف عن طريق الغوص.
</p>

<p>
	على ضوء هذه المعلومات، سنعيد تعريف الباني <code>‎__init__()‎</code> والتابع <code>‎swim_backwards()‎</code>. لا نحتاج إلى تعديل التابع <code>‎swim()‎</code> لأنّ أسماك القرش يمكنها السباحة. دعنا نلقي نظرة على هذا الصنف الفرعي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_30" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> first_name</span><span class="pun">,</span><span class="pln"> last_name</span><span class="pun">=</span><span class="str">"Shark"</span><span class="pun">,</span><span class="pln">
                 skeleton</span><span class="pun">=</span><span class="str">"cartilage"</span><span class="pun">,</span><span class="pln"> eyelids</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> first_name
        self</span><span class="pun">.</span><span class="pln">last_name </span><span class="pun">=</span><span class="pln"> last_name
        self</span><span class="pun">.</span><span class="pln">skeleton </span><span class="pun">=</span><span class="pln"> skeleton
        self</span><span class="pun">.</span><span class="pln">eyelids </span><span class="pun">=</span><span class="pln"> eyelids

    </span><span class="kwd">def</span><span class="pln"> swim_backwards</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The shark cannot swim backwards, but can sink backwards."</span><span class="pun">)</span></pre>

<p>
	لقد أعدنا تعريف المعاملات التي تمت تهيئتها في التابع <code>‎__init__()‎</code>، فأخذ المتغير <code>‎last_name‎</code> القيمة <code>‎"Shark"‎</code>، كما أُسنِد إلى المتغير <code>‎skeleton‎</code> القيمة <code>‎"cartilage"‎</code>، فيما أُسنِدَت القيمة المنطقية <code>‎True‎</code> إلى المتغير <code>‎eyelids‎</code>. يمكن لجميع نُسخ الصنف إعادة تعريف هذه المعاملات.
</p>

<p>
	يطبع التابع <code>‎swim_backwards()‎</code> <a href="https://wiki.hsoub.com/Python/str" rel="external">سلسلة نصية</a> مختلفة عن تلك التي يطبعها في الصنف الأساسي <code>‎Fish‎</code>، لأنّ أسماك القرش غير قادرة على السباحة للخلف كما تفعل الأسماك العظمية.
</p>

<p>
	يمكننا الآن إنشاء نسخة من الصنف الفرعي <code>‎Shark‎</code>، والذي سيستخدم التابع <code>‎swim()‎</code> الخاص بالصنف الأساسي <code>‎Fish‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_32" style="">
<span class="pun">...</span><span class="pln">
sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> sammy</span><span class="pun">.</span><span class="pln">last_name</span><span class="pun">)</span><span class="pln">
sammy</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
sammy</span><span class="pun">.</span><span class="pln">swim_backwards</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">.</span><span class="pln">eyelids</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">.</span><span class="pln">skeleton</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ هذه الشيفرة، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_34" style="">
<span class="typ">Sammy</span><span class="pln"> </span><span class="typ">Shark</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> fish </span><span class="kwd">is</span><span class="pln"> swimming</span><span class="pun">.</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> shark cannot swim backwards</span><span class="pun">,</span><span class="pln"> but can sink backwards</span><span class="pun">.</span><span class="pln">
</span><span class="kwd">True</span><span class="pln">
cartilage</span></pre>

<p>
	لقد أعاد الصنف الفرعي <code>‎Shark‎</code> تعريف التابعين <code>‎__init__()‎</code> و <code>‎swim_backwards()‎</code> الخاصين بالصنف الأساسي <code>‎Fish‎</code>، وورث في نفس الوقت التابع <code>‎swim()‎</code> الخاص بالصنف الأساسي.
</p>

<h2>
	الدالة <code>‎super()‎</code>
</h2>

<p>
	يمكنك باستخدام الدالة <code>‎super()‎</code> الوصول إلى التوابع الموروثة التي أُعيدت كتابتها.
</p>

<p>
	عندما نستخدم الدالة <code>‎super()‎</code>، فإننا نستدعي التابع الخاص بالصنف الأساسي لاستخدامه في الصنف الفرعي. على سبيل المثال، قد نرغب في إعادة تعريف جانب من التابع الأساسي وإضافة وظائف معينة إليه، ثم بعد ذلك نستدعي التابع الأساسي لإنهاء بقية العمل.
</p>

<p>
	في برنامج خاص بتقييم الطلاب مثلًا، قد نرغب في تعريف صنف فرعي <code>‎Weighted_grade‎</code> يرث الصنف الأساسي <code>‎Grade‎</code>، ونعيد فيه تعريف التابع <code>‎calculate_grade()‎</code> الخاص بالصنف الأساسي من أجل تضمين شيفرة خاصة بحساب التقدير المرجّح (weighted grade)، مع الحفاظ على بقية وظائف الصنف الأساسي. عبر استدعاء التابع <code>‎super()‎</code>، سنكون قادرين على تحقيق ذلك.
</p>

<p>
	عادة ما يُستخدم التابع <code>‎super()‎</code> ضمن التابع <code>‎__init__()‎</code>، لأنّه المكان الذي ستحتاج فيه على الأرجح إلى إضافة بعض الوظائف الخاصة إلى الصنف الفرعي قبل إكمال التهيئة من الصنف الأساسي.
</p>

<p>
	لنضرب مثلًا لتوضيح ذلك، دعنا نعدّل الصنف الفرعي <code>‎Trout‎</code>. نظرًا لأنّ سمك السلمون المرقَّط من أسماك المياه العذبة، فلنضف متغيرًا اسمه <code>‎water‎</code> إلى التابع <code>‎__init__()‎</code>، ولنُعطه القيمة <code>‎"freshwater"‎</code>، ولكن مع الحفاظ على باقي متغيرات ومعاملات الصنف الأساسي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_36" style="">
<span class="pun">...</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">(</span><span class="typ">Fish</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> water </span><span class="pun">=</span><span class="pln"> </span><span class="str">"freshwater"</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">water </span><span class="pun">=</span><span class="pln"> water
        super</span><span class="pun">().</span><span class="pln">__init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	لقد أعدنا تعريف التابع <code>‎__init__()‎</code> في الصنف الفرعي <code>‎Trout‎</code>، وغيرنا سلوكه موازنةً بالتابع <code>‎__init__()‎</code> المُعرَّف سلفًا في الصنف الأساسي <code>‎Fish‎</code>. لاحظ أننا استدعينا التابع <code>‎__init__()‎</code> الخاص بالصنف <code>‎Fish‎</code> بشكل صريح ضمن التابع <code>‎__init__()‎</code> الخاص بالصنف <code>‎Trout‎</code>،.
</p>

<p>
	بعد إعادة تعريف التابع، لم نعد بحاجة إلى تمرير <code>‎first_name‎</code> كمعامل إلى <code>‎Trout‎</code>، وفي حال فعلنا ذلك، فسيؤدي ذلك إلى إعادة تعيين <code>‎freshwater‎</code> بدلاً من ذلك. سنُهيِّئ بعد ذلك الخاصية <code>‎first_name‎</code> عن طريق استدعاء المتغير في الكائن خاصتنا.
</p>

<p>
	الآن يمكننا استدعاء متغيرات الصنف الأساسي التي تمت تهيئتها، وكذلك استخدام المتغير الخاص بالصنف الفرعي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_38" style="">
<span class="pun">...</span><span class="pln">
terry </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Trout</span><span class="pun">()</span><span class="pln">

</span><span class="com"># تهيئة الاسم الأول</span><span class="pln">
terry</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Terry"</span><span class="pln">

</span><span class="com"># super()  الخاص بالصنف الأساسي عبر  __init__() استخدام</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">first_name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> terry</span><span class="pun">.</span><span class="pln">last_name</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">eyelids</span><span class="pun">)</span><span class="pln">

</span><span class="com"># المعاد تعريفها في الصنف الفرعي __init__() استخدام</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">terry</span><span class="pun">.</span><span class="pln">water</span><span class="pun">)</span><span class="pln">

</span><span class="com"># الخاص بالصنف الأساسي swim() استخدام التابع</span><span class="pln">
terry</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span></pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Terry Fish
False
freshwater
The fish is swimming.
</pre>

<p>
	تُظهر المخرجات أنّ الكائن <code>‎terry‎</code> المنسوخ من الصنف الفرعي <code>‎Trout‎</code> قادر على استخدام المتغير <code>‎water‎</code> الخاص بتابع الصنف الفرعي <code>‎__init__()‎</code>، إضافة إلى استدعاء المتغيرات <code>‎first_name‎</code> و <code>‎last_name‎</code> و <code>‎eyelids‎</code> الخاصة بالتابع <code>‎__init__()‎</code> المُعرَّف في الصنف الأساسي <code>‎Fish‎</code>.
</p>

<p>
	يسمح لنا التابع <code>‎super()‎</code> المُضمن في بايثون باستخدام توابع الصنف الأساسي حتى بعد إعادة تعريف تلك التوابع في الأصناف الفرعية.
</p>

<h2>
	الوراثة المُتعدِّدة (Multiple Inheritance)
</h2>

<p>
	المقصود بالوراثة المتعددة هي قدرة الصنف على أن يرث الخاصيات والتوابع من أكثر من صنف أساسي واحد. هذا من شأنه تقليل التكرار في البرامج، ولكنه يمكن أيضًا أن يُعقِّد العمل، لذلك يجب استخدام هذا المفهوم بحذر.
</p>

<p>
	لإظهار كيفية عمل الوراثة المتعددة، دعنا ننشئ صنفًا فرعيًا <code>‎Coral_reef‎</code> يرث من الصنفين <code>‎Coral‎</code> و <code>‎Sea_anemone‎</code>. يمكننا إنشاء تابع في كل صنف أساسي، ثم استخدام الكلمة المفتاحية <code>‎pass‎</code> في الصنف الفرعي <code>‎Coral_reef‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_40" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Coral</span><span class="pun">:</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> community</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Coral lives in a community."</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Anemone</span><span class="pun">:</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> protect_clownfish</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The anemone is protecting the clownfish."</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">CoralReef</span><span class="pun">(</span><span class="typ">Coral</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Anemone</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<p>
	يحتوي الصنف <code>‎Coral‎</code> على تابع يسمى <code>‎community()‎</code>، والذي يطبع سطرًا واحدًا، بينما يحتوي الصنف <code>‎Anemone‎</code> على تابع يسمى <code>‎protect_clownfish()‎</code>، والذي يطبع سطرًا آخر. سنُمرِّر الصنفين كلاهما بين قوسين في تعريف الصنف <code>CoralReef</code>، ما يعني أنه سيرث الصنفين معًا.
</p>

<p>
	دعنا الآن ننشئ كائنًا من الصنف <code>CoralReef</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6824_42" style="">
<span class="pun">...</span><span class="pln">
great_barrier </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CoralReef</span><span class="pun">()</span><span class="pln">
great_barrier</span><span class="pun">.</span><span class="pln">community</span><span class="pun">()</span><span class="pln">
great_barrier</span><span class="pun">.</span><span class="pln">protect_clownfish</span><span class="pun">()</span></pre>

<p>
	الكائن <code>‎great_barrier‎</code> مُشتقٌ الصنف <code>‎CoralReef‎</code>، ويمكنه استخدام التوابع من كلا الصنفين الأساسيين. عند تنفيذ البرنامج، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Coral lives in a community.
The anemone is protecting the clownfish.
</pre>

<p>
	تُظهِر المخرجات أنَّ التوابع من كلا الصنفين الأساسيين استُخدِما بفعالية في الصنف الفرعي.
</p>

<p>
	تسمح لنا الوراثة المُتعدِّدة بإعادة استخدام الشيفرات البرمجية المكتوبة في أكثر من صنف أساسي واحد. وإذا تم تعريف التابع نفسه في أكثر من صنف أساسي واحد، فإنّ الصنف الفرعي سيستخدم التابع الخاص بالصنف الأساسي الذي ظهر أولًا في قائمة الأصناف المُمرَّرة إليه عند تعريفه.
</p>

<p>
	رغم فوائدها الكثيرة وفعاليتها، إلا أنَّ عليك توخي الحذر في استخدام الوراثة المُتعدِّدة، حتى لا ينتهي بك الأمر بكتابة برامج مُعقَّدة وغير مفهومة للمبرمجين الآخرين.
</p>

<h2>
	خلاصة
</h2>

<p>
	تعلمنا في هذا الدرس كيفية إنشاء أصناف أساسية وفرعية، وكيفية إعادة تعريف توابع وخاصيات الأصناف الأساسية داخل الأصناف الفرعية باستخدام التابع <code>‎super()‎</code>، إضافة إلى مفهوم الوراثة المتعددة.
</p>

<p>
	الوراثة هي إحدى أهم ميزات البرمجة الكائنية التي تجعلها متوافقة مع مبدأ DRY (لا تكرر نفسك)، وهذا يحسن إنتاجية المبرمجين، ويساعدهم على تصميم برامج فعالة وواضحة.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/understanding-class-inheritance-in-python-3" rel="external nofollow">Understanding Class Inheritance in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D8%AA%D8%B9%D8%AF%D8%AF%D9%8A%D8%A9-%D8%A7%D9%84%D8%B4%D9%83%D9%84%D9%8A%D8%A9-polymorphism-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r757" rel="">كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r755/" rel="">فهم متغيرات الأصناف والنسخ في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">756</guid><pubDate>Sat, 09 Nov 2019 14:03:00 +0000</pubDate></item><item><title>&#x641;&#x647;&#x645; &#x645;&#x62A;&#x63A;&#x64A;&#x631;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x635;&#x646;&#x627;&#x641; &#x648;&#x627;&#x644;&#x646;&#x633;&#x62E; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r755/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01e17ab98d_-----.jpg.6750ff560405dcb51c3952d74153c1a8.jpg" /></p>

<p>
	تسمح البرمجة الكائنية باستخدام متغيرات على مستوى الصنف، أو على مستوى النسخة (instance). المتغيرات هي رموز (symbols) تدل على قيمة تستخدمها في برنامجك.
</p>

<p>
	يشار إلى المتغيرات على مستوى الصنف باسم متغيرات الصنف (class variables)، في حين تسمى المتغيرات الموجودة على مستوى النسخة متغيرات النسخة (instance variables).
</p>

<p>
	إذا توقعت أن يكون المتغير متسقًا في جميع نسخ الصنف، أو عندما تود تهيئة المتغير، فالأفضل أن تُعرِّف ذلك المتغير على مستوى الصنف. أما إن كنت تعلم أن المتغير سيختلف من نسخة إلى أخرى، فالأفضل أن تعرفه على مستوى النسخة.
</p>

<p>
	يسعى أحد مبادئ تطوير البرمجيات هو مبدأ DRY (اختصارًا للعبارة don’t repeat yourself، والذي يعني لا تكرر نفسك) إلى الحد من التكرار في الشيفرة. أي تلتزم البرمجة الكائنية بمبدأ DRY على تقليل التكرار في الشيفرة.
</p>

<p>
	ستتعلم في هذا الدرس كيفية استخدام متغيرات الصنف والنسخة في البرمجة الكائنية في بايثون.
</p>

<h2>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32144" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db01e19c7611_-----.jpg.ae8040190d05216d0785a86b5273cce4.jpg" rel=""><img alt="فـهــم-متغيـــرات-الأصناف-والنسخ-فـــي-بـــايـثــــون.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32144" data-unique="7tts8fc86" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01e19dc5ad_-----.thumb.jpg.bc548e72f60ea8c2d77ddf53cb79f8b5.jpg"></a>
</h2>

<h2>
	متغيرات الصنف
</h2>

<p>
	تٌعرَّف متغيرات الصنف داخل الصنف وخارج كل توابعه وعادةً ما توضع مباشرة أسفل ترويسة الصنف، وقبل الباني (constructor) والتوابع الأخرى. ولمَّا كانت مملوكة للصنف نفسه، فستُشارَك مع جميع نُسَخ ذلك الصنف. وبالتالي، سيكون لها نفس القيمة بغض النظر عن النسخة، إلا إن كنت ستستخدم متغير الصنف لتهيئة متغير معيَّن.
</p>

<p>
	متغير الصنف يبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_6" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    animal_type </span><span class="pun">=</span><span class="pln"> </span><span class="str">"fish"</span></pre>

<p>
	في الشيفرة أعلاه أحلنا القيمة "<code>fish</code>" إلى المتغير <code>animal_type</code>.
</p>

<p>
	يمكننا <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754/" rel="">إنشاء نسخة من الصنف</a> Shark (سنطلق عليها <code>new_shark</code>)، ونطبع المتغير باستخدام الصياغة النقطية (dot notation):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_8" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    animal_type </span><span class="pun">=</span><span class="pln"> </span><span class="str">"fish"</span><span class="pln">

new_shark </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">animal_type</span><span class="pun">)</span></pre>

<p>
	لننفذ البرنامج:
</p>

<pre class="ipsCode">
python shark.py
</pre>

<p>
	سيعيد البرنامج قيمة المتغير:
</p>

<pre class="ipsCode">
fish
</pre>

<p>
	دعنا نضيف مزيدًا من متغيرات الصنف، ونطبعها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_10" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    animal_type </span><span class="pun">=</span><span class="pln"> </span><span class="str">"fish"</span><span class="pln">
    location </span><span class="pun">=</span><span class="pln"> </span><span class="str">"ocean"</span><span class="pln">
    followers </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">

new_shark </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">animal_type</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">location</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">followers</span><span class="pun">)</span></pre>

<p>
	يمكن أن تتألف متغيرات الصنف من أي <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r720/" rel="">نوع من البيانات المتاحة في بايثون</a> تمامًا مثل أي متغير آخر. استخدمنا في هذا البرنامج <a href="https://wiki.hsoub.com/Python/str" rel="external">السلاسل النصية</a> <a href="https://wiki.hsoub.com/Python/int" rel="external">والأعداد الصحيحة</a>. لننفذ البرنامج مرة أخرى باستخدام الأمر <code>python shark.py</code> ونرى المخرجات:
</p>

<pre class="ipsCode">
fish
ocean
5
</pre>

<p>
	يمكن للنسخة <code>new_shark</code> الوصول إلى جميع متغيرات الصنف وطباعتها عند تنفيذ البرنامج.
</p>

<p>
	تُنشَأ متغيرات الصنف عند إنشاء الصنف مباشرةً (وليس عند إنشاء نسخة منه) وتحتل موضعًا لها في الذاكرة ويمكن لأي كائن مُشتَق (نسخة) من الصنف نفسه أن يصل إليها ويقرأ قيمتها.
</p>

<h2>
	متغيرات النسخة
</h2>

<p>
	تختلف متغيرات النسخة عن متغيرات الصنف أن النسخة المشتقة من الصنف هي من تملكها وليس الصنف نفسه أي تكون على مستوى النسخة وسيُنشَأ متغير مستقل في الذاكرة عند إنشاء كل نسخة. هذا يعني أنّ متغيرات النسخة ستختلف من كائن إلى آخر.
</p>

<p>
	تُعرَّف متغيرات النسخة ضمن التوابع على خلاف متغيرات الصنف. في مثال الصنف <code>Shark</code> أدناه، عّرفنا متغيري النسخة <code>name</code> و <code>age</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_12" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age</span></pre>

<p>
	عندما ننشئ كائنًا من الصنف Shark، سيتعيّن علينا تعريف هذه المتغيرات، عبر تمريرها كمعاملات ضمن الباني (constructor)، أو أي تابع آخر.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_14" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age

new_shark </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span></pre>

<p>
	كما هو الحال مع متغيرات الأصناف، يمكننا بالمثل طباعة متغيرات النسخة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_16" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age

new_shark </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ البرنامج أعلاه باستخدام <code>python shark.py</code>، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Sammy
5
</pre>

<p>
	تتألف المخرجات التي حصلنا عليها من قيم المتغيرات التي هيّأناها لأجل الكائن <code>new_shark</code>.
</p>

<p>
	لننشئ كائنًا آخر من الصنف <code>Shark</code> يسمى <code>stevie</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_18" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age

new_shark </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">new_shark</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln">

stevie </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Stevie"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">stevie</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">stevie</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span></pre>

<p>
	يمرِّر الكائن <code>stevie</code> المعاملات إلى الباني لتعيين قيم متغيرات النسخة الخاصة به.
</p>

<p>
	تسمح متغيرات النسخة، المملوكة لكائنات الصنف، لكل كائن أو نسخة أن تكون لها متغيرات خاصة بها ذات قيم مختلفة عن بعضها بعضًا.
</p>

<h2>
	العمل مع متغيرات الصنف والنسخة معًا
</h2>

<p>
	غالبًا ما تُستخدم متغيرات الصنف ومتغيرات النسخة في نفس الشيفرة، ويوضح المثال التالي يستخدم الصنف <code>Shark</code> الذي أنشأناه سابقًا هذا الأمر. تشرح التعليقات في البرنامج كل خطوة من خطوات العملية.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4839_20" style="">
<span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">

    </span><span class="com"># متغيرات الصنف</span><span class="pln">
    animal_type </span><span class="pun">=</span><span class="pln"> </span><span class="str">"fish"</span><span class="pln">
    location </span><span class="pun">=</span><span class="pln"> </span><span class="str">"ocean"</span><span class="pln">

    </span><span class="com"># name و age باني مع متغيري النسخة </span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age

    </span><span class="com"># followers تابع مع متغير النسخة </span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> set_followers</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This user has "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">" followers"</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    </span><span class="com"># الكائن الأول، إعداد متغيرات النسخة في الباني</span><span class="pln">
    sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># name طباعة متغير النسخة </span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># location طباعة متغير الصنف </span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sammy</span><span class="pun">.</span><span class="pln">location</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># الكائن الثاني</span><span class="pln">
    stevie </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Stevie"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># name طباعة متغير النسخة </span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">stevie</span><span class="pun">.</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># followers لتمرير متغير النسخة set_followers استخدام التابع</span><span class="pln">
    stevie</span><span class="pun">.</span><span class="pln">set_followers</span><span class="pun">(</span><span class="lit">77</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># animal_type طباعة متغير الصنف </span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">stevie</span><span class="pun">.</span><span class="pln">animal_type</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">"__main__"</span><span class="pun">:</span><span class="pln">
    main</span><span class="pun">()</span></pre>

<p>
	عند تنفيذ البرنامج باستخدام <code>python shark.py</code>، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">
Sammy
ocean
Stevie
This user has 77 followers
fish
</pre>

<h2>
	خلاصة
</h2>

<p>
	في البرمجة الكائنية، يشار إلى المتغيرات المُعرَّفة على مستوى الصنف بمتغيرات الصنف، في حين تسمى المتغيرات المُعرّفة على مستوى الكائن بمتغيرات النسخة.
</p>

<p>
	يتيح لنا هذا التمييز استخدام متغيرات ذات قيم واحدة بينها عبر متغيرات الصنف، أو استخدام متغيرات مختلفة لكل كائن على حدة عبر متغيرات النسخة. كما يضمن استخدام المتغيرات الخاصة بالصنف أو النسخة أن تكون الشيفرة متوافقة مع مبدأ DRY.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/understanding-class-and-instance-variables-in-python-3" rel="external nofollow">Understanding Class and Instance Variables in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%B1%D8%A7%D8%AB%D8%A9-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r756" rel="">وراثة الأصناف في بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754/" rel="">كيفية إنشاء الأصناف وتعريف الكائنات في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">755</guid><pubDate>Wed, 06 Nov 2019 14:08:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x627;&#x644;&#x623;&#x635;&#x646;&#x627;&#x641; &#x648;&#x62A;&#x639;&#x631;&#x64A;&#x641; &#x627;&#x644;&#x643;&#x627;&#x626;&#x646;&#x627;&#x62A; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01c7a8e128_----.jpg.705dd6dffec03dce9a2e87a0a6552a6f.jpg" /></p>
<p>
	بايثون لغةٌ برمجة كائنية (object-oriented programming language). تركز البرمجة الكائنية (<abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr>) على كتابة شيفرات قابلة لإعادة الاستخدام، على عكس <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%A5%D8%AC%D8%B1%D8%A7%D8%A6%D9%8A%D8%A9/" rel="">البرمجة الإجرائية</a> (procedural programming) التي تركز على كتابة تعليمات صريحة ومتسلسلة.
</p>

<p>
	تتيح البرمجة الكائنية لمبرمجي بايثون كتابة شيفرات سهلة القراءة والصيانة، وهذا مفيد للغاية عند تطوير البرامج المُعقَّدة.
</p>

<p>
	التمييز بين الأصناف والكائنات أحدُ المفاهيم الأساسية في البرمجة الكائنية، ويوضح التعريفان التاليان الفرق بين المفهومين:
</p>

<ul>
	<li>
		<strong>الصنف</strong> - نموذج عام تُنسج على منواله كائنات يُنشِئها المبرمج. يُعرِّف الصنف مجموعةً من الخاصيات التي تميز أي كائن يُستنسَخ (instantiated) منه.
	</li>
	<li>
		<strong>الكائن</strong> - نسخةٌ (instance) من الصنف، فهو تجسيد عملي للصنف داخل البرنامج.
	</li>
</ul>

<p>
	تُستخدَم الأصناف لإنشاء أنماط، ثم تُستعمَل تلك الأنماط لإنشاء كائنات منها.
</p>

<p>
	ستتعلم في هذا الدرس كيفيَّة إنشاء الأصناف والكائنات، وتهيئة الخاصيات باستخدام تابعٍ بانٍ (constructor method)، والعمل على أكثر من كائن من نفس الصنف.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32143" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db01c76ed324_----.jpg.d15f273e21363ea6567fb6459c1ec4ea.jpg" rel="" data-fileext="jpg"><img alt="كيفية-إنشاء-الأصناف-وتـعــريـــف-الكـائـنــــات.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32143" data-unique="h6ephiulj" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01c770e706_----.thumb.jpg.6366611db60b1d1b24e097ce74edf8c8.jpg"></a>
</p>

<h2>
	الأصناف
</h2>

<p>
	الأصناف هي نماذج عامة تُستخدم لإنشاء كائنات وسبق أن عرَّفناها آنفًا.
</p>

<p>
	تُنشَأ الأصناف باستخدام الكلمة المفتاحية <code>‎class‎</code>، بشكل مشابه [لتعريف الدوال](رابط المقالة 34) الذي يكون باستخدام الكلمة المفتاحية <code>‎def‎</code>.
</p>

<p>
	دعنا نعرّف صنفًا يسمى <code>‎Shark‎</code>، ونجعل له تابعين مرتبطين به، <code>swim</code> و <code>be_awesome</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_6" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The shark is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> be_awesome</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The shark is being awesome."</span><span class="pun">)</span></pre>

<p>
	تُسمَّى مثل هذه الدوال «<strong>توابعًا</strong>» (methods) لأنهما معرفتان داخل الصنف <code>‎Shark‎</code>؛ أي أنهما دالتان تابعتان للصنف <code>‎Shark‎</code>.
</p>

<p>
	الوسيط الأول لهاتَين الدالتين هو <code>‎self‎</code>، وهو مرجع إلى الكائنات التي يتم بناؤها من هذا الصنف. للإشارة إلى نُسخ (أو كائنات) من الصنف، يوضع <code>‎self‎</code> دائمًا في البداية، لكن يمكن أن تكون معه وسائط أخرى.
</p>

<p>
	لا يؤدي تعريف الصنف <code>‎Shark‎</code> إلى إنشاء كائنات منه، وإنما يعرّف فقط النمط العام لتلك الكائنات، والتي يمكننا تعريفها لاحقًا. لذا، إذا نفّذت البرنامج أعلاه الآن، فلن يُعاد أي شيء.
</p>

<h2>
	الكائنات
</h2>

<p>
	الكائن هو نسخةٌ (instance) من صنف. ويمكن أن نأخذ الصنف <code>‎Shark‎</code> المُعرَّف أعلاه، ونستخدمه لإنشاء كائن يعدُّ نسخةً منه.
</p>

<p>
	سننشئ كائنًا <code>‎Shark‎</code> يسمى <code>‎sammy‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_8" style=""><span class="pln">sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span></pre>

<p>
	لقد أحلنا على الكائن <code>‎sammy‎</code> ناتج الباني <code>‎Shark()‎</code>، والذي يعيد نسخةً من الصنف.
</p>

<p>
	سنستخدم في الشيفرة التالية التابعين الخاصين بالكائن <code>‎sammy‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_10" style=""><span class="pln">sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">
sammy</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
sammy</span><span class="pun">.</span><span class="pln">be_awesome</span><span class="pun">()</span></pre>

<p>
	يستخدم الكائن <code>‎sammy‎</code> التابعين <code>‎swim()‎</code> و <code>‎be_awesome()‎</code>، وقد استدعينَاهما باستعمال المعامل النقطي (<code>‎.‎</code>)، والذي يُستخدم للإشارة إلى خاصيات أو توابع الكائنات. في هذه الحالة، استدعينا تابعًا، لذلك استعملنا قوسين مثلما نفعل عند استدعاء دالة.
</p>

<p>
	الكلمة <code>‎self‎</code> هي معامل يُمرّر إلى توابع الصنف <code>‎Shark‎</code>، في المثال أعلاه، يمثّل <code>‎self‎</code> الكائن <code>‎sammy‎</code>. يتيح المعامل <code>‎self‎</code> للتوابع الوصول إلى خاصيات الكائن الذي استُدعيت معه.
</p>

<p>
	لاحظ أننا لم نمرر شيئًا داخل القوسين عند استدعاء التابع أعلاه، ذلك أنّ الكائن <code>‎sammy‎</code> يُمرّر تلقائيًا مع العامل النقطي.
</p>

<p>
	البرنامج التالي يوضح لنا الأمر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_12" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The shark is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> be_awesome</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The shark is being awesome."</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">()</span><span class="pln">
    sammy</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
    sammy</span><span class="pun">.</span><span class="pln">be_awesome</span><span class="pun">()</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">"__main__"</span><span class="pun">:</span><span class="pln">
    main</span><span class="pun">()</span></pre>

<p>
	لننفذ البرنامج لنرى ما سيحدث:
</p>

<pre class="ipsCode">python shark.py
</pre>

<p>
	ستُطبع المخرجات التالية:
</p>

<pre class="ipsCode">The shark is swimming.
The shark is being awesome.
</pre>

<p>
	في الشيفرة أعلاه، استدعى الكائن <code>‎sammy‎</code> التابعين <code>‎swim()‎</code> و <code>‎be_awesome()‎</code> في الدالة الرئيسية <code>‎main()‎</code>.
</p>

<h2>
	الباني
</h2>

<p>
	يٌستخدم الباني (Constructor Method) لتهيئة البيانات الأولية، ويُنفَّذ لحظة إنشاء الكائن. في تعريف الصنف، يأخذ الباني الاسم <code>‎__init__‎</code>، وهو أول تابع يُعرّف في الصنف، ويبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_15" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This is the constructor method."</span><span class="pun">)</span></pre>

<p>
	إذا أضفت التابع <code>‎__init__‎</code> إلى الصنف <code>‎Shark‎</code> في البرنامج أعلاه، فسيَطبع البرنامجُ المخرجات التالية:
</p>

<pre class="ipsCode">This is the constructor method.
The shark is swimming.
The shark is being awesome.
</pre>

<p>
	يُنفَّذ الباني تلقائيًا، لذا يستخدمه مطورو بايثون لتهيئة أصنافهم.
</p>

<p>
	سنُعدِّل الباني أعلاه، ونجعله يستخدم متغيرًا اسمه <code>‎name‎</code> سيمثّل اسم الكائن. في الشيفرة التالية، سيكون المتغير <code>‎name‎</code> المعامل المُمرَّر إلى الباني، ونحيل قيمته إلى الخاصية <code>‎self.name‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_17" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name</span></pre>

<p>
	بعد ذلك، يمكننا تعديل <a href="https://wiki.hsoub.com/Python/str" rel="external">السلاسل النصية</a> في دوالنا للإشارة إلى اسم الصنف، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_19" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name

    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="com"># الإشارة إلى الاسم</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> be_awesome</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="com"># الإشارة إلى الاسم</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is being awesome."</span><span class="pun">)</span></pre>

<p>
	أخيرًا، يمكننا تعيين اسم الكائن <code>‎sammy‎</code> عند القيمة <code>‎"Sammy"‎</code> (أي قيمة الخاصية <code>name</code>) بتمريره إلى <code>‎Shark()‎</code> عند إنشائه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_21" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name

    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> be_awesome</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is being awesome."</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    </span><span class="com"># Shark تعيين اسم كائن</span><span class="pln">
    sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">)</span><span class="pln">
    sammy</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">
    sammy</span><span class="pun">.</span><span class="pln">be_awesome</span><span class="pun">()</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">"__main__"</span><span class="pun">:</span><span class="pln">
    main</span><span class="pun">()</span></pre>

<p>
	عرّفنا التابع <code>‎__init__‎</code>، والذي يقبل مُعاملين <code>‎self‎</code> و <code>name</code> (تذكر أن المعامل <code>‎self‎</code> يُمرر تلقائيا إلى التابع)، ثم عرّفنا متغيرًا فيه.
</p>

<p>
	عند تنفيذ البرنامج:
</p>

<pre class="ipsCode">python shark.py
</pre>

<p>
	سنحصل على:
</p>

<pre class="ipsCode">Sammy is swimming.
Sammy is being awesome.
</pre>

<p>
	لقد طُبع الاسم الذي مرّرناه إلى الكائن. ونظرًا لأنّ الباني يُنفّذ تلقائيًا، فلست بحاجة إلى استدعائه بشكل صريح، فيكفي تمرير الوسائط بين القوسين التاليين لاسم الصنف عند إنشاء نسخة جديدة منه.
</p>

<p>
	إذا أردت إضافة معامل آخر، مثل <code>‎age‎</code>، فيمكن ذلك عبر تمريره إلى التابع <code>‎__init__‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_23" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> age</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name
        self</span><span class="pun">.</span><span class="pln">age </span><span class="pun">=</span><span class="pln"> age</span></pre>

<p>
	عند إنشاء الكائن <code>‎sammy‎</code>، سنمرر عُمره أيضًا بالإضافة إلى اسمه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_25" style=""><span class="pln">sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span></pre>

<p>
	إذًا، تتيح البانيات تهيئة خاصيات الكائن لحظة إنشائه.
</p>

<h2>
	العمل مع عدة كائنات
</h2>

<p>
	تتيح لنا الأصناف إنشاء العديد من الكائنات المتماثلة التي تتبع نفس النمط. لتفهم ذلك بشكل أفضل، دعنا نضيف كائنًا آخر من الصنف <code>‎Shark‎</code> إلى برنامجنا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8743_27" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> name</span><span class="pun">):</span><span class="pln">
        self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">=</span><span class="pln"> name

    </span><span class="kwd">def</span><span class="pln"> swim</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is swimming."</span><span class="pun">)</span><span class="pln">

    </span><span class="kwd">def</span><span class="pln"> be_awesome</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">name </span><span class="pun">+</span><span class="pln"> </span><span class="str">" is being awesome."</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    sammy </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">)</span><span class="pln">
    sammy</span><span class="pun">.</span><span class="pln">be_awesome</span><span class="pun">()</span><span class="pln">
    stevie </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Shark</span><span class="pun">(</span><span class="str">"Stevie"</span><span class="pun">)</span><span class="pln">
    stevie</span><span class="pun">.</span><span class="pln">swim</span><span class="pun">()</span><span class="pln">

</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">"__main__"</span><span class="pun">:</span><span class="pln">
  main</span><span class="pun">()</span></pre>

<p>
	لقد أنشأنا كائنًا ثانيًا من الصنف <code>‎Shark‎</code> يسمى <code>‎stevie‎</code>، ومرّرنا إليه الاسم <code>‎"Stevie"‎</code>. في هذا المثال، استدعينا التابع <code>‎be_awesome()‎</code> مع الكائن <code>‎sammy‎</code>، والتابع <code>‎swim()‎</code> مع الكائن <code>‎stevie‎</code>.
</p>

<p>
	لننفذ البرنامج:
</p>

<pre class="ipsCode">python shark.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">Sammy is being awesome.
Stevie is swimming.
</pre>

<p>
	يبدو ظاهرًا في المخرجات أننا نستخدم كائنين مختلفين، الكائن <code>‎sammy‎</code> والكائن <code>‎stevie‎</code>، وكلاهما من الصنف <code>‎Shark‎</code>.
</p>

<p>
	تتيح لنا الأصناف إنشاء عدة كائنات تتبع كلها نفس النمط دون الحاجة إلى بناء كل واحد منها من البداية.
</p>

<h2>
	خلاصة
</h2>

<p>
	تطرَّقنا في هذا الدرس إلى عِدَّة مفاهيم، مثل إنشاء الأصناف، وإنشاء الكائنات، وتهيئة الخاصيات باستخدام البانيات، والعمل مع أكثر من كائن من نفس الصنف.
</p>

<p>
	تُعدُّ البرمجة الكائنية أحد المفاهيم الضرورية التي ينبغي أن يتعلمها كل مبرمجي بايثون، لأنها تساعد على كتابة شيفرات قابلة لإعادة الاستخدام، إذ أنَّ الكائنات التي تُنشَأ في برنامج ما يمكن استخدامها في برامج أخرى. كما أنّ البرامج الكائنية عادة ما تكون أوضح وأكثر مقروئية، خصوصًا في البرامج المعقدة التي تتطلب تخطيطًا دقيقًا، وهذا بدوره يسهل صيانة البرامج مستقبلًا.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-construct-classes-and-define-objects-in-python-3" rel="external nofollow">How To Construct Classes and Define Objects in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%A7%D9%84%D9%86%D8%B3%D8%AE-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r755" rel="">فهم متغيرات الأصناف والنسخ في بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-args-%D9%88-kwargs-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r753/" rel="">كيفية استخدام ‎<em>args و ‎</em>*kwargs في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">754</guid><pubDate>Sat, 02 Nov 2019 14:04:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; args* &#x648; kwargs** &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-args-%D9%88-kwargs-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r753/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01aee1c398_--args--kwargs.jpg.9df089101cb4379c937972de29c98e9e.jpg" /></p>
<p>
	تعدُّ المعاملات في <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/" rel="">تعاريف الدوال</a> كيانات مسماة تُحدِّد وسيطًا (argument) يمكن أن يُمرَّر إلى الدالة المُعرَّفة.
</p>

<p>
	أثناء البرمجة، قد لا تدرك جميع حالات الاستخدام الممكنة للشيفرة، لذا قد ترغب في توسيع خيارات المبرمجين المستقبليين الذين سيستخدمون الوحدة التي طورتها.
</p>

<p>
	سنتعلم في هذا الدرس كيفيَّة تمرير عدد متغير من الوسائط إلى دالة ما باستخدام الصياغتين <code>‎*args‎</code> و <code>‎**kwargs‎</code>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32142" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db01ae94d1b7_--args--kwargs.jpg.c79b9931046b550c3df025bbaf265046.jpg" rel="" data-fileext="jpg"><img alt="كـيـفـيـــة-اسـتـخــــدام-args-و-kwargs.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32142" data-unique="ak4eda8o4" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db01ae962b91_--args--kwargs.thumb.jpg.cc7dbf7b6dd869fa580d2db247dc2984.jpg"></a>
</p>

<h2>
	<code>الوسيط ‎*args</code>
</h2>

<p>
	في بايثون، يمكن استخدام الشكل أحادي النجمة <code>‎*args‎</code> كمعامل لتمرير قائمة غير محددة الطول من الوسائط غير المسماة (non-keyworded argument) إلى الدوال. تجدر الإشارة إلى أنّ النجمة (<code>‎*‎</code>) عنصر ضروري هنا، إذ رغم أنّ الكلمة <code>‎args‎</code> متعارف عليها بين المبرمجين، إلا أنها غير رسمية.
</p>

<p>
	لنلقِ نظرة على مثال لدالة تستخدم وسيطين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_6" style=""><span class="kwd">def</span><span class="pln"> multiply</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> y</span><span class="pun">)</span></pre>

<p>
	عرّفنا في الشفرة أعلاه دالة تقبل وسيطين <code>‎x‎</code> و <code>‎y‎</code>، عندما نستدعي هذه الدالة، سنحتاج إلى تمرير عددين موافقين للوسيطين <code>‎x‎</code> و <code>‎y‎</code>. في هذا المثال، سنمرّر العدد الصحيح <code>‎5‎</code> إلى <code>‎x‎</code>، والعدد الصحيح <code>‎4‎</code> إلى <code>‎y‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_8" style=""><span class="kwd">def</span><span class="pln"> multiply</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">

multiply</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ الشفرة أعلاه:
</p>

<pre class="ipsCode">python lets_multiply.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">20
</pre>

<p>
	ماذا لو قررنا لاحقًا أننا نود حساب ناتج ضرب ثلاثة أعداد بدلًا من عددين فقط؟ إذا حاولت تمرير عدد إضافي إلى الدالة، كما هو موضح أدناه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_10" style=""><span class="kwd">def</span><span class="pln"> multiply</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">

multiply</span><span class="pun">(</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	فسيُطلَق الخطأ التالي:
</p>

<pre class="ipsCode">TypeError: multiply() takes 2 positional arguments but 3 were given
</pre>

<p>
	إذا شككت أنك ستحتاج إلى استخدام المزيد من الوسائط لاحقًا، فالحل هو استخدام <code>‎*args‎</code> كمعامل.
</p>

<p>
	سنزيل المُعاملين <code>‎x‎</code> و <code>‎y‎</code> من الشفرة في المثال الأول، ونضع مكانهما <code>‎*args‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_12" style=""><span class="kwd">def</span><span class="pln"> multiply</span><span class="pun">(*</span><span class="pln">args</span><span class="pun">):</span><span class="pln">
    z </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> num </span><span class="kwd">in</span><span class="pln"> args</span><span class="pun">:</span><span class="pln">
        z </span><span class="pun">*=</span><span class="pln"> num
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">z</span><span class="pun">)</span><span class="pln">

multiply</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
multiply</span><span class="pun">(</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">)</span><span class="pln">
multiply</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln">
multiply</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">)</span></pre>

<p>
	عندما ننفّذ هذه الشفرة، سنحصل على ناتج استدعاءات الدالة أعلاه:
</p>

<pre class="ipsCode">20
90
24
900
</pre>

<p>
	يمكننا باستخدام الوسيط <code>‎*args‎</code> تمرير أي عدد نحب من الوسائط عند استدعاء الدالة بالإضافة إلى كتابة شيفرة أكثر مرونة، وإنشاء دوال تقبل عددًا غير محدد مسبقًا من الوسائط غير المسماة.
</p>

<h2>
	<code>الوسيط ‎**kwargs</code>
</h2>

<p>
	يُستخدَم الشكل ذو النجمتين <code>‎**kwargs‎</code> لتمرير <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D9%85%D9%8A%D8%B3-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r743/" rel="">قاموس</a> متغير الطول من الوسائط المسماة إلى الدالة المعرّفة. مرة أخرى، النجمتان (<code>‎**‎</code>) ضروريتان، فمع أنّ استخدام الكلمة <code>‎kwargs‎</code> متعارف عليه لدى المبرمجين، إلا أنها غير رسمية.
</p>

<p>
	يمكن أن تأخذ <code>‎**kwargs‎</code>، كما هو شأن <code>‎*args‎</code>، أيّ عدد من الوسائط التي ترغب في تمريرها إلى الدالة بيْد أنّ <code>‎**kwargs‎</code> تختلف عن <code>‎*args‎</code> في أنها تستوجب تعيين أسماء المعاملات (keywords).
</p>

<p>
	في المثال التالي، ستطبع الدالة الوسيط <code>‎**kwargs‎</code> الممرر إليها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_14" style=""><span class="kwd">def</span><span class="pln"> print_kwargs</span><span class="pun">(**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">kwargs</span><span class="pun">)</span></pre>

<p>
	سنستدعي الآن الدالة ونمرر إليها بعض الوسائط المسماة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_16" style=""><span class="kwd">def</span><span class="pln"> print_kwargs</span><span class="pun">(**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">kwargs</span><span class="pun">)</span><span class="pln">

print_kwargs</span><span class="pun">(</span><span class="pln">kwargs_1</span><span class="pun">=</span><span class="str">"Shark"</span><span class="pun">,</span><span class="pln"> kwargs_2</span><span class="pun">=</span><span class="lit">4.5</span><span class="pun">,</span><span class="pln"> kwargs_3</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span></pre>

<p>
	لننفذ البرنامج أعلاه:
</p>

<pre class="ipsCode">python print_kwargs.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">{'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark'}
</pre>

<p>
	اعتمادًا على إصدار بايثون 3 الذي تستخدمه، فقد لا يكون القاموس مرتبًا. في بايثون 3.6 وما بعده، ستحصل على أزواج قيمة-مفتاح (key-value) مرتبة، ولكن في الإصدارات السابقة، سيكون ترتيب الأزواج عشوائيًا.
</p>

<p>
	سيُنشَأ قاموس يسمى <code>‎kwargs‎</code>، والذي يمكننا التعامل معه مثل أي قاموس عادي داخل الدالة.
</p>

<p>
	لننشئ برنامجًا آخر لإظهار كيفية استخدام <code>‎**kwargs‎</code>. سننشئ دالة تطبع قاموسًا من الأسماء. أولاً، سنبدأ بقاموس يحتوي اسمين:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_18" style=""><span class="kwd">def</span><span class="pln"> print_values</span><span class="pun">(**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> value </span><span class="kwd">in</span><span class="pln"> kwargs</span><span class="pun">.</span><span class="pln">items</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The value of {} is {}"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">))</span><span class="pln">

print_values</span><span class="pun">(</span><span class="pln">my_name</span><span class="pun">=</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> your_name</span><span class="pun">=</span><span class="str">"Casey"</span><span class="pun">)</span></pre>

<p>
	بعد تنفيذ البرنامج:
</p>

<pre class="ipsCode">python print_values.py
</pre>

<p>
	سنحصل على مايلي:
</p>

<pre class="ipsCode">The value of your_name is Casey
The value of my_name is Sammy
</pre>

<p>
	قد لا تكون القواميس مرتَّبة، لذلك قد يظهر الاسم <code>‎Casey‎</code> أولاً، وقد يظهر ثانيًا.
</p>

<p>
	سنمرر الآن وسائط إضافية إلى الدالة لنرى كيف يمكن أن تقبل <code>‎**kwargs‎</code> أيّ عدد من الوسائط:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_20" style=""><span class="kwd">def</span><span class="pln"> print_values</span><span class="pun">(**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> key</span><span class="pun">,</span><span class="pln"> value </span><span class="kwd">in</span><span class="pln"> kwargs</span><span class="pun">.</span><span class="pln">items</span><span class="pun">():</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"The value of {} is {}"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">))</span><span class="pln">

print_values</span><span class="pun">(</span><span class="pln">
            name_1</span><span class="pun">=</span><span class="str">"Alex"</span><span class="pun">,</span><span class="pln">
            name_2</span><span class="pun">=</span><span class="str">"Gray"</span><span class="pun">,</span><span class="pln">
            name_3</span><span class="pun">=</span><span class="str">"Harper"</span><span class="pun">,</span><span class="pln">
            name_4</span><span class="pun">=</span><span class="str">"Phoenix"</span><span class="pun">,</span><span class="pln">
            name_5</span><span class="pun">=</span><span class="str">"Remy"</span><span class="pun">,</span><span class="pln">
            name_6</span><span class="pun">=</span><span class="str">"Val"</span><span class="pln">
        </span><span class="pun">)</span></pre>

<p>
	إذا نفّذنا البرنامج الآن، فسنحصل على المخرجات التالية، والتي قد تكون غير مرتبة:
</p>

<pre class="ipsCode">The value of name_2 is Gray
The value of name_6 is Val
The value of name_4 is Phoenix
The value of name_5 is Remy
The value of name_3 is Harper
The value of name_1 is Alex
</pre>

<p>
	يتيح لك استخدام <code>‎**kwargs‎</code> مرونةً كبيرةً في استخدام الوسائط المسماة. فعند استخدامها، لن نحتاج إلى معرفة مسبقة بعدد الوسائط التي ستمرر إلى الدالة.
</p>

<h2>
	ترتيب الوسائط
</h2>

<p>
	عند الخلط بين عدة أنواع من الوسائط داخل دالة، أو داخل استدعاء دالة، يجب أن تظهر الوسائط وفق الترتيب التالي:
</p>

<ul>
	<li>
		الوسائط العادية
	</li>
	<li>
		<code>‎*args‎</code>
	</li>
	<li>
		الوسائط المسمّاة
	</li>
	<li>
		<code>‎**kwargs‎</code>
	</li>
</ul>

<p>
	عمليًا، عند الجمع بين المعاملات العادية، والوسيطين <code>‎*args‎</code> و <code>‎**kwargs‎</code>، فينبغي أن تكون وفق الترتيب التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_22" style=""><span class="kwd">def</span><span class="pln"> example</span><span class="pun">(</span><span class="pln">arg_1</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">args</span><span class="pun">,</span><span class="pln"> </span><span class="pun">**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	وعند الجمع بين المعاملات العادية والمعاملات المسماة و <code>‎*args‎</code> و <code>‎**kwargs‎</code>، ينبغي أن تكون وفق الترتيب التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_24" style=""><span class="kwd">def</span><span class="pln"> example2</span><span class="pun">(</span><span class="pln">arg_1</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">args</span><span class="pun">,</span><span class="pln"> kw_1</span><span class="pun">=</span><span class="str">"shark"</span><span class="pun">,</span><span class="pln"> kw_2</span><span class="pun">=</span><span class="str">"blobfish"</span><span class="pun">,</span><span class="pln"> </span><span class="pun">**</span><span class="pln">kwargs</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	من المهم أن تأخذ في الحسبان ترتيب الوسائط عند إنشاء الدوال حتى لا تتسبب في إطلاق خطأٍ متعلقٍ بالصياغة.
</p>

<h2>
	استخدام <code>‎*args</code> و <code>‎**kwargs</code> في استدعاءات الدوال
</h2>

<p>
	يمكننا أيضًا استخدام <code>‎*args‎</code> و <code>‎**kwargs‎</code> لتمرير الوسائط إلى الدوال. أولاً، دعنا ننظر إلى مثال يستخدم <code>‎*args‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_26" style=""><span class="kwd">def</span><span class="pln"> some_args</span><span class="pun">(</span><span class="pln">arg_1</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">,</span><span class="pln"> arg_3</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_1:"</span><span class="pun">,</span><span class="pln"> arg_1</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_2:"</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_3:"</span><span class="pun">,</span><span class="pln"> arg_3</span><span class="pun">)</span><span class="pln">

args </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">"Sammy"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Casey"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Alex"</span><span class="pun">)</span><span class="pln">
some_args</span><span class="pun">(*</span><span class="pln">args</span><span class="pun">)</span></pre>

<p>
	في الدالة أعلاه، هناك ثلاثة معاملات، وهي <code>‎arg_1‎</code> و <code>‎arg_‎</code> و <code>‎arg_3‎</code>. ستطبع الدالة كل هذه الوسائط. بعد ذلك أنشأنا متغيرًا، وأَحلنا عليه عنصرًا تكراريًا (في هذه الحالة، <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-tuples-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r507/" rel="">صف</a>)، ثم مرَّرنا ذلك المتغير إلى الدالة باستخدام الصياغة النجمية (asterisk syntax).
</p>

<p>
	عندما ننفّذ البرنامج باستخدام الأمر <code>‎python some_args.py‎</code>، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">arg_1: Sammy
arg_2: Casey
arg_3: Alex
</pre>

<p>
	يمكننا أيضًا تعديل البرنامج أعلاه، واستخدام <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%A6%D9%85-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r733/" rel="">قائمة</a>. سندمج أيضًا <code>‎*args‎</code> مع <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/" rel="">وسيط مسمى</a>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_28" style=""><span class="kwd">def</span><span class="pln"> some_args</span><span class="pun">(</span><span class="pln">arg_1</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">,</span><span class="pln"> arg_3</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_1:"</span><span class="pun">,</span><span class="pln"> arg_1</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_2:"</span><span class="pun">,</span><span class="pln"> arg_2</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"arg_3:"</span><span class="pun">,</span><span class="pln"> arg_3</span><span class="pun">)</span><span class="pln">

my_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">]</span><span class="pln">
some_args</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="pun">*</span><span class="pln">my_list</span><span class="pun">)</span></pre>

<p>
	إذا نفذنا البرنامج أعلاه، فسنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">arg_1: 1
arg_2: 2
arg_3: 3
</pre>

<p>
	وبالمثل، يمكن استخدام الوسائط المسماة <code>‎**kwargs‎</code> لاستدعاء دالة.
</p>

<p>
	سننشئ متغيرًا، ونسند إليه قاموسًا من 3 أزواج مفتاح-قيمة (سنستخدم <code>‎kwargs‎</code> هنا، ولكن يمكنك تسميته ما تشاء)، ثم نُمرِّره إلى دالة ذات 3 وسائط:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6470_30" style=""><span class="kwd">def</span><span class="pln"> some_kwargs</span><span class="pun">(</span><span class="pln">kwarg_1</span><span class="pun">,</span><span class="pln"> kwarg_2</span><span class="pun">,</span><span class="pln"> kwarg_3</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"kwarg_1:"</span><span class="pun">,</span><span class="pln"> kwarg_1</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"kwarg_2:"</span><span class="pun">,</span><span class="pln"> kwarg_2</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"kwarg_3:"</span><span class="pun">,</span><span class="pln"> kwarg_3</span><span class="pun">)</span><span class="pln">

kwargs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">"kwarg_1"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Val"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"kwarg_2"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Harper"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"kwarg_3"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"Remy"</span><span class="pun">}</span><span class="pln">
some_kwargs</span><span class="pun">(**</span><span class="pln">kwargs</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ البرنامج أعلاه باستخدام الأمر <code>‎python some_kwargs.py‎</code>، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">kwarg_1: Val
kwarg_2: Harper
kwarg_3: Remy
</pre>

<h2>
	خلاصة
</h2>

<p>
	يمكنك استخدام الصياغتين الخاصتين <code>‎*args‎</code> و <code>‎**kwargs‎</code> ضمن تَعاريف الدوال لتمرير أيّ عدد تشاء من الوسائط إليها.
</p>

<p>
	يُستحسن استخدام <code>‎*args‎</code> و <code>‎**kwargs‎</code> في المواقف التي تتوقع أن يظل فيها عدد المدخلات في قائمة الوسائط صغيرًا نسبيًا. وضع في ذهنك أن استخدام <code>‎*args‎</code> و <code>‎**kwargs‎</code> يحسِّن مقروئية الشيفرة، ويسهِّل على المبرمجين، ولكن ينبغي استخدامهما بحذر.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-args-and-kwargs-in-python-3" rel="external nofollow">How To Use *args and **kwargs in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%A7%D9%84%D8%A3%D8%B5%D9%86%D8%A7%D9%81-%D9%88%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r754" rel="">كيفية إنشاء الأصناف وتعريف الكائنات في بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/" rel="">كيفية تعريف الدوال في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">753</guid><pubDate>Wed, 30 Oct 2019 14:04:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x62A;&#x639;&#x631;&#x64A;&#x641; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db013a760f5e_.jpg.e7bbafc07bf1fcc3113191c4f22f56be.jpg" /></p>
<p>
	الدالة (funtion) هي كتلة من التعليمات التي تنفِّذ إجراءً ما، ويمكن، بعد تعريفها، إعادة استخدامها في أكثر من موضع. تجعل الدوال الشيفرة تركيبية (modular)، مما يسمح باستخدام نفس الشفرة مرارًا وتكرارًا.
</p>

<p>
	تضم بايثون عددًا من الدوال المُضمّنة الشائعة، مثل:
</p>

<ul>
	<li>
		<code>‎print()‎:</code> تطبع كائنًا في الطرفية.
	</li>
	<li>
		<code>‎int()‎:</code> تحوّل أنواع البيانات النصية أو العددية إلى أعداد صحيحة.
	</li>
	<li>
		<code>‎len()‎:</code> تعيد طول كائن، وغيرها من الدوال.
	</li>
</ul>

<p>
	تتضمن أسماء الدوال الأقواس، وقد تتضمن معاملات أيضًا.
</p>

<p>
	في هذا الدرس، سنتعلم كيفية تعريف الدوال، وكيفية استخدامها في البرامج.
</p>

<h2>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32140" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db013a9d96af_.jpg.e632fd86da5fe29fc0b278db1a168bf6.jpg" rel="" data-fileext="jpg"><img alt="كيفية تعريف الدوال.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32140" data-unique="2lvkurbip" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db013a9ee989_.thumb.jpg.1c0f085f81e8073ad76bc06493839f71.jpg"></a>
</h2>

<h2>
	تعريف الدالة
</h2>

<p>
	لنبدأ بتحويل البرنامج <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81-%D8%AA%D9%83%D8%AA%D8%A8-%D8%A3%D9%88%D9%84-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D8%AC-%D9%84%D9%83-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r715/" rel="">"مرحبًا بالعالم!"</a> إلى دالة. أنشئ ملفًا نصيًا جديدًا، وافتحه في محرر النصوص المفضل عندك، ثم استدع البرنامج <code>‎hello.py‎</code>.
</p>

<p>
	تُعرَّف الدالة باستخدام الكلمة المفتاحية <code>‎def‎</code>، متبوعة باسم من اختيارك، متبوعًا بقوسين يمكن أن يَحتويا المعاملات التي ستأخذها الدالة، ثم ينتهي التعريف بنقطتين.
</p>

<p>
	في هذه الحالة، سنعرّف دالة باسم <code>‎hello()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_6" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span></pre>

<p>
	في الشفرة أعلاه، أعددنا السطر الأول من تعريف الدالة.
</p>

<p>
	بعد هذا، سنضيف سطرًا ثانيًا مُزاحًا بأربع مسافات بيضاء، وفيه سنكتب التعليمات التي ستنفّذها الدالة. في هذه الحالة، سنطبع العبارة <code>مرحبا بالعالم</code> في سطر الأوامر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_8" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"مرحبا بالعالم"</span><span class="pun">)</span></pre>

<p>
	لقد أتممنا تعريف دالتنا، غير أننا إن نَفَّذنا البرنامج الآن، فلن يحدث أيّ شيء، لأننا لم نستدع الدالة؛ لذلك، سنستدع الدالة عبر التعبير <code>‎hello()‎</code> خارج كتلة تعريف الدالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_11" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"مرحبا بالعالم"</span><span class="pun">)</span><span class="pln">

hello</span><span class="pun">()</span><span class="pln">
</span></pre>

<p>
	الآن، لننفّذ البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_13" style=""><span class="pln">python hello</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	يجب أن تحصل على المخرجات التالية:
</p>

<pre class="ipsCode">مرحبا بالعالم!
</pre>

<p>
	بعض الدوال أكثر تعقيدًا بكثير من الدالة <code>‎hello()‎</code> التي عرّفناها أعلاه. على سبيل المثال، يمكننا استخدام <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/" rel="">for</a> و<a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r746/" rel="">التعليمات الشرطية</a>، وغيرها داخل كتلة الدالة.
</p>

<p>
	على سبيل المثال، تستخدم الدالة المُعرّفة أدناه تعليمة شرطية للتحقق مما إذا كانت المدخلات الممرّرة إلى المتغير <code>‎name‎</code> تحتوي على حرف علة (vowel)، ثم تستخدم الحلقة <code>‎for‎</code> للمرور (iterate) على الحروف الموجودة في السلسلة النصية <code>‎name‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_15" style=""><span class="com"># names() تعريف الدالة</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> names</span><span class="pun">():</span><span class="pln">
    </span><span class="com"># وإحالة المدخلات عليه name إعداد المتغير</span><span class="pln">
    name </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'أدخل اسمك:'</span><span class="pun">))</span><span class="pln">
    </span><span class="com"># يحتوي حرف علة name التحقق من أن</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> set</span><span class="pun">(</span><span class="str">'aeiou'</span><span class="pun">).</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">name</span><span class="pun">.</span><span class="pln">lower</span><span class="pun">()):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك يحوي حرف علة'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك لا يحوي حرف علة'</span><span class="pun">)</span><span class="pln">

    </span><span class="com"># name المرور على حروف</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> name</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">

</span><span class="com"># استدعاء الدالة</span><span class="pln">
names</span><span class="pun">()</span></pre>

<p>
	تستخدم الدالة <code>‎names()‎</code> التي عرّفناها أعلاه تعليمة شرطية، وحلقة <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/" rel=""><code>for</code></a>، وهذا توضيح لكيفية تنظيم الشفرة البرمجية ضمن تعريف الدالة. يمكننا أيضًا جعل التعليمة الشرطية والحلقة <code>‎for‎</code> دالتين منفصلتين.
</p>

<p>
	إنّ تعريف الدوال داخل البرامج يجعل الشفرة البرمجية تركيبية (modular)، وقابلة لإعادة الاستخدام، وذلك سيتيح لنا استدعاء نفس الدالة دون إعادة كتابة شيفرتها كل مرة.
</p>

<h2>
	المعاملات
</h2>

<p>
	حتى الآن، عرّفنا دالة ذات قوسين فارغين لا تأخذ أيّ وسائط (arguments)، سنتعلم في هذا القسم كيفية تعريف المعاملات (parameters) وتمرير البيانات إلى الدوال.
</p>

<p>
	المعامل (parameter) هو كيان مُسمًّى يوضع في تعريف الدالة، ويعرّف وسيطًا (arguments) يمكن أن تقبله الدالة عند استدعائها.
</p>

<p>
	دعنا ننشئ برنامجًا صغيرًا يأخذ 3 معاملات <code>‎x‎</code> و <code>‎y‎</code> و <code>‎z‎</code>. سننشئ دالة تجمع تلك المعاملات وفق عدة مجموعات ثم تطبع تلك حاصل جمعها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_17" style=""><span class="kwd">def</span><span class="pln"> add_numbers</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> z</span><span class="pun">):</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y
    b </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> z
    c </span><span class="pun">=</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z
    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c</span><span class="pun">)</span><span class="pln">

add_numbers</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	مرّرنا العدد <code>‎1‎</code> إلى المعامل <code>‎x‎</code>، و <code>‎2‎</code> إلى المعامل <code>‎y‎</code>، و <code>‎3‎</code> إلى المعامل <code>‎z‎</code>. تتوافق هذه القيم مع المعاملات المقابلة لها في ترتيب الظهور.
</p>

<p>
	يُجرِي البرنامج العمليات الحسابية على المعاملات على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_19" style=""><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span></pre>

<p>
	تطبع الدالة أيضًا <code>‎a‎</code> و <code>‎b‎</code> و <code>‎c‎</code>، وبناءً على العمليات الحسابية أعلاه، فإنّ قيمة <code>‎a‎</code> ستساوي العدد <code>‎3‎</code>، و <code>‎b‎</code> ستساوي <code>‎4‎</code>، و <code>‎c‎</code> ستساوي العدد <code>‎5‎</code>.
</p>

<p>
	لننفّذ البرنامج:
</p>

<pre class="ipsCode">python add_numbers.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">3 4 5
</pre>

<p>
	المعاملات هي وسائط يتم تعريفها عادة كمتغيرات ضمن تعريف الدالة. يمكن تعيين قيم إليها عند تنفيذ التابع بتمرير وسائط إلى الدالة.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<h2>
	الوسائط المسمّاة
</h2>

<p>
	تُستدعى المعاملات بحسب ترتيب ظهورها في تعريف الدالة، أما الوسائط المسماة (Keyword Arguments) فتُستخدَم بأسمائها في استدعاء الدالة.
</p>

<p>
	عند استخدام الوسائط المسمّاة، يمكنك استخدام المعاملات بأيّ ترتيب تريد، لأنّ مترجم بايثون سيستخدم الكلمات المفتاحية لمطابقة القيم مع المعاملات.
</p>

<p>
	سننشئ دالة تعرض معلومات الملف الشخصي للمستخدم، ونمرر إليها المُعامِلين <code>‎username‎</code> (سلسلة نصية)، و <code>‎followers‎</code> (عدد صحيح).
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_21" style=""><span class="com"># تعريف دالة ذات معاملات</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Username: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Followers: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">))</span></pre>

<p>
	داخل تعريف الدالة، وضعنا <code>‎username‎</code> و <code>‎followers‎</code> بين قوسي الدالة <code>‎profile_info()‎</code> أثناء تعريفها. تطبع شفرة الدالة المعلومات الخاصة بالمستخدم على هيئة <a href="https://wiki.hsoub.com/Python/str" rel="external">سلسلة نصية</a> باستخدام المعاملين المُمرّرين.
</p>

<p>
	الآن، يمكننا استدعاء الدالة وتعيين المعاملات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_23" style=""><span class="kwd">def</span><span class="pln"> profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Username: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Followers: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">))</span><span class="pln">

</span><span class="com"># استدعاء الدالة مع تعيين المعاملات</span><span class="pln">
profile_info</span><span class="pun">(</span><span class="str">"sammyshark"</span><span class="pun">,</span><span class="pln"> </span><span class="lit">945</span><span class="pun">)</span><span class="pln">

</span><span class="com"># استدعاء الدالة مع تمرير الوسائط المسماة إليها</span><span class="pln">
profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">=</span><span class="str">"AlexAnglerfish"</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">=</span><span class="lit">342</span><span class="pun">)</span></pre>

<p>
	في الاستدعاء الأول للدالة، مرّرنا اسم المستخدم <code>‎sammyshark‎</code>، وعدد المتابعين <code>‎945‎</code> بالترتيب الوارد في تعريف الدالة. أمّا في الاستدعاء الثاني للدالة، فقد استخدمنا الوسائط المسمّاة، وقمنا بتعيين قيم للوسائط ويمكن عكس الترتيب إن شئنا.
</p>

<p>
	لننفذ البرنامج:
</p>

<pre class="ipsCode">python profile.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">Username: sammyshark
Followers: 945
Username: AlexAnglerfish
Followers: 342
</pre>

<p>
	سنحصل في المخرجات على أسماء المستخدمين، وأعداد المتابعين لكلا المستخدمين. يمكننا تغيير ترتيب المعاملات، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_26" style=""><span class="kwd">def</span><span class="pln"> profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Username: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Followers: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">))</span><span class="pln">

</span><span class="com"># تغيير ترتيب المعاملات</span><span class="pln">
profile_info</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">=</span><span class="lit">820</span><span class="pun">,</span><span class="pln"> username</span><span class="pun">=</span><span class="str">"cameron-catfish"</span><span class="pun">)</span></pre>

<p>
	عند تنفيذ البرنامج أعلاه، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">Username: cameron-catfish
Followers: 820
</pre>

<p>
	يحافظ تعريف الدالة على نفس ترتيب العبارات في <code>‎print()‎</code>، لذلك يمكننا استخدام الوسائط المسمّاة بأيّ ترتيب نشاء.
</p>

<h2>
	القيم الافتراضية للوسائط
</h2>

<p>
	يمكننا إعطاء قيم افتراضية لواحد أو أكثر من المعاملات. في المثال أدناه، سنعطي للمعامل <code>‎followers‎</code> القيمة الافتراضية <code>‎1‎</code> لاستعمالها إن لم تُمرَّر هذه القيمة للدالة عند استدعائها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_28" style=""><span class="kwd">def</span><span class="pln"> profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Username: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Followers: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">))</span></pre>

<p>
	الآن، يمكننا استدعاء الدالة مع تعيين اسم المستخدم فقط، وسيُعيّن عدد المتابعين تلقائيًا ويأخذ القيمة <code>1</code>. لكن يمكننا تغيير عدد المتابعين إن شئنا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_30" style=""><span class="kwd">def</span><span class="pln"> profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">=</span><span class="lit">1</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Username: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> username</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Followers: "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">followers</span><span class="pun">))</span><span class="pln">

profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">=</span><span class="str">"JOctopus"</span><span class="pun">)</span><span class="pln">
profile_info</span><span class="pun">(</span><span class="pln">username</span><span class="pun">=</span><span class="str">"sammyshark"</span><span class="pun">,</span><span class="pln"> followers</span><span class="pun">=</span><span class="lit">945</span><span class="pun">)</span></pre>

<p>
	عندما ننفّذ البرنامج باستخدام الأمر <code>‎python profile.py‎</code>، سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">Username: JOctopus
Followers: 1
Username: sammyshark
Followers: 945
</pre>

<p>
	تمرير قيم إلى المعاملات الافتراضية سيتخطى القيمة الافتراضية المعطاة في تعريف الدالة.
</p>

<h2>
	إعادة قيمة
</h2>

<p>
	كما يمكن تمرير قيم إلى الدالة، فيمكن كذلك أن تنتج الدالة قيمة وتعيدها لم استدعاها.
</p>

<p>
	يمكن أن تنتج الدالة قيمة، ويكونُ ذلك عبر استخدام التعليمة <code>‎return‎</code>، هذه التعليمة اختيارية، وفي حال استخدامها، فستُنهِي الدالة مباشرةً عملها وتوقف تنفيذها، وتُمرَّر قيمة التعبير الذي يعقُبها إلى المُستدعي (caller). إذا لم يلي التعليمة <code>‎return‎</code> أي شيء، فستُعيد الدالة القيمةَ <code>‎None‎</code>.
</p>

<p>
	حتى الآن، استخدمنا الدالة <code>‎print()‎</code> بدلاً من <code>‎return‎</code> في دوالنا لطباعة شيء بدلًا من إعادته. لننشئ برنامجًا يعيد متغيرًا بدلًا من طباعته الآن.
</p>

<p>
	في ملف نصي جديد يسمى <code>‎square.py‎</code>، سننشئ برنامجًا يحسب مربع المعامل <code>‎x‎</code>، ويُحيل الناتج إلى المتغير <code>‎y‎</code>، ثم يعيده. سنطبع المتغير <code>‎result‎</code>، والذي يساوي ناتج تنفيذ الدالة <code>‎square(3)‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_32" style=""><span class="kwd">def</span><span class="pln"> square</span><span class="pun">(</span><span class="pln">x</span><span class="pun">):</span><span class="pln">
    y </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">**</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> y

result </span><span class="pun">=</span><span class="pln"> square</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span></pre>

<p>
	لننفّذ البرنامج:
</p>

<pre class="ipsCode">python square.py
</pre>

<p>
	سنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">9
</pre>

<p>
	مخرجات البرنامج هي العدد الصحيح <code>‎9‎</code> الذي أعادته الدالة وهو ما نتوقعه لو طلبنا من بايثون حساب مربع العدد 3.
</p>

<p>
	لفهم كيفية عمل التعليمة <code>‎return‎</code>، يمكننا <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%82%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r719/" rel="">تعليق التعليمة</a> <code>‎return‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_34" style=""><span class="kwd">def</span><span class="pln"> square</span><span class="pun">(</span><span class="pln">x</span><span class="pun">):</span><span class="pln">
    y </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">**</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
    </span><span class="com"># return y</span><span class="pln">

result </span><span class="pun">=</span><span class="pln"> square</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">result</span><span class="pun">)</span></pre>

<p>
	الآن، لننفّذ البرنامج مرة أخرى:
</p>

<pre class="ipsCode">python square.py
</pre>

<p>
	سنحصل على الناتج التالي:
</p>

<pre class="ipsCode">None
</pre>

<p>
	بدون استخدام التعليمة <code>‎return‎</code>، لا يمكن للبرنامج إعادة أيّ قيمة، لذلك تُعاد القيمة الافتراضية <code>‎None‎</code>.
</p>

<p>
	إليك مثال آخر، في برنامج <code>‎add_numbers.py‎</code> أعلاه، سنستبدل بالتعليمة <code>‎return‎</code> الدالة <code>‎print()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_36" style=""><span class="kwd">def</span><span class="pln"> add_numbers</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">,</span><span class="pln"> z</span><span class="pun">):</span><span class="pln">
    a </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> y
    b </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> z
    c </span><span class="pun">=</span><span class="pln"> y </span><span class="pun">+</span><span class="pln"> z
    </span><span class="kwd">return</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> b</span><span class="pun">,</span><span class="pln"> c

sums </span><span class="pun">=</span><span class="pln"> add_numbers</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">sums</span><span class="pun">)</span></pre>

<p>
	خارج الدالة، أحلنا إلى المتغير <code>‎sums‎</code> نتيجة استدعاء الدالة بالوسائط <code>‎1‎</code> و <code>‎2‎</code> و <code>‎3‎</code> كما فعلنا أعلاه ثم طبعنا قيمته.
</p>

<p>
	فلننفّذ البرنامج مرة أخرى:
</p>

<pre class="ipsCode">python add_numbers.py
</pre>

<p>
	والناتج سيكون:
</p>

<pre class="ipsCode">(3, 4, 5)
</pre>

<p>
	لقد حصلنا على الأعداد <code>‎3‎</code> و <code>‎4‎</code> و <code>‎5‎</code> وهي نفس المخرجات التي تلقيناها سابقًا عندما استخدمنا الدالة <code>‎print()‎</code> في الدالة. هذه المرة تمت إعادتها على هيئة <a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D9%86%D9%88%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-tuples-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r507/" rel="">صف</a> لأنّ التعبير المرافق للتعليمة <code>‎return‎</code> يحتوي على فاصلة واحدة على الأقل.
</p>

<p>
	تُوقَف الدوال فورًا عندما تصل إلى التعليمة <code>‎return‎</code>، سواء أعادت قيمة، أم لم تُعِد.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_38" style=""><span class="kwd">def</span><span class="pln"> loop_five</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> x </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">25</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
        </span><span class="kwd">if</span><span class="pln"> x </span><span class="pun">==</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
            </span><span class="com"># x == 5 إيقاف الدالة عند</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"This line will not execute."</span><span class="pun">)</span><span class="pln">

loop_five</span><span class="pun">()</span></pre>

<p>
	يؤدي استخدام التعليمة <code>‎return‎</code> داخل الحلقة <code>‎for‎</code> إلى إنهاء الدالة، وبالتالي لن يتم تنفيذ السطر الموجود خارج الحلقة. لو استخدمنا بدلًا من ذلك <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-break-%D9%88-continue-%D9%88-pass-%D8%B9%D9%86%D8%AF-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r511/" rel="">break</a>، فسيُنفّذ السطر <code>‎print()‎</code> الأخير من المثال السابق.
</p>

<p>
	نعيد التذكير أنَّ التعليمة <code>‎return‎</code> تنهي عمل الدالة، وقد تعيد قيمة إذا أعقبها تعبير.
</p>

<h2>
	استخدام <code>‎main()‎</code> دالةً
</h2>

<p>
	رغم أنه يمكنك في بايثون استدعاء الدالة في أسفل البرنامج، وسيتم تنفيذها (كما فعلنا في الأمثلة أعلاه)، فإنّ العديد من لغات البرمجة (مثل C++‎ و <a href="https://academy.hsoub.com/programming/java" rel="">Java</a>) تتطلب الدالة <code>‎main‎</code>. إنّ تضمين دالة <code>‎main()‎</code>، وإن لم يكن إلزاميًا، يمكن أن يهيكل برامج بيثون بطريقة منطقية، بحيث تضع أهم مكونات البرنامج في دالة واحدة. كما يمكن أن يجعل البرنامج أكثر مقروئية للمبرمجين غير البايثونيِّين.
</p>

<p>
	سنبدأ بإضافة دالة <code>‎main()‎</code> إلى برنامج <code>‎hello.py‎</code> أعلاه. سنحتفظ بالدالة <code>‎hello()‎</code>، ثم نعرّف دالة <code>‎main()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_40" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"مرحبا بالعالم"</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span></pre>

<p>
	ضمن الدالة <code>‎main()‎</code>، سندرج الدالة <code>‎print()‎</code>، والتي ستعُلِمنا بأننا في الدالة <code>‎main()‎</code>. أيضًا سنستدعي الدالة <code>‎hello()‎</code> داخل <code>‎main()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_42" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"مرحبا بالعالم"</span><span class="pun">)</span><span class="pln">


</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"هذه هي الدالة الرئيسية"</span><span class="pun">)</span><span class="pln">
    hello</span><span class="pun">()</span></pre>

<p>
	أخيرًا، في أسفل البرنامج، سنستدعي الدالة <code>‎main()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_44" style=""><span class="kwd">def</span><span class="pln"> hello</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"مرحبا بالعالم"</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"هذه هي الدالة الرئيسية."</span><span class="pun">)</span><span class="pln">
    hello</span><span class="pun">()</span><span class="pln">

main</span><span class="pun">()</span></pre>

<p>
	الآن يمكننا تنفيذ برنامجنا:
</p>

<pre class="ipsCode">python hello.py
</pre>

<p>
	وسنحصل على المخرجات التالية:
</p>

<pre class="ipsCode">هذه هي الدالة الرئيسية.
مرحبا بالعالم!
</pre>

<p>
	لمّا استدعينا الدالة <code>‎hello()‎</code> داخل <code>‎main()‎</code>، ثم نفّذنا الدالة <code>‎main()‎</code> وحدها، فقد طُبع النص <code>مرحبا بالعالم</code> مرة واحدة فقط، وذلك عقب <a href="https://wiki.hsoub.com/Python/str" rel="external">السلسلة النصية</a> التي أخبرتنا بأننا في الدالة الرئيسية.
</p>

<p>
	سنعمل الآن مع دوال مُتعدِّدة، لذلك من المستحسن أن تراجع نطاقات المتغيرات في المقالة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r729/" rel="">كيفية استخدام المتغيرات في بايثون</a>.
</p>

<p>
	إذا عرّفت متغيرًا داخل دالة، فلا يمكنك أن تستخدم ذلك المتغير إلا ضمن تلك الدالة. لذا، إن أردت استخدام متغير ما في عدة دوال، فقد يكون من الأفضل الإعلان عنه متغيرًا عامًا (global variable).
</p>

<p>
	في بايثون، يعدُّ <code>‎'__main__'‎</code> اسم النطاق الذي ستُنفَّذ فيه الشيفرة العليا (top-level code). عند تنفيذ برنامج من الدخل القياسي (standard input)، أو من سكربت، أو من سطر الأوامر، سيتم ضبط <code>‎__name__‎</code> عند القيمة <code>‎'__main__'‎</code>.
</p>

<p>
	لهذا السبب، اصطلح مطورو بايثون على استخدام الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_47" style=""><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">'__main__'</span><span class="pun">:</span><span class="pln">
    </span><span class="com"># الشفرة التي ستُنفّذ لو كان هذا هو البرنامج الرئيسي</span></pre>

<p>
	هذه الصياغة تتيح استخدام ملفات بايثون إما:
</p>

<ul>
	<li>
		برامج رئيسية، مع تنفيذ ما يلي التعليمة <code>‎if‎</code>، أو
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D9%8A%D8%B1%D8%A7%D8%AF-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r744/" rel="">وحدات</a> عادية، مع عدم تنفيذ ما يتبع التعليمة <code>‎if‎</code>.
	</li>
</ul>

<p>
	سيتم تنفيذ الشفرة غير المُتضمّنة في العبارة <code>if __name__ == '__main__'‎:‎</code> عند التنفيذ. إذا كنت تستخدم ملف بايثون كوحدة، فسيتم أيضًا تنفيذ الشفرة البرمجية غير المُتضمّنة في هذه العبارة عند استيراد ذلك الملف.
</p>

<p>
	دعنا نوسع البرنامج <code>‎names.py‎</code> أعلاه، سننشئ ملفا جديدًا يسمى <code>‎more_names.py‎</code>. سنعلن في هذا البرنامج عن متغير عام، ونعدِّل الدالة <code>‎names()‎</code> الأصليَّة بشكل نقسِّم فيه التعليمات إلى دالّتين منفصلتين.
</p>

<p>
	ستتحقق الدالة الأولى <code>‎has_vowel()‎</code> مما إذا كانت السلسلة النصية <code>‎name‎</code> تحتوي على حرف علة (vowel). وتطبع الدالة الثانية <code>‎print_letters()‎</code> كل حرف من السلسلة النصية <code>‎name‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_49" style=""><span class="com"># الإعلان عن متغير عام لاستخدامه في جميع الدوال</span><span class="pln">
name </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'أدخل اسمك:'</span><span class="pun">))</span><span class="pln">


</span><span class="com"># يحتوي حرف علة name تعريف دالة للتحقق من أن</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> has_vowel</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> set</span><span class="pun">(</span><span class="str">'aeiou'</span><span class="pun">).</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">name</span><span class="pun">.</span><span class="pln">lower</span><span class="pun">()):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك لا يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">


</span><span class="com"># name المرور على حروف</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> print_letters</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> name</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span></pre>

<p>
	بعد ذلك، دعنا نعرّف الدالة <code>‎main()‎</code> التي سَتستدعي كلا الدّالتين <code>‎has_vowel()‎</code> و <code>‎print_letters()‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_51" style=""><span class="com"># الإعلان عن متغير عام لاستخدامه في جميع الدوال</span><span class="pln">
name </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'أدخل اسمك:'</span><span class="pun">))</span><span class="pln">


</span><span class="com"># يحتوي حرف علة name تعريف دالة للتحقق من أنّ</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> has_vowel</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> set</span><span class="pun">(</span><span class="str">'aeiou'</span><span class="pun">).</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">name</span><span class="pun">.</span><span class="pln">lower</span><span class="pun">()):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك لا يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">


</span><span class="com"># name المرور على حروف</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> print_letters</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> name</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">


</span><span class="com"># التي ستستدعي بقية الدوال main تعريف الدالة</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    has_vowel</span><span class="pun">()</span><span class="pln">
    print_letters</span><span class="pun">()</span></pre>

<p>
	أخيرًا، سنضيف العبارة <code>‎if __name__ == '__main__':‎</code> في أسفل الملف. لقد وضعنا جميع الدوال التي نودّ تنفيذها في الدالة <code>‎main()‎</code>، لذا سنستدعي الدالة <code>‎main()‎</code> بعد العبارة <code>‎if‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_53" style=""><span class="com"># الإعلان عن متغير عام لاستخدامه في جميع الدوال</span><span class="pln">
name </span><span class="pun">=</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'أدخل اسمك:'</span><span class="pun">))</span><span class="pln">


</span><span class="com"># يحتوي حرف علة name تعريف دالة للتحقق من أن</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> has_vowel</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> set</span><span class="pun">(</span><span class="str">'aeiou'</span><span class="pun">).</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">name</span><span class="pun">.</span><span class="pln">lower</span><span class="pun">()):</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'اسمك لا يحتوي حرف علة'</span><span class="pun">)</span><span class="pln">


</span><span class="com"># name المرور على حروف</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> print_letters</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> name</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span><span class="pln">

</span><span class="com"># التي ستستدعي بقية الدوال main تعريف الدالة</span><span class="pln">

</span><span class="kwd">def</span><span class="pln"> main</span><span class="pun">():</span><span class="pln">
    has_vowel</span><span class="pun">()</span><span class="pln">
    print_letters</span><span class="pun">()</span><span class="pln">

</span><span class="com"># main() تنفيذ الدالة</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">'__main__'</span><span class="pun">:</span><span class="pln">
    main</span><span class="pun">()</span></pre>

<p>
	يمكننا الآن تنفيذ البرنامج:
</p>

<pre class="ipsCode">python more_names.py
</pre>

<p>
	سيعرض هذا البرنامج نفس المخرجات التي عرضها البرنامج <code>‎names.py‎</code>، بيْد أنّ الشفرة هنا أكثر تنظيمًا، ويمكن استخدامها بطريقة تركيبية (modular).
</p>

<p>
	إذا لم ترغب في الإعلان عن الدالة <code>‎main()‎</code>، يمكنك بدلاً من ذلك إنهاء البرنامج كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4328_55" style=""><span class="pun">...</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> __name__ </span><span class="pun">==</span><span class="pln"> </span><span class="str">'__main__'</span><span class="pun">:</span><span class="pln">
    has_vowel</span><span class="pun">()</span><span class="pln">
    print_letters</span><span class="pun">()</span></pre>

<p>
	يؤدي استخدام <code>‎main()‎</code> كدالة، واستخدام العبارة <code>‎if __name__ == '__main__':‎</code> إلى تنظيم الشيفرة البرمجية بطريقة منطقية، وجعلها أكثر مقروئية وتراكبية.
</p>

<h2>
	خلاصة
</h2>

<p>
	الدوال هي كتل من التعليمات البرمجية التي تُنفِّذ إجراءات معيّنة داخل البرنامج، كما تساعد على جعل الشفرة تركيبية، وقابلة لإعادة الاستخدام بالإضافة إلى أنها تنظمها وتسهل من قراءتها.
</p>

<p>
	لمعرفة المزيد حول كيفية جعل الشفرة تركيبية، يمكنك قراءة المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r745/" rel="">كيفية كتابة الوحدات في بايثون 3</a>.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة -وبتصرّف- للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-define-functions-in-python-3" rel="external nofollow">How To Define Functions in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
	<li>
		المقالة التالية: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-args-%D9%88-kwargs-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r753" rel="">كيفية استخدام ‎args و ‎*kwargs في بايثون 3</a>
	</li>
	<li>
		المقالة السابقة: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-break-%D9%88-continue-%D9%88-pass-%D8%B9%D9%86%D8%AF-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r511/" rel="">كيفية استخدام تعابير break و continue و pass عند التعامل مع حلقات التكرار في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">752</guid><pubDate>Sat, 26 Oct 2019 19:07:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x62A;&#x639;&#x627;&#x628;&#x64A;&#x631; break &#x648; continue &#x648; pass &#x639;&#x646;&#x62F; &#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x62D;&#x644;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-break-%D9%88-continue-%D9%88-pass-%D8%B9%D9%86%D8%AF-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r511/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c5c35f5ae_break.jpg.717123cb21a2c7460024679d096322c3.jpg" /></p>
<p id="تمهيد">
	يسمح لك استخدام حلقات <code>for</code> أو <code>while</code> في بايثون بأتمتة وتكرار المهام بطريقة فعّالة.<br>
	لكن في بعض الأحيان، قد يتدخل عامل خارجي في طريقة تشغيل برنامجك، وعندما يحدث ذلك، فربما تريد من برنامجك الخروج تمامًا من حلقة التكرار، أو تجاوز جزء من الحلقة قبل إكمال تنفيذها، أو تجاهل هذا العامل الخارجي تمامًا. لذا يمكنك فعل ما سبق باستخدام تعابير <code>break</code> و <code>continue</code> و <code>pass</code>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32015" href="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c5c3a0547_break.jpg.337fa039c7dd2c0dd80cedab85d4f135.jpg" rel="" data-fileext="jpg"><img alt="كيفية استخدام تعليمات break.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32015" data-unique="ex7s4fwc2" src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c5c3b5aef_break.thumb.jpg.1d2bc3d1487731dbebe913e55e153ebd.jpg"></a>
</p>

<h2 id="التعبير-break">
	التعبير break
</h2>

<p>
	يوفِّر لك التعبير <code>break</code> القدرة على الخروج من حلقة التكرار عند حدوث عامل خارجي. حيث عليك وضع التعبير <code>break</code> في الشيفرة التي ستُنفَّذ في كل تكرار للحلقة، ويوضع عادةً ضمن تعبير <code>if</code>.<br>
	ألقِ نظرةً إلى أحد الأمثلة الذي يستعمل التعبير <code>break</code> داخل حلقة <code>for</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><span class="pln">number </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> number </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">10</span><span class="pun">):</span><span class="pln">
   number </span><span class="pun">=</span><span class="pln"> number </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">

   </span><span class="kwd">if</span><span class="pln"> number </span><span class="pun">==</span><span class="pln"> </span><span class="lit">5</span><span class="pun">:</span><span class="pln">
      </span><span class="kwd">break</span><span class="pln">    </span><span class="com"># break here</span><span class="pln">

   </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Number is '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">number</span><span class="pun">))</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Out of loop'</span><span class="pun">)</span></pre>

<p>
	هذا برنامجٌ صغيرٌ، هيّأنا في بدايته المتغير <code>number</code> بجعله يساوي الصفر، ثم بنينا حلقة تكرار <code>for</code> التي تعمل لطالما كانت قيمة المتغير <code>number</code> أصغر من 10.<br>
	ثم قمنا بزيادة قيمة المتغير <code>number</code> داخل حلقة <code>for</code> بمقدار 1 في كل تكرار، وذلك في السطر <code>number = number + 1</code>.<br>
	ثم كانت هنالك عبارة <code>if</code> التي تختبر إن كان المتغير <code>number</code> مساوٍ للرقم 5، وعند حدوث ذلك فسيُنفَّذ التعبير <code>break</code> للخروج من الحلقة.<br>
	وتوجد داخل حلقة التكرار الدالة <code>print()‎</code> التي تُنفَّذ في كل تكرار إلى أن نخرج من الحلقة عبر التعبير <code>break</code>، وذلك لأنَّها موجودة بعد التعبير <code>break</code>.<br>
	لكي نتأكد أننا خرجنا من الحلقة، فوضعنا عبارة <code>print()‎</code> أخيرة موجودة خارج حلقة <code>for</code>.<br>
	سنرى الناتج الآتي عند تنفيذ البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><code class="hljs vhdl"><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="typ">Out</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">of</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">loop</span></span></code></pre>

<p>
	الناتج السابق يُظهِر أنَّه بمجرد أن أصبح العدد الصحيح <code>number</code> مساويًا للرقم 5، فسينتهي تنفيذ حلقة التكرار عبر التعبير <code>break</code>.<br>
	الخلاصة: التعبير <code>break</code> يؤدي إلى الخروج من حلقة التكرار.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<h2 id="التعبير-continue">
	التعبير continue
</h2>

<p>
	التعبير <code>continue</code> يسمح لنا بتخطي جزء من حلقة التكرار عند حدوث عامل خارجي، لكن إكمال بقية الحلقة إلى نهايتها. بعبارةٍ أخرى: سينتقل تنفيذ البرنامج إلى أوّل حلقة التكرار عند تنفيذ التعبير <code>continue</code>.<br>
	يجب وضع التعبير <code>continue</code> في الشيفرة التي ستُنفَّذ في كل تكرار للحلقة، ويوضع عادةً ضمن تعبير <code>if</code>.<br>
	سنستخدم نفس البرنامج الذي استعملناها لشرح التعبير <code>break</code> أعلاه، لكننا سنستخدم التعبير <code>continue</code> بدلًا من <code>break</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><code class="hljs applescript"><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">10</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">

   </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">:</span><span class="pln">
      </span><span class="hljs-keyword"><span class="kwd">continue</span></span><span class="pln">    </span><span class="hljs-comment"><span class="com"># continue here</span></span><span class="pln">

   </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Number </span><span class="hljs-keyword"><span class="str">is</span></span><span class="str"> '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">))</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Out </span><span class="hljs-keyword"><span class="str">of</span></span><span class="str"> loop'</span><span class="pun">)</span></code></pre>

<p>
	الفرق بين استخدام التعبير <code>continue</code> بدلًا من <code>break</code> هو إكمال تنفيذ الشيفرة بغض النظر عن التوقف الذي حدث عندما كانت قيمة المتغير <code>number</code> مساويةً إلى الرقم 5. لننظر إلى الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><code class="hljs vhdl"><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">8</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">9</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">10</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="typ">Out</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">of</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">loop</span></span></code></pre>

<p>
	نلاحظ أنَّ السطر الذي يجب أن يحتوي على <code>Number is 5</code> ليس موجودًا في المخرجات، لكن سيُكمَل تنفيذ حلقة التكرار بعد هذه المرحلة مما يطبع الأرقام من 6 إلى 10 قبل إنهاء تنفيذ الحلقة.<br>
	يمكنك استخدام التعبير <code>continue</code> لتفادي استخدام تعابير شرطية معقدة ومتشعّبة، أو لتحسين أداء البرنامج عن طريق تجاهل الحالات التي ستُرفَض نتائجها.<br>
	الخلاصة: التعبير <code>continue</code> سيؤدي إلى جعل البرنامج يتجاهل تنفيذ حلقة التكرار عند تحقيق شرط معين، لكن بعدئذٍ سيُكمِل تنفيذ الحلقة كالمعتاد.
</p>

<h2 id="التعبير-pass">
	التعبير pass
</h2>

<p>
	التعبير <code>pass</code> يسمح لنا بالتعامل مع أحد الشروط دون إيقاف عمل حلقة التكرار بأي شكل، أي ستُنفَّذ جميع التعابير البرمجية الموجودة في حلقة التكرار ما لم تستعمل تعابير مثل <code>break</code> أو <code>continue</code> فيها.<br>
	وكما هو الحال مع التعابير السابقة، يجب وضع التعبير <code>pass</code> في الشيفرة التي ستُنفَّذ في كل تكرار للحلقة، ويوضع عادةً ضمن تعبير <code>if</code>.<br>
	سنستخدم نفس البرنامج الذي استعملناها لشرح التعبير <code>break</code> أو <code>continue</code> أعلاه، لكننا سنستخدم التعبير <code>pass</code> هذه المرة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><code class="hljs livecodeserver"><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">10</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">

   </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">:</span><span class="pln">
      </span><span class="kwd">pass</span><span class="pln">    </span><span class="hljs-comment"><span class="com"># pass here</span></span><span class="pln">

   </span><span class="kwd">print</span><span class="pun">(</span><span class="hljs-string"><span class="str">'Number is '</span></span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pun">))</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="hljs-string"><span class="str">'Out of loop'</span></span><span class="pun">)</span></code></pre>

<p>
	التعبير <code>pass</code> الذي يقع بعد العبارة الشرطية <code>if</code> يخبر البرنامج أنَّ عليه إكمال تنفيذ الحلقة وتجاهل مساواة المتغير <code>number</code> للرقم 5.<br>
	لنشغِّل البرنامج ولننظر إلى الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2152_7" style=""><code class="hljs vhdl"><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">4</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">6</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">7</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">8</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">9</span></span><span class="pln">
</span><span class="typ">Number</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">10</span></span><span class="pln">
</span><span class="hljs-keyword"><span class="typ">Out</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">of</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">loop</span></span></code></pre>

<p>
	لاحظنا عند استخدامنا للتعبير <code>pass</code> في هذا البرنامج أنَّ البرنامج يعمل كما لو أننا لم نضع عبارة شرطية داخل حلقة التكرار؛ حيث يخبر التعبير <code>pass</code> البرنامج أن يكمل التنفيذ كما لو أنَّ الشرط لم يتحقق.<br>
	يمكن أن تستفيد من التعبير <code>pass</code> عندما تكتب برنامجك لأوّل مرة أثناء تفكيرك بحلّ مشكلة ما عبر خوارزمية، لكن قبل أن تضع التفاصيل التقنية له.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	تسمح لك التعابير <code>break</code> و <code>continue</code> و <code>pass</code> باستعمال حلقات <code>for</code> و <code>while</code> بطريقةٍ أكثر كفاءة.
</p>

<p>
	ترجمة –وبتصرّف– للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-use-break-continue-and-pass-statements-when-working-with-loops-in-python-3" rel="external nofollow">How To Use Break, Continue, and Pass Statements when Working with Loops in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		الدرس التالي: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r752" rel="">كيفية تعريف الدوال في بايثون 3</a>
	</li>
	<li>
		الدرس السابق: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/" rel="">كيفية إنشاء حلقات تكرار for في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">511</guid><pubDate>Wed, 23 Oct 2019 01:06:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x62D;&#x644;&#x642;&#x627;&#x62A; &#x62A;&#x643;&#x631;&#x627;&#x631; for &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c4dd1aec3_for.jpg.1f4ac75ad47d8b0abef8430cc85f70de.jpg" /></p>
<p id="كيفية-إنشاء-حلقات-تكرار-for-في-بايثون-3">
	يسمح لنا استخدام حلقات التكرار في <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-r1956/" rel="">برمجة الحاسوب</a> بأتمتة وتكرار المهام المتشابهة مرّاتٍ عدِّة. وسنشرح في هذا الدرس كيفية استخدام حلقة <code>for</code> في بايثون.<br>
	حلقة <code>for</code> تؤدي إلى تكرار تنفيذ جزء من الشيفرات بناءً على عدّاد أو على متغير، وهذا يعني أنَّ حلقات <code>for</code> تستعمل عندما يكون عدد مرات تنفيذ حلقة التكرار معلومًا قبل الدخول في الحلقة، وذلك على النقيض من حلقات <code>while</code> المبنية على شرط.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="32014" href="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c4e03ae4b_for.jpg.1546e036c134c6ce5e7d5bf8974d90b8.jpg" rel=""><img alt="كيفية إنشاء حلقات for.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32014" data-unique="c8cszhy6h" src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c4e0501b7_for.thumb.jpg.51ebb0004b4ee46f86bc5915d3ef7276.jpg"></a>
</p>

<h2 id="حلقات-for">
	حلقات for
</h2>

<p>
	تُبنى حلقات <code>for</code> في بايثون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><span class="kwd">for</span><span class="pln"> </span><span class="pun">[</span><span class="pln">iterating variable</span><span class="pun">]</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">[</span><span class="pln">sequence</span><span class="pun">]:</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">do</span><span class="pln"> something</span><span class="pun">]</span></pre>

<p>
	ستُنفَّذ الشيفرات الموجودة داخل حلقة التكرار عدِّة مرات إلى أن تنتهي الحلقة.<br>
	لننظر إلى كيفية مرور الحلقة <code>for</code> على مجالٍ من القيم:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">,</span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span></code></pre>

<p>
	سيُخرِج البرنامج السابق عند تشغيله الناتج الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="lit">0</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="lit">3</span><span class="pln">
</span><span class="lit">4</span></code></pre>

<p>
	ضبطنا المتغير <code>i</code> في حلقة <code>for</code> ليحتوي على القيمة التي ستُنفَّذ عليها حلقة التكرار، وكان مجال القيم التي ستُسنَد إلى هذا المتغير من 0 إلى 5.<br>
	ثم طبعًا قيمة المتغير في كل دوران لحلقة التكرار، لكن أبقِ في ذهنك أنَّنا نميل إلى بدء العد من الرقم 0 في البرمجة، وعلى الرغم من عرض خمسة أرقام، لكنها تبدأ بالرقم 0 وتنتهي بالرقم 4.<br>
	من الشائع أن ترى استخدامًا لحلقة <code>for</code> عندما تحتاج إلى تكرار كتلة معيّنة من الشيفرات لعددٍ من المرات.
</p>

<h2 id="استخدام-حلقات-التكرار-مع-الدالة-range">
	استخدام حلقات التكرار مع الدالة range()‎
</h2>

<p>
	إحدى أنواع السلاسل غير القابلة للتعديل في بايثون هي تلك الناتجة من الدالة <code>range()‎</code>، وتستخدم الدالة <code>range()‎</code> في حلقات التكرار للتحكم بعدد مرات تكرار الحلقة.<br>
	عند التعامل مع الدالة <code>range()‎</code> عليك أن تمرر معاملًا رقميًا أو معاملين أو ثلاثة معاملات:
</p>

<ul>
	<li>
		<code>start</code> يشير إلى القيم العددية الصيحية التي ستبدأ بها السلسلة، وإذا لم تُمرَّر قيمة لهذا المعامل فستبدأ السلسلة من 0
	</li>
	<li>
		<code>stop</code> هذا المعامل مطلوب دومًا وهو القيمة العددية الصحيحة التي تمثل نهاية السلسلة العددية لكن دون تضمينها
	</li>
	<li>
		<code>step</code> هي مقدار الخطوة، أي عدد الأرقام التي يجب زيادتها (أو إنقاصها إن كنّا نتعامل مع أرقام سالبة) في الدورة القادمة، وقيمة المعامل <code>step</code> تساوي 1 في حال لم تُحدَّد له قيمة
	</li>
</ul>

<p>
	لننظر إلى بعض الأمثلة التي نُمرِّر فيها مختلف المعاملات إلى الدالة <code>range()‎</code>.<br>
	لنبدأ بتمرير المعامل <code>stop</code> فقط، أي أنَّ السلسلة الآتية من الشكل <code>range(stop)</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span></code></pre>

<p>
	كانت قيمة المعامل <code>stop</code> في المثال السابق مساويةً للرقم 6، لذا ستمر حلقة التكرار من بداية المجال 0 إلى نهايته 6 (باستثناء الرقم 6 كما ذكرنا أعلاه):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="lit">0</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="lit">3</span><span class="pln">
</span><span class="lit">4</span><span class="pln">
</span><span class="lit">5</span></code></pre>

<p>
	المثال الآتي من الشكل <code>range(start ,stop)</code> الذي تُمرَّر قيم بدء السلسلة ونهايتها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">20</span></span><span class="pun">,</span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span></code></pre>

<p>
	المجال –في المثال السابق– يتراوح بين 20 (بما فيها الرقم 20) إلى 25 (باستثناء الرقم 25)، لذا سيبدو الناتج كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="lit">20</span><span class="pln">
</span><span class="lit">21</span><span class="pln">
</span><span class="lit">22</span><span class="pln">
</span><span class="lit">23</span><span class="pln">
</span><span class="lit">24</span></code></pre>

<p>
	الوسيط <code>step</code> الخاص بالدالة <code>range()‎</code> شبيه بمعامل الخطوة الذي نستعمله عند تقسيم [السلاسل النصية](آلية فهرسة السلاسل النصية وطريقة تقسيمها في بايثون 3) لأنه يستعمل لتجاوز بعض القيم ضمن السلسلة.<br>
	يأتي المعامل <code>step</code> في آخر قائمة المعاملات التي تقبلها الدالة <code>range()‎</code> وذلك بالشكل الآتي <code>range(start, stop, step)</code>. لنستعمل المعامل <code>step</code> مع قيمة موجبة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">,</span><span class="hljs-number"><span class="lit">15</span></span><span class="pun">,</span><span class="hljs-number"><span class="lit">3</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span></code></pre>

<p>
	سيؤدي المثال السابق إلى إنشاء سلسلة من الأرقام التي تبدأ من 0 وتنتهي عند 15 لكن قيمة المعامل <code>step</code> هي 3، لذا سيتم تخطي رقمين في كل دورة، أي سيكون الناتج كالآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="lit">0</span><span class="pln">
</span><span class="lit">3</span><span class="pln">
</span><span class="lit">6</span><span class="pln">
</span><span class="lit">9</span><span class="pln">
</span><span class="lit">12</span></code></pre>

<p>
	يمكننا أيضًا استخدام قيمة سالبة للمعامل <code>step</code> للدوران إلى الخلف، لكن علينا تعديل قيم <code>start</code> و <code>stop</code> بما يتوافق مع ذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> range</span><span class="pun">(</span><span class="hljs-number"><span class="lit">100</span></span><span class="pun">,</span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">,-</span><span class="hljs-number"><span class="lit">10</span></span><span class="pun">):</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span></code></pre>

<p>
	قيمة المعامل <code>start</code> في المثال السابق هي 100، وكانت قيمة المعامل <code>stop</code> هي 0، والخطوة هي <code>‎-10</code>، لذا ستبدأ السلسلة من الرقم 100 وستنتهي عند الرقم 0، وسيكون التناقص بمقدار 10 في كل دورة، ويمكننا ملاحظة ذلك في الناتج الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="lit">100</span><span class="pln">
</span><span class="lit">90</span><span class="pln">
</span><span class="lit">80</span><span class="pln">
</span><span class="lit">70</span><span class="pln">
</span><span class="lit">60</span><span class="pln">
</span><span class="lit">50</span><span class="pln">
</span><span class="lit">40</span><span class="pln">
</span><span class="lit">30</span><span class="pln">
</span><span class="lit">20</span><span class="pln">
</span><span class="lit">10</span></code></pre>

<p>
	الخلاصة: عندما نبرمج باستخدام لغة بايثون، فسنجد أننا نستفيد كثيرًا من السلاسل الرقمية التي تنتجها الدالة <code>range()‎</code>.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<h2 id="استخدام-حلقة-for-مع-أنواع-البيانات-المتسلسلة">
	استخدام حلقة for مع أنواع البيانات المتسلسلة
</h2>

<p>
	يمكن الاستفادة من القوائم (من النوع list) وغيرها من أنواع البيانات المتسلسلة واستعمالها كمعاملات لحلقات <code>for</code>، فبدلًا من الدوران باستخدام الدالة <code>range()‎</code> فيمكننا تعريف قائمة ثم الدوران على عناصرها.<br>
	سنُسنِد في المثال الآتي قائمةً إلى متغير، ثم سنستخدم حلقة <code>for</code> للدوران على عناصر القائمة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">sharks </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'hammerhead'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'great white'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'dogfish'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'frilled'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'bullhead'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'requiem'</span></span><span class="pun">]</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> shark </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> sharks</span><span class="pun">:</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">shark</span><span class="pun">)</span></code></pre>

<p>
	في هذه الحالة، قمنا بطباعة كل عنصر موجود في القائمة؛ وصحيحٌ أننا استعملنا الكلمة <code>shark</code> كاسم للمتغير، لكن يمكنك استعمال أي اسم صحيح آخر ترغب به، وستحصل على نفس النتيجة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="pln">hammerhead
great white
dogfish
frilled
bullhead
requiem</span></code></pre>

<p>
	الناتج السابق يُظهِر دوران الحلقة <code>for</code> على جميع عناصر القائمة مع طباعة كل عنصر في سطرٍ منفصل.<br>
	يشيع استخدام القوائم والأنواع الأخرى من البيانات المتسلسلة مثل السلاسل النصية وبنى tuple مع حلقات التكرار لسهولة الدوران على عناصرها. يمكنك دمج هذه الأنواع من البيانات مع الدالة <code>range()‎</code> لإضافة عناصر إلى قائمة، مثلًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs go"><span class="pln">sharks </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'hammerhead'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'great white'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'dogfish'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'frilled'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'bullhead'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'requiem'</span></span><span class="pun">]</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> item </span><span class="kwd">in</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">range</span></span><span class="pun">(</span><span class="hljs-built_in"><span class="pln">len</span></span><span class="pun">(</span><span class="pln">sharks</span><span class="pun">)):</span><span class="pln">
   sharks</span><span class="pun">.</span><span class="hljs-built_in"><span class="pln">append</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'shark'</span></span><span class="pun">)</span><span class="pln">

</span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">sharks</span><span class="pun">)</span></code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs json"><span class="pun">[</span><span class="str">'hammerhead'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'great white'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dogfish'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'frilled'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'bullhead'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'requiem'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'shark'</span><span class="pun">]</span></code></pre>

<p>
	أضفنا هنا السلسلة النصية <code>'shark'</code> خمس مرات (وهو نفس طول القائمة <code>sharks</code> الأصلي) إلى القائمة <code>sharks</code>.<br>
	يمكننا استخدام حلقة <code>for</code> لبناء قائمة جديدة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs go"><span class="pln">integers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> i </span><span class="kwd">in</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">range</span></span><span class="hljs-number"><span class="pun">(</span><span class="lit">10</span></span><span class="pun">):</span><span class="pln">
   integers</span><span class="pun">.</span><span class="hljs-built_in"><span class="pln">append</span></span><span class="pun">(</span><span class="pln">i</span><span class="pun">)</span><span class="pln">

</span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">integers</span><span class="pun">)</span></code></pre>

<p>
	هيّئنا في المثال السابق قائمةً فارغةً باسم <code>integers</code> لكن حلقة التكرار <code>for</code> ملأت القائمة لتصبح كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs json"><span class="pun">[</span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">3</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">4</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">6</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">7</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">8</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">9</span></span><span class="pun">]</span></code></pre>

<p>
	وبشكلٍ شبيهٍ بما سبق، يمكننا الدوران على السلاسل النصية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">sammy </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">'Sammy'</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> sammy</span><span class="pun">:</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span></code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs livecodeserver"><span class="pln">S
</span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln">
m
m
y</span></code></pre>

<p>
	يمكن الدوران على بنى tuple كما هو الحال في القوائم والسلاسل النصية.<br>
	عند المرور على عناصر نوع البيانات dictionary، فمن المهم أن تبقي بذهنك البنية الخاصة به (key:value) لكي تضمن أنَّك تستدعي العنصر الصحيح من المتغير. هذا مثالٌ بسيطٌ نعرض فيه المفتاح (key) والقيمة (value):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">sammy_shark </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="hljs-string"><span class="str">'name'</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="str">'Sammy'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'animal'</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="str">'shark'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'color'</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="str">'blue'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'location'</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="str">'ocean'</span></span><span class="pun">}</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> key </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> sammy_shark</span><span class="pun">:</span><span class="pln">
   </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">key </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-string"><span class="str">': '</span></span><span class="pln"> </span><span class="pun">+</span><span class="pln"> sammy_shark</span><span class="pun">[</span><span class="pln">key</span><span class="pun">])</span></code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs http"><span class="hljs-attribute"><span class="pln">name</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="typ">Sammy</span></span><span class="pln">
</span><span class="hljs-attribute"><span class="pln">animal</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="pln">shark</span></span><span class="pln">
</span><span class="hljs-attribute"><span class="pln">location</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="pln">ocean</span></span><span class="pln">
</span><span class="hljs-attribute"><span class="pln">color</span></span><span class="pun">:</span><span class="pln"> </span><span class="hljs-string"><span class="pln">blue</span></span></code></pre>

<p>
	عند استخدام متغيرات من النوع dictionary مع حلقات <code>for</code> فيكون المتغير المرتبط بحلقة التكرار متعلقًا بمفتاح القيم، وعلينا استخدام التعبير <code>dictionary_variable[iterating_variable]</code> للوصول إلى القيمة الموافقة للمفتاح. ففي المثال السابق كان المتغير المرتبط بحلقة التكرار باسم <code>key</code> وهو يُمثِّل المفاتيح، واستعملنا التعبير <code>sammy_shark[key]</code> للوصول إلى القيمة المرتبطة بذاك المفتاح.<br>
	الخلاصة: تُستعمَل حلقات التكرار عادةً للدوران على عناصر البيانات المتسلسلة وتعديلها.
</p>

<h2 id="حلقات-for-المتشعبة">
	حلقات for المتشعّبة
</h2>

<p>
	يمكن تشعّب حلقات التكرار في بايثون، كما هو الحال في بقية لغات البرمجة.<br>
	حلقة التكرار المتشعبة هي الحلقة الموجودة ضمن حلقة تكرار أخرى، وهي شبيهة بعبارات <code>if</code> المتشعّبة. تُبنى حلقات التكرار المتشعبة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs livecodeserver"><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> </span><span class="pun">[</span><span class="hljs-keyword"><span class="pln">first</span></span><span class="pln"> iterating </span><span class="hljs-built_in"><span class="pln">variable</span></span><span class="pun">]</span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">in</span></span><span class="pln"> </span><span class="pun">[</span><span class="pln">outer loop</span><span class="pun">]:</span><span class="pln"> </span><span class="hljs-comment"><span class="com"># Outer loop</span></span><span class="pln">
    </span><span class="pun">[</span><span class="hljs-built_in"><span class="kwd">do</span></span><span class="pln"> something</span><span class="pun">]</span><span class="pln">  </span><span class="hljs-comment"><span class="com"># Optional</span></span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> </span><span class="pun">[</span><span class="hljs-keyword"><span class="pln">second</span></span><span class="pln"> iterating </span><span class="hljs-built_in"><span class="pln">variable</span></span><span class="pun">]</span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">in</span></span><span class="pln"> </span><span class="pun">[</span><span class="pln">nested loop</span><span class="pun">]:</span><span class="pln">   </span><span class="hljs-comment"><span class="com"># Nested loop</span></span><span class="pln">
        </span><span class="pun">[</span><span class="hljs-built_in"><span class="kwd">do</span></span><span class="pln"> something</span><span class="pun">]</span><span class="pln">  </span></code></pre>

<p>
	يبدأ البرنامج بتنفيذ حلقة التكرار الخارجية، ويُنفَّذ أوّل دوران فيها، وأوّل دوران سيؤدي إلى الدخول إلى حلقة التكرار الداخلية، مما يؤدي إلى تنفيذها إلى أن تنتهي تمامًا. ثم سيعود تنفيذ البرنامج إلى بداية حلقة التكرار الخارجية، ويبدأ بتنفيذ الدوران الثاني، ثم سيصل التنفيذ إلى حلقة التكرار الداخلية، وستُنفَّذ حلقة التكرار الداخلية بالكامل، ثم سيعود التنفيذ إلى بداية حلقة التكرار الخارجية، وهلّم جرًا إلى أن ينتهي تنفيذ حلقة التكرار الخارجية أو إيقاف حلقة التكرار عبر استخدام [التعبير <code>break</code>](كيفية استخدام تعابير break و continue و pass عند التعامل مع حلقات التكرار في بايثون 3) أو غيره من التعابير.<br>
	لنُنشِئ مثالًا يستعمل حلقة <code>for</code>متشعبة لكي نفهم كيف تعمل بدقة. حيث ستمر حلقة التكرار الخارجية في المثال الآتي على قائمة من الأرقام اسمها <code>num_list</code>، أما حلقة التكرار الداخلية فستمر على قائمة من السلاسل النصية اسمها <code>alpha_list</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">num_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">3</span></span><span class="pun">]</span><span class="pln">
alpha_list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="hljs-string"><span class="str">'a'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'b'</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-string"><span class="str">'c'</span></span><span class="pun">]</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> number </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> num_list</span><span class="pun">:</span><span class="pln">
    </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">number</span><span class="pun">)</span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> letter </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> alpha_list</span><span class="pun">:</span><span class="pln">
        </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">letter</span><span class="pun">)</span></code></pre>

<p>
	سيظهر الناتج الآتي عند تشغيل البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs livecodeserver"><span class="hljs-number"><span class="lit">1</span></span><span class="pln">
</span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln">
b
c
</span><span class="hljs-number"><span class="lit">2</span></span><span class="pln">
</span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln">
b
c
</span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">
</span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln">
b
c</span></code></pre>

<p>
	يُظهِر الناتج السابق أنَّ البرنامج أكمل أوّل دوران على عناصر حلقة التكرار الخارجية بطباعة الرقم <code>1</code>، ومن ثم بدأ تنفيذ حلقة التكرار الدخلية مما يطبع الأحرف <code>a</code> و <code>b</code> و <code>c</code> على التوالي. وبعد انتهاء تنفيذ حلقة التكرار الداخلية، فعاد البرنامج إلى بداية حلقة التكرار الخارجية طابعًا الرقم <code>2</code>، ثم بدأ تنفيذ حلقة التكرار الداخلية (مما يؤدي إلى إظهار <code>a</code> و <code>b</code> و <code>c</code> مجددًا). وهكذا.<br>
	يمكن الاستفادة من حلقات <code>for</code> المتشعبة عند المرور على عناصر قوائم تتألف من قوائم. فلو استعملنا حلقة تكرار وحيدة لعرض عناصر قائمة تتألف من عناصر تحتوي على قوائم، فستُعرَض قيم القوائم الداخلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">list_of_lists </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="pun">[[</span><span class="str">'hammerhead'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'great white'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dogfish'</span><span class="pun">],[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">],[</span><span class="lit">9.9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8.8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7.7</span><span class="pun">]]</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> list </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> list_of_lists</span><span class="pun">:</span><span class="pln">
    </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">list</span><span class="pun">)</span></code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs json"><span class="pun">[</span><span class="str">'hammerhead'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'great white'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dogfish'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-number"><span class="lit">0</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">2</span></span><span class="pun">]</span><span class="pln">
</span><span class="pun">[</span><span class="hljs-number"><span class="lit">9.9</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">8.8</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">7.7</span></span><span class="pun">]</span></code></pre>

<p>
	وفي حال أردنا الوصول إلى العناصر الموجودة في القوائم الداخلية، فيمكننا استعمال حلقة <code>for</code> متشعبة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs lua"><span class="pln">list_of_lists </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="pun">[[</span><span class="str">'hammerhead'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'great white'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dogfish'</span><span class="pun">],[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">],[</span><span class="lit">9.9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">8.8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7.7</span><span class="pun">]]</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> list </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> list_of_lists</span><span class="pun">:</span><span class="pln">
    </span><span class="hljs-keyword"><span class="kwd">for</span></span><span class="pln"> item </span><span class="hljs-keyword"><span class="kwd">in</span></span><span class="pln"> list</span><span class="pun">:</span><span class="pln">
        </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="pln">item</span><span class="pun">)</span></code></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_4435_8" style=""><code class="hljs "><span class="pln">hammerhead
great white
dogfish
</span><span class="lit">0</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="lit">9.9</span><span class="pln">
</span><span class="lit">8.8</span><span class="pln">
</span><span class="lit">7.7</span></code></pre>

<p>
	الخلاصة: نستطيع الاستفادة من حلقات <code>for</code> المتشعبة عندما نريد الدوران على عناصر محتوى في قوائم.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	رأينا في هذا الدرس كيف تعمل حلقة التكرار <code>for</code> في لغة بايثون، وكيف نستطيع إنشاءها واستعمالها. حيث تستمر حلقة <code>for</code> بتنفيذ مجموعة من الشيفرات لعددٍ مُحدِّدٍ من المرات.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة –وبتصرّف– للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-python-3" rel="external nofollow" style="background-color: rgb(255, 255, 255);">How To Construct For Loops in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		الدرس التالي: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-break-%D9%88-continue-%D9%88-pass-%D8%B9%D9%86%D8%AF-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r511/" rel="">كيفية استخدام تعابير break و continue و pass عند التعامل مع حلقات التكرار في بايثون 3</a>
	</li>
	<li>
		الدرس السابق: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-while-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r509/" rel="">كيفية إنشاء حلقات تكرار while في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">513</guid><pubDate>Sat, 19 Oct 2019 18:09:00 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641;&#x64A;&#x629; &#x625;&#x646;&#x634;&#x627;&#x621; &#x62D;&#x644;&#x642;&#x627;&#x62A; &#x62A;&#x643;&#x631;&#x627;&#x631; while &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; 3</title><link>https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-while-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r509/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c36ec41c2_while.jpg.45507b53056612c9c0be6c8baa39d62f.jpg" /></p>
<p>
	نستفيد من البرامج الحاسوبية خيرَ استفادة في أتمتة المهام وإجراء المهام التكرارية لكيلا نحتاج إلى القيام بها يدويًا، وإحدى طرائق تكرار المهام المتشابهة هي استخدام حلقات التكرار، وسنشرح في درسنا هذا حلقة تكرار while.<br>
	حلفة تكرار <code>while</code> تؤدي إلى تكرار تنفيذ قسم من الشيفرة بناءً على متغير منطقي (boolean)، وسيستمر تنفيذ هذه الشيفرة لطالما كانت نتيجة التعبير المستعمل معها تساوي <code>true</code>.
</p>

<p>
	يمكنك أن تتخيل أنَّ حلقة <code>while</code> هي عبارة شريطة تكرارية، فبعد انتهاء تنفيذ العبارة الشرطية <code>if</code> فيُستَكمَل تنفيذ بقية البرنامج، لكن مع حلقة <code>while</code> فسيعود تنفيذ البرنامج إلى بداية الحلقة بعد انتهاء تنفيذها إلى أن يصبح الشرط مساويًا للقيمة <code>false</code>.
</p>

<p>
	وعلى النقيض من حلقات for التي تُنفَّذ عدد معيّن من المرات، فسيستمر تنفيذ حلقات <code>while</code> اعتمادًا على شرطٍ معيّن، لذا لن تحتاج إلى عدد مرات تنفيذ الحلقة قبل إنشائها.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32012" href="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c37176e8b_while.jpg.681b2e865ed1df0ce52ac9da5003cbda.jpg" rel="" data-fileext="jpg"><img alt="كيفية إنشاء حلقات while.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32012" data-unique="2cnfq3z2g" src="https://academy.hsoub.com/uploads/monthly_2019_10/5d95c3718c398_while.thumb.jpg.19ad3d560e98b702b0aae41d88702b75.jpg"></a>
</p>

<h2 id="حلقة-while">
	حلقة while
</h2>

<p>
	الشكل العام لحلقات <code>while</code> في لغة بايثون كالآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><span class="kwd">while</span><span class="pln"> </span><span class="pun">[</span><span class="pln">a condition </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">]:</span><span class="pln">
    </span><span class="pun">[</span><span class="kwd">do</span><span class="pln"> something</span><span class="pun">]</span></pre>

<p>
	سيستمر تنفيذ التعليمات البرمجية الموجودة داخل الحلقة إلى أن يصبح الشرط <code>false</code>.<br>
	لنُنشِئ برنامجًا صغيرًا فيه حلقة <code>while</code>، ففي هذه البرنامج سنطلب من المستخدم إدخال كلمة مرور. وهنالك خياران أمام حلقة التكرار:<br>
	- إما أن تكون كلمة المرور صحيحة، فعندها سينتهي تنفيذ حلقة <code>while</code>.<br>
	- أو أن تكون كلمة المرور غير صحيحة، فعندها سيستمر تنفيذ حلقة التكرار.<br>
	لنُنشِئ ملفًا باسم <code>password.py</code> في محررنا النصي المفضَّل، ولنبدأ بتهيئة المتغير <code>paasword</code> بإسناد سلسلة نصية فارغة إليه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs bash"><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">''</span></span></code></pre>

<p>
	نستخدم المتغير السابق للحصول على مدخلات المستخدم داخل حلقة التكرار <code>while</code>.<br>
	علينا بعد ذلك إنشاء حلقة <code>while</code> مع تحديد ما هو الشرط الذي يجب تحقيقه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs bash"><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">''</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> password </span><span class="pun">!=</span><span class="pln"> </span><span class="hljs-string"><span class="str">'password'</span></span><span class="pun">:</span></code></pre>

<p>
	أتبَعنا –في المثال السابق– الكلمة المحجوزة <code>while</code> بالمتغير <code>password</code>، ثم سنتحقق إذا كانت قيمة المتغير <code>password</code> تساوي السلسلة النصية <code>'password'</code> (لا تنسَ أنَّ قيمة المتغير سنحصل عليها من مدخلات المستخدم)، يمكنك أن تختار أي سلسلة نصية تشاء لمقارنة مدخلات المستخدم بها.<br>
	هذا يعني أنَّه لو أدخل المستخدم السلسلة النصية <code>password</code> فستتوقف حلقة التكرار وسيُكمَل تنفيذ البرنامج وستُنفَّذ أيّة شيفرات خارج الحلقة، لكن إذا أدخل المستخدم أيّة سلسلة نصية لا تساوي <code>password</code> فسيُكمَل تنفيذ الحلقة.<br>
	علينا بعد ذلك إضافة الشيفرة المسؤولة عمّا يحدث داخل حلقة <code>while</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs lua"><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">''</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> password </span><span class="pun">!=</span><span class="pln"> </span><span class="hljs-string"><span class="str">'password'</span></span><span class="pun">:</span><span class="pln">
    </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'What is the password?'</span></span><span class="pun">)</span><span class="pln">
    password </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span></code></pre>

<p>
	نفَّذ البرنامج عبارة <code>print</code> داخل حلقة <code>while</code> والتي تسأل المستخدم عن كلمة مروره، ثم أسندنا قيمة مدخلات المستخدم (التي حصلنا عليها عبر الدالة <code>input()‎</code>) إلى المتغير <code>password</code>.<br>
	سيتحقق البرنامج إذا كانت قيمة المتغير <code>password</code> تساوي السلسلة النصية <code>'password'</code>، وإذا تحقق ذلك فسينتهي تنفيذ حلقة <code>while</code>. لنضف سطرًا آخر إلى البرنامج لنعرف ماذا يحدث إن أصبحت قيمة الشرط مساويةً إلى <code>false</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs lua"><span class="pln">password </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-string"><span class="str">''</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> password </span><span class="pun">!=</span><span class="pln"> </span><span class="hljs-string"><span class="str">'password'</span></span><span class="pun">:</span><span class="pln">
    </span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'What is the password?'</span></span><span class="pun">)</span><span class="pln">
    password </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">

</span><span class="hljs-built_in"><span class="kwd">print</span></span><span class="pun">(</span><span class="hljs-string"><span class="str">'Yes, the password is '</span></span><span class="pln"> </span><span class="pun">+</span><span class="pln"> password </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-string"><span class="str">'. You may enter.'</span></span><span class="pun">)</span></code></pre>

<p>
	لاحظ أنَّ آخر عبارة <code>print()‎</code> موجودة خارج حلقة <code>while</code>، لذا عندما يُدخِل المستخدم الكلمة <code>password</code> عند سؤاله عن كلمة مروره، فستُطبَع آخر جملة والتي تقع خارج حلقة التكرار.<br>
	لكن ماذا يحدث لو لم يدخل المستخدم الكلمة <code>password</code> قط؟ حيث لن يستمر تنفيذ البرنامج ولن يروا آخر عبارة <code>print()‎</code> وسيستمر تنفيذ حلقة التكرار إلى ما لا نهاية!<br>
	يستمر تنفيذ حلقة التكرار إلى ما لا نهاية إذا بقي تنفيذ البرنامج داخل حلقة تكرار دون الخروج منها. وإذا أردتَ الخروج من حلقة تكرار نهائية، فاضغط <code>Ctrl+C</code> في سطر الأوامر.<br>
	احفظ البرنامج ثم شغِّله:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs avrasm"><span class="pln">python password</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<p>
	سيُطلَب منك إدخال كلمة المرور، ويمكنك تجربة ما تشاء من الكلمات. هذا مثالٌ عن ناتج البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs applescript"><span class="typ">What</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">the</span></span><span class="pln"> password</span><span class="pun">?</span><span class="pln">
hello
</span><span class="typ">What</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">the</span></span><span class="pln"> password</span><span class="pun">?</span><span class="pln">
sammy
</span><span class="typ">What</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">the</span></span><span class="pln"> password</span><span class="pun">?</span><span class="pln">
PASSWORD
</span><span class="typ">What</span><span class="pln"> </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">the</span></span><span class="pln"> password</span><span class="pun">?</span><span class="pln">
password
</span><span class="typ">Yes</span><span class="pun">,</span><span class="pln"> </span><span class="hljs-keyword"><span class="pln">the</span></span><span class="pln"> password </span><span class="hljs-keyword"><span class="kwd">is</span></span><span class="pln"> password</span><span class="pun">.</span><span class="pln"> </span><span class="typ">You</span><span class="pln"> may enter</span><span class="pun">.</span></code></pre>

<p>
	أبقِ في ذهنك أنَّ السلاسل النصية حساسة لحالة الأحرف إلا إذا استعملتَ <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B3%D9%84%D8%A7%D8%B3%D9%84-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r412/" rel="">دالةً من دوال النصوص</a> لتحويل السلسلة النصية إلى حالة الأحرف الصغيرة (على سبيل المثال) قبل التحقق منها.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<h2 id="مثال-عن-برنامج-يستخدم-حلقة-while">
	مثال عن برنامج يستخدم حلقة while
</h2>

<p>
	بعد أن تعلمنا المبدأ الأساسي لحلقة تكرار <code>while</code>، فلنُنشِئ لعبة تعمل على سطر الأوامر لتخمين الأرقام والتي تستعمل الحلقة <code>while</code> . <br>
	نريد من الحاسوب أن يُنشِئ أرقامًا عشوائيةً لكي يحاول المستخدمون تخمينها، لذا علينا استيراد الوحدة <code>random</code> عبر استخدام العبارة <code>import</code>، وإذا لم تكن هذه الحزمة مألوفةً لك فيمكنك قراءة المزيد من المعلومات عن <a href="https://docs.python.org/3.6/library/random.html" rel="external nofollow">توليد الأرقام العشوائية في توثيق بايثون</a>. لنُنشِئ بدايةً ملفًا باسم <code>guess.py</code> في محررك النصي المفضَّل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs rsl"><span class="kwd">import</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">random</span></span></code></pre>

<p>
	علينا الآن إسناد عدد صحيح عشوائي إلى المتغير <code>number</code>، ولنجعل مجاله من 1 إلى 25 (بما فيها تلك الأرقام) كيلا نجعل اللعبة صعبة جدًا.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs livecodeserver"><span class="kwd">import</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">random</span></span><span class="pln">

</span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">random</span></span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">)</span></code></pre>

<p>
	يمكننا الآن إنشاء حلقة <code>while</code>، وذلك بتهيئة متغير ثم كتابة الحلقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs livecodeserver"><span class="kwd">import</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">random</span></span><span class="pln">

</span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">random</span></span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">)</span><span class="pln">

number_of_guesses </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> number_of_guesses </span><span class="pun">&lt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="hljs-string"><span class="str">'Guess a number between 1 and 25:'</span></span><span class="pun">)</span><span class="pln">

    guess </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    guess </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="pln">guess</span><span class="pun">)</span><span class="pln">

    number_of_guesses </span><span class="pun">=</span><span class="pln"> number_of_guesses </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">break</span></code></pre>

<p>
	هيئنا متغيرًا اسمه <code>number_of_guesses</code> قيمته <code>0</code>، وسوف نزيد قيمته عند كل تكرار للحلقة لكي لا تصبح حلقتنا لا نهائية. ثم سنضيف تعبير <code>while</code> الذي يشترط ألّا تزيد قيمة المتغير <code>number_of_guesses</code> عن 5. وبعد المحاولة الخامسة سيُعاد المستخدم إلى سطر الأوامر، وإذا حاول المستخدم إدخال أيّ شيء غير رقمي فسيحصل على رسالة خطأ.<br>
	أضفنا داخل حلقة <code>while</code> عبارة <code>print()‎</code> لطلب إدخال رقم من المستخدم، ثم سنأخذ مدخلات المستخدم عبر الدالة <code>input()‎</code> ونُسنِدَها إلى المتغير <code>guess</code>، ثم سنحوِّل المتغير <code>guess</code> من سلسلة نصية إلى عدد صحيح.<br>
	وقبل انتهاء حلقة التكرار، فعلينا زيادة قيمة المتغير <code>number_of_guesses</code> بمقدار 1، لكيلا تُنفَّذ حلقة التكرار أكثر من 5 مرات.<br>
	وفي النهاية، كتبنا عبارة <code>if</code> شرطية لنرى إذا كان المتغير <code>guess</code> الذي أدخله المستخدم مساوٍ للرقم الموجود في المتغير <code>number</code> الذي ولَّده الحاسوب، وإذا تحقق الشرط فسنستخدم عبارة <code>break</code> للخروج من الحلقة.<br>
	أصبح البرنامج جاهزًا للاستخدام، ويمكننا تشغيله عبر تنفيذ الأمر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs avrasm"><span class="pln">python guess</span><span class="hljs-preprocessor"><span class="pun">.</span><span class="pln">py</span></span></code></pre>

<p>
	صحيحٌ أنَّ البرنامج يعمل عملًا سليمًا، لكن المستخدم لن يعلم إذا كان تخمينه صحيحًا ويمكنه أن يخمِّن الرقم خمس مرات دون أن يعلم إذا كانت إحدى محاولاته صحيحة. هذا مثال عن مخرجات البرنامج:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs livecodeserver"><span class="typ">Guess</span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> between </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">and</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-number"><span class="lit">11</span></span><span class="pln">
</span><span class="typ">Guess</span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> between </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">and</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-number"><span class="lit">19</span></span><span class="pln">
</span><span class="typ">Guess</span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> between </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">and</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-number"><span class="lit">22</span></span><span class="pln">
</span><span class="typ">Guess</span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> between </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">and</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-number"><span class="lit">3</span></span><span class="pln">
</span><span class="typ">Guess</span><span class="pln"> </span><span class="hljs-operator"><span class="pln">a</span></span><span class="pln"> </span><span class="hljs-built_in"><span class="pln">number</span></span><span class="pln"> between </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln"> </span><span class="hljs-operator"><span class="kwd">and</span></span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">:</span><span class="pln">
</span><span class="hljs-number"><span class="lit">8</span></span></code></pre>

<p>
	لنضف بعض العبارات الشرطية خارج حلقة التكرار لكي يحصل المستخدم على معلومات فيما إذا استطاعوا تخمين الرقم أم لا، وسنضيف هذه العبارات في نهاية الملف:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs applescript"><span class="kwd">import</span><span class="pln"> random

</span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">)</span><span class="pln">

number_of_guesses </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> number_of_guesses </span><span class="pun">&lt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Guess a </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">between</span></span><span class="str"> </span><span class="hljs-number"><span class="str">1</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">and</span></span><span class="str"> </span><span class="hljs-number"><span class="str">25</span></span><span class="str">:'</span><span class="pun">)</span><span class="pln">
    guess </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    guess </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="pln">guess</span><span class="pun">)</span><span class="pln">

    number_of_guesses </span><span class="pun">=</span><span class="pln"> number_of_guesses </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">break</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You guessed </span><span class="hljs-keyword"><span class="str">the</span></span><span class="str"> </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">in</span></span><span class="str"> '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">number_of_guesses</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">' tries!'</span><span class="pun">)</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">else</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You did </span><span class="hljs-keyword"><span class="str">not</span></span><span class="str"> guess </span><span class="hljs-keyword"><span class="str">the</span></span><span class="str"> </span><span class="hljs-type"><span class="str">number</span></span><span class="str">. The </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> was '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">))</span></code></pre>

<p>
	في هذه المرحلة سيُخبِر البرنامجُ المستخدمَ إذا استطاعوا تخمين الرقم، لكن ذلك لن يحدث إلا بعد انتهاء حلقة التكرار وبعد انتهاء عدد مرات التخمين المسموحة.<br>
	ولمساعد المستخدم قليلًا، فلنضف بعض العبارات الشرطية داخل حلقة <code>while</code> وتلك العبارات ستخبر المستخدم إذا كان تخمينه أعلى من الرقم أو أصغر منه، لكي يستطيعوا تخمين الرقم بنجاح، وسنضيف تلك العبارات الشرطية قبل السطر الذي يحتوي على <code>if guess == number</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8443_7" style=""><code class="hljs applescript"><span class="kwd">import</span><span class="pln"> random

</span><span class="hljs-type"><span class="pln">number</span></span><span class="pln"> </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">randint</span><span class="pun">(</span><span class="hljs-number"><span class="lit">1</span></span><span class="pun">,</span><span class="pln"> </span><span class="hljs-number"><span class="lit">25</span></span><span class="pun">)</span><span class="pln">

number_of_guesses </span><span class="pun">=</span><span class="pln"> </span><span class="hljs-number"><span class="lit">0</span></span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">while</span></span><span class="pln"> number_of_guesses </span><span class="pun">&lt;</span><span class="pln"> </span><span class="hljs-number"><span class="lit">5</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Guess a </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">between</span></span><span class="str"> </span><span class="hljs-number"><span class="str">1</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">and</span></span><span class="str"> </span><span class="hljs-number"><span class="str">25</span></span><span class="str">:'</span><span class="pun">)</span><span class="pln">
    guess </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    guess </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">int</span><span class="pun">(</span><span class="pln">guess</span><span class="pun">)</span><span class="pln">

    number_of_guesses </span><span class="pun">=</span><span class="pln"> number_of_guesses </span><span class="pun">+</span><span class="pln"> </span><span class="hljs-number"><span class="lit">1</span></span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">&lt;</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Your guess </span><span class="hljs-keyword"><span class="str">is</span></span><span class="str"> too low'</span><span class="pun">)</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">&gt;</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Your guess </span><span class="hljs-keyword"><span class="str">is</span></span><span class="str"> too high'</span><span class="pun">)</span><span class="pln">

    </span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">break</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">if</span></span><span class="pln"> guess </span><span class="pun">==</span><span class="pln"> </span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You guessed </span><span class="hljs-keyword"><span class="str">the</span></span><span class="str"> </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> </span><span class="hljs-keyword"><span class="str">in</span></span><span class="str"> '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="pln">number_of_guesses</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">' tries!'</span><span class="pun">)</span><span class="pln">

</span><span class="hljs-keyword"><span class="kwd">else</span></span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You did </span><span class="hljs-keyword"><span class="str">not</span></span><span class="str"> guess </span><span class="hljs-keyword"><span class="str">the</span></span><span class="str"> </span><span class="hljs-type"><span class="str">number</span></span><span class="str">. The </span><span class="hljs-type"><span class="str">number</span></span><span class="str"> was '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> str</span><span class="pun">(</span><span class="hljs-type"><span class="pln">number</span></span><span class="pun">))</span></code></pre>

<p>
	وعندما نُشغِّل البرنامج مرةً أخرى بتنفيذ <code>python guess.py</code>، فيمكننا ملاحظة أنَّ المستخدم سيحصل على بعض المساعدة، فلو كان الرقم المولَّد عشوائيًا هو <code>12</code> وكان تخمين المستخدم <code>18</code>، فسيُخبره البرنامج أنَّ الرقم الذي خمنه أكبر من الرقم العشوائي، وذلك لكي يستطيع تعديل تخمنيه وفقًا لذلك.<br>
	هنالك الكثير من التحسينات التي يمكن إجراؤها على الشيفرة السابقة، مثل تضمين آلية لمعالجة الأخطاء التي تحدث عندما لا يُدخِل المستخدم عددًا صحيحًا، لكن كان غرضنا هو رؤية كيفية استخدام حلقة <code>while</code> في برنامج قصير ومفيد يعمل من سطر الأوامر.
</p>

<h2 id="الخلاصة">
	الخلاصة
</h2>

<p>
	شرحنا في هذا الدرس كيف تعمل حلقات <code>while</code> في بايثون وكيفية إنشائها. حيث تستمر حلقات <code>while</code> بتنفيذ مجموعة من الأسطر البرمجية لطالما كان الشرط مساويًا للقيمة <code>true</code>.
</p>

<p>
	هذه المقالة جزء من سلسة مقالات حول <a href="https://academy.hsoub.com/tags/%D8%AF%D9%84%D9%8A%D9%84%20%D8%AA%D8%B9%D9%84%D9%85%20%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعلم البرمجة في بايثون 3</a>.
</p>

<p>
	ترجمة –وبتصرّف– للمقال <a href="https://www.digitalocean.com/community/tutorials/how-to-construct-while-loops-in-python-3" rel="external nofollow">How To Construct While Loops in Python 3</a> لصاحبته Lisa Tagliaferri
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		الدرس التالي: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A5%D9%86%D8%B4%D8%A7%D8%A1-%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-for-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r513/" rel="">كيفية إنشاء حلقات تكرار for في بايثون 3</a>
	</li>
	<li>
		الدرس السابق: <a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D9%84%D9%8A%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r746/" rel="">كيفية كتابة التعليمات الشرطية في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">المرجع الشامل إلى تعلم لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/files/15-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">كتاب البرمجة بلغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">509</guid><pubDate>Wed, 16 Oct 2019 01:00:00 +0000</pubDate></item></channel></rss>
