<?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/4/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</description><language>ar</language><item><title>&#x645;&#x635;&#x637;&#x644;&#x62D;&#x627;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D8%B5%D8%B7%D9%84%D8%AD%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r1982/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_05/--.png.6cd3557c7a9d8bb5f9d4fb40f2312c43.png" /></p>
<p>
	أنشأ راندال مونرو Randall Munroe في مدونة الكاريكاتير XKCD مخططًا تقنيًا لصاروخ "زحل الخامس" تحت عنوان "Up Goer Five" مُستخدمًا فقط الكلمات الإنجليزية الألف الأشهر، إذ بسّط المصطلحات التقنية إلى جمل يستطيع أي طفل فهمها، إلا أن هذا الأمر يسلط الضوء أيضًا على تفسير عدم إمكانية شرح أي شيء باستخدام مصطلحات بسيطة؛ فالشرح القائل "شيء يساعد الناس على الهرب بسرعة كبيرة في حال وجود مشكلة واشتعال كل شيء ما يجعلهم يقررون عدم الذهاب إلى الفضاء" أسهل فهمًا للمتلقي العادي من عبارة "بدء نظام الهروب Launch Escape System". الشرح الأول مبالغ بإطالته ليستخدمه مهندسو الإدارة الوطنية للملاحة الجوية والفضاء NASA في عملهم اليومي، بل أنهم حتى قد يفضلون استخدام الاختصار LES.
</p>

<p>
	قد تسبب مصطلحات الحوسبة الحيرة والقلق <a href="https://academy.hsoub.com/programming/general/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D8%A8%D8%B3%D8%A7%D8%B7%D8%A9-%D9%84%D9%84%D9%85%D8%A8%D8%AA%D8%AF%D8%A6%D9%8A%D9%86-r1870/" rel="">للمبرمجين المبتدئين</a>، إلا أنها أمر لا بد من تعلمه، إذ تختلف العديد من المصطلحات في بايثون ومجال التطوير البرمجي عمومًا اختلافات دقيقة، لدرجة أن المطورين المتمرسين قد يخلطون بينها دون اكتراث. قد يختلف التعريف التقني لهذه المصطلحات من لغة برمجة لأخرى، إلا أن هذا المقال يغطي المصطلحات المتعلقة بلغة بايثون تحديدًا، إذ ستحصل فيه على فهم واسع لمفاهيم لغة البرمجة الكامنة في الكواليس حتى لو لم يكن عميقًا.
</p>

<h2>
	تعاريف
</h2>

<p>
	ما أن يبلغ عدد المبرمجين في نفس المكان اثنين، حتى تصبح احتمالية انطلاق نقاش حول دلالات اللغة 100%، فاللغة سهلة والبشر هم سادات الكلمات وليس العكس. قد يستخدم بعض المطورين المصطلحات بطريقة مختلفة قليلًا، ومع ذلك يبقى التعرف على هذه المصطلحات أمرًا مفيدًا. سنستعرض في هذا المقال قسمًا من هذه المصطلحات وكيفية مقارنتها ببعضها بعضًا، وفي حال رغبتك بالحصول على قائمة مرتبة أبجديًا بالمصطلحات، فيمكنك الاعتماد على تلك <a href="https://docs.python.org/3/glossary.html" rel="external nofollow">الرسمية الخاصة ببايثون</a> وصولًا إلى التعريفات الأساسية.
</p>

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

<h3>
	لغة بايثون ومفسر بايثون
</h3>

<p>
	تنطوي كلمة "بايثون" على معانٍ عديدة، إذ سُميّت <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> نسبةً إلى الفرقة الكوميدية البريطانية Monty Python، وليس نسبةً إلى الثعبان كما توحي الترجمة الحرفية، رغم كون مصادر بايثون التعليمية وتوثيقاتها تشير إلى كلًا من فرقة Monty Python والثعبان مثل مرجع لأصل التسمية، وكذلك الأمر من حيث الشق البرمجي، إذ تحمل كلمة بايثون معنيين أيضًا.
</p>

<p>
	يمكن أن نقول "تُشغّل بايثون برنامجًا" أو "ستعرض بايثون استثناءً"، والمقصود هنا هو مفسر بايثون -وهو البرنامج الفعلي المسؤول عن قراءة النصوص ضمن الملفات ذات اللاحقة "py." مُنفذًا التعليمات الواردة فيها؛ فعندما نقول "مفسر بايثون"، نقصد غالبًا "CPython"، وهو المفسر المُعتمد من قبل مؤسسة بايثون للبرمجيات Python Software Foundation. إذًا، CPython هو تنفيذ للغة بايثون، بمعنى أنه برمجية أُنشئت لتحقق مواصفات محددة، ولكن يوجد برمجيات غيرها؛ ففي حين أن المفسر CPython مكتوب بلغة البرمجة سي C، المفسر <code>Jython</code> مكتوبٌ بلغة جافا Java بغية تشغيل نصوص بايثون البرمجية القابلة للتشغيل المتبادل مع برامج جافا؛ أما <code>PyPy</code> فهو مترجم ديناميكي just-in-time compiler لبايثون والذي يترجم البرامج لدى تنفيذها، فهو مكتوبٌ بلغة بايثون.
</p>

<p>
	تُشغّل كل من هذه التنفيذات الشبفرات المصدرية المكتوبة بلغة البرمجة بايثون، وهي المقصودة لدى قولنا: "هذا برنامج بايثون" أو "<a href="https://academy.hsoub.com/python/" rel="">أتعلم بايثون</a>".ومن الناحية المثالية فإن أي مفسر بايثون قادر على تشغيل أي شيفرة مصدرية مكتوبة بلغة بايثون، أما في الواقع العملي فتوجد بعض حالات عدم التوافق البسيطة والاختلافات ما بين المفسرات، ولعل سبب تسمية CPython بالمفسر المرجعي للغة بايثون هو أنه في حال وجود اختلافات في كيفية تفسير شيفرة بايثون ما بين CPython وغيره من المفسرات، سيكون ما فسره CPython هو الصحيح والمُتفق عليه.
</p>

<h3>
	كنس المهملات Garbage Collection
</h3>

<p>
	كان على المبرمج سابقًا في لغات البرمجة القديمة توجيه البرنامج لتخصيص أو إلغاء تخصيص أو تحرير الذاكرة لبنى المعطيات حسب الحاجة، وقد كانت عملية تخصيص الذاكرة اليدوية هذه مصدرًا للعديد من الأخطاء، مثل تسريبات الذاكرة memory leaks (التي تحدث عند نسيان المبرمج لتحرير الذاكرة) أو أخطاء التحرير المزدوج للذاكرة double-free bugs (إذ يحرر المبرمج نفس الجزء من الذاكرة مرتين، متسببًا في تلف البيانات).
</p>

<p>
	تمنلك بايثون ميزة <a href="https://academy.hsoub.com/programming/javascript/%D9%83%D9%86%D8%B3-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%87%D9%85%D9%84%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r797/" rel="">تجميع وكنس المهملات</a> لتجنب هذه الأخطاء، والتي تعد أحد أشكال الإدارة التلقائية للذاكرة والتي تتعقّب التوقيت المناسب لتخصيص وتحرير الذاكرة نيابةً عن المبرمج. من الممكن النظر إلى تجميع المهملات مثل عملية إعادة تدوير للذاكرة، لكونها تتيح الذاكرة للبيانات الجديدة. فعلى سبيل المثال، لنكتب ما يلي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_8" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> someFunction</span><span class="pun">():</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'someFunction() called.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> someFunction</span><span class="pun">()</span><span class="pln">
someFunction</span><span class="pun">()</span><span class="pln"> called</span><span class="pun">.</span></pre>

<p>
	تخصص بايثون لدى استدعاء الدالة <code>()someFunction</code> الذاكرة للقائمة <code>['cat', 'dog', 'moose']</code>. وبالتالي ما من حاجة لمعرفة المبرمج عدد البايتات من الذاكرة المتوجب طلبها لأن بايثون تدير هذا الأمر نلقائيًا، إذ سيحرر مُجمّع المهملات المتغيرات المحلية بمجرد إعادة الدالة المُستدعاة، ما يجعل الذاكرة متاحةً لبيانات جديدة. إذًا، يجعل مفهوم تجميع المهملات من البرمجة أمرًا أسهل وأقل عرضة للأخطاء.
</p>

<h3>
	القيم المجردة Literals
</h3>

<p>
	القيمة المجردة هي نص ضمن الشيفرة المصدرية ذات قيمة ثابتة كما هي مكتوبة. ففي المثال التالي 42 هو قيمة صحيحة مجردة و <code>'Zophie'</code> هي سلسلة نصية مجردة.:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> len</span><span class="pun">(</span><span class="str">'Zophie'</span><span class="pun">)</span></pre>

<p>
	يمكن فهم القيم المجردة مثل قيم تظهر كما هي بحرفيتها مثل نص ضمن الشيفرة المصدرية، ولا يمكن إلا لأنواع البيانات المُعرّفة أصلًا في بايثون امتلاك قيم مجردة في الشيفرة المصدرية، وبالتالي ليس المتغير <code>age</code> قيمة مجردة. يبيّن الجدول 1 التالي بعض الأمثلة عن القيم المجردة في بايثون.
</p>

<table>
	<thead>
		<tr>
			<th>
				القيمة المجردة
			</th>
			<th>
				نوع البيانات
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				42
			</td>
			<td>
				عدد صحيح
			</td>
		</tr>
		<tr>
			<td>
				3.14
			</td>
			<td>
				عدد عشري
			</td>
		</tr>
		<tr>
			<td>
				1.4886191506362924e+36
			</td>
			<td>
				عدد عشري
			</td>
		</tr>
		<tr>
			<td>
				"""!Howdy"""
			</td>
			<td>
				سلسلة نصية
			</td>
		</tr>
		<tr>
			<td>
				'r'Green\Blue
			</td>
			<td>
				سلسلة نصية
			</td>
		</tr>
		<tr>
			<td>
				[]
			</td>
			<td>
				قائمة
			</td>
		</tr>
		<tr>
			<td>
				{'name': 'Zophie'}
			</td>
			<td>
				قاموس
			</td>
		</tr>
		<tr>
			<td>
				'b'\x41
			</td>
			<td>
				بايتات
			</td>
		</tr>
		<tr>
			<td>
				True
			</td>
			<td>
				بولياني
			</td>
		</tr>
		<tr>
			<td>
				None
			</td>
			<td>
				نوع فارغ NoneType
			</td>
		</tr>
	</tbody>
</table>

<p>
	قد يجادل بعض المعترضين في أن بعضًا من القيم لا يمثّل قيمًا مجردة استنادًا إلى التوثيق الرسمي للغة بايثون، فمن الناحية التقنية، <code>5-</code> ليست قيمة مجردة في بايثون لأن اللغة تعرّف رمز السالب (-) مثل عامل على القيمة المجردة 5، كما تُعد القيم <code>True</code> و <code>False</code> و <code>None</code> كلمات مفتاحية في بايثون وليست قيمًا مجردة، في حين أن <code>[]</code> و<code>{}</code> تسمى مُخرجات أو ذرات atoms اعتمادًا على جزء التوثيق الرسمي الذي تبحث ضمنه. بغض النظر عن ذلك، القيمة المجردة هي مصطلح شائع يستخدمه محترفو البرمجيات للدلالة على كل الأمثلة السابقة.
</p>

<h3>
	الكلمات المفتاحية Keywords
</h3>

<p>
	تمتلك كل لغة برمجة الكلمات المفتاحية الخاصة بها؛ وكلمات بايثون المفتاحية هي مجموعة من الأسماء المحجوزة للاستخدام مثل جزء من بناء اللغة والتي لا يمكن استخدامها أسماءً للمتغيرات (أي المعرّفات). على سبيل المثال، لا يمكنك تسمية أحد المتغيرات بالاسم <code>while</code> لأنها كلمة محجوزة للاستخدام في حلقات <code>while</code> التكرارية، وفيما يلي الكلمات المفتاحية المحجوزة في بايثون وفقًا للإصدار 3.9 منها.
</p>

<table>
	<thead>
		<tr>
			<th>
				and
			</th>
			<th>
				continue
			</th>
			<th>
				finally
			</th>
			<th>
				is
			</th>
			<th>
				raise
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				as
			</td>
			<td>
				def
			</td>
			<td>
				for
			</td>
			<td>
				lambda
			</td>
			<td>
				return
			</td>
		</tr>
		<tr>
			<td>
				assert
			</td>
			<td>
				del
			</td>
			<td>
				from
			</td>
			<td>
				None
			</td>
			<td>
				True
			</td>
		</tr>
		<tr>
			<td>
				async
			</td>
			<td>
				elif
			</td>
			<td>
				global
			</td>
			<td>
				nonlocal
			</td>
			<td>
				try
			</td>
		</tr>
		<tr>
			<td>
				await
			</td>
			<td>
				else
			</td>
			<td>
				if
			</td>
			<td>
				not
			</td>
			<td>
				while
			</td>
		</tr>
		<tr>
			<td>
				break
			</td>
			<td>
				except
			</td>
			<td>
				import
			</td>
			<td>
				or
			</td>
			<td>
				with
			</td>
		</tr>
		<tr>
			<td>
				class
			</td>
			<td>
				False
			</td>
			<td>
				in
			</td>
			<td>
				pass
			</td>
			<td>
				yield
			</td>
		</tr>
	</tbody>
</table>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_13" style=""><span class="kwd">def</span><span class="pln"> agregarDosN</span><span class="pun">ú</span><span class="pln">meros</span><span class="pun">(</span><span class="pln">primerN</span><span class="pun">ú</span><span class="pln">mero</span><span class="pun">,</span><span class="pln"> segundoN</span><span class="pun">ú</span><span class="pln">mero</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> primerN</span><span class="pun">ú</span><span class="pln">mero </span><span class="pun">+</span><span class="pln"> segundoN</span><span class="pun">ú</span><span class="pln">mero</span></pre>

<p>
	تهيمن اللغة الإنجليزية لسوء الحظ على <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AC%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">مجال البرمجة</a> بالنسبة للتعداد البالغ 6.5 مليار من غير الناطقين بها.
</p>

<h3>
	الكائنات Objects والقيم Values والنسخ Instances والهويات Identities
</h3>

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

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

<p>
	يُنشَأ الكائن بهوية، وهي رقم صحيح فريد من الممكن الإطلاع عليه باستدعاء الدالة <code>()id</code>. على سبيل المثال، لنكتب ما يلي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33805656</span></pre>

<p>
	يُخزّن المتغير <code>spam</code> كائنًا من نوع البيانات "قائمة"، قيمته تساوي <code>['cat', 'dog', 'moose']</code> أما هويته فهي <code>33805656</code>، رغم كون العدد الصحيح ID هذا يتغير في كل مرة يُنفّذ فيها البرنامج، وبالتالي ستكون القيمة على حاسوبك مختلفة عن هذه المعروضة هنا، ولكن بمجرد إنشاء الكائن، لن تتغير قيمة هويته طالما أن البرنامج قيد التشغيل، ورغم أن كلًا من هوية ونوع بيانات الكائن لا يتغيران أثناء تشغيل البرنامج، إلا أن قيمته قد تتغير، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_18" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">'snake'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'snake'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33805656</span></pre>

<p>
	وبذلك أصبحت القائمة تتضمّن أيضًا العنصر <code>'snake'</code>، ولكن وكما هو مبين من نتيجة استدعاء الدالة <code>(id(spam</code> أن هويتها لم تتغير وبقيت نفسها، ولكن ماذا لو كتبنا الشيفرات التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_20" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </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">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="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33838544</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_22" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Zophie'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33861824</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> spam
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33861824</span></pre>

<p>
	ومنه نجد أن هوية كل من المعرفين <code>spam</code> و <code>eggs</code> نفسها وتساوي <code>33861824</code>، لأنهما يتبعان لنفس كائن القاموس. الآن وبتغيير قيمة <code>spam</code> في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_24" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Zophie'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> spam
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Al'</span><span class="pln">  
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Al'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs  
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Al'</span><span class="pun">}</span></pre>

<p>
	ومنه نجد أن التغييرات على المتغير <code>spam</code> في السطر 1 قد ظهرت أيضًا على المتغير <code>eggs</code> في السطر 2، وسبب ذلك أن كلاهما يتبع لنفس الكائن.
</p>

<h2>
	مفهوم المتغيرات المجرد: الصندوق BOX مقابل العنوان LABEL
</h2>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="125957" href="https://academy.hsoub.com/uploads/monthly_2023_05/1st.png.a0ac87bcab862fcc35160d6b886ef429.png" rel=""><img alt="1st.png" class="ipsImage ipsImage_thumbnailed" data-fileid="125957" data-unique="nzrslpay9" src="https://academy.hsoub.com/uploads/monthly_2023_05/1st.png.a0ac87bcab862fcc35160d6b886ef429.png"> </a>
</p>

<p>
	شكل 1: تفيد العديد من المراجع بأنه من الممكن فهم المتغيرات على أنها صناديق تحتوي على قيم
</p>

<p>
	<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r221/" rel="">المتغيرات في بايثون</a> من الناحية التقنية هي مراجع وليست حاويات containers للقيم، وذلك بغض النظر عن نوع البيانات التي تحتويها. رغم بساطة مفهوم الصندوق إلا أنه منقوص، فبدلًا من فهم المتغيرات على أنها صناديق، يُفضّل فهمها مثل عناوين للكائنات في الذاكرة، والشكل 2 التالي يبين العناوين لأمثلة المتغيرين <code>spam</code> و <code>eggs</code> السابقين.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="125956" href="https://academy.hsoub.com/uploads/monthly_2023_05/2nd.png.8f28695260d3a2850fb74e10db29555b.png" rel=""><img alt="2nd.png" class="ipsImage ipsImage_thumbnailed" data-fileid="125956" data-unique="zq4r4dtt4" src="https://academy.hsoub.com/uploads/monthly_2023_05/2nd.png.8f28695260d3a2850fb74e10db29555b.png"> </a>
</p>

<p>
	شكل 2: من الممكن أيضًا فهم المتغيرات مثل عناوين للقيم
</p>

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

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

<p>
	يمكن استخدام العامل <code>is</code> لمقارنة فيما إذا كان لكائنين نفس الهوية، وبالمقابل يمكن استخدام العامل <code>==</code> للتحقق فقط من كون قيمتي الكائنين متطابقتين، وبالتالي التعبير <code>x is y</code> مكافئ لنظيره <code>(id(x) == id(y</code>. لنكتب ما يلي في الصدفة التفاعلية لنلاحظ الفرق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Zophie'</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"> eggs </span><span class="pun">=</span><span class="pln"> spam
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="kwd">is</span><span class="pln"> eggs  
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> eggs  
</span><span class="kwd">True</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Zophie'</span><span class="pun">}</span><span class="pln">  
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> fish  
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="kwd">is</span><span class="pln"> fish  
</span><span class="kwd">False</span></pre>

<p>
	إذ يشير المتغيران <code>spam</code> و<code>eggs</code> إلى نفس كائن القاموس (في السطر 1)، وبالتالي فهما متساويان بالقيمة والهوية.، بينما يشير المتغير <code>fish</code> إلى كائن قاموس آخر (في السطر 2)، رغم كونه يتضمن بيانات مطابقة لتلك الموجودة في المتغيرين <code>spam</code> و <code>eggs</code>. يعني تطابق البيانات أن للمتغير <code>fish</code> نفس القيمة كما في المتغيرين <code>spam</code> و <code>eggs</code>، إلا أنهما كائنان مختلفان بهويتين مختلفتين.
</p>

<h3>
	العناصر Items
</h3>

<p>
	ندعو في بايثون الكائن الموجود ضمن كائن حاوية مثل قائمة أو قاموس بالعنصر، فعلى سبيل المثال، السلسة النصية ضمن القائمة <code>['dog', 'cat', 'moose']</code> هي كائنات ولكننا ندعوها أيضًا بالعناصر.
</p>

<h3>
	الثابت Immutable والمتغير Mutable
</h3>

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

<p>
	جدول 2: بعض أنواع البيانات الثابتة والمتغيرة في بايثون
</p>

<table>
	<thead>
		<tr>
			<th>
				أنواع البيانات الثابتة
			</th>
			<th>
				أنواع البيانات المتغيرة
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				عدد صحيح
			</td>
			<td>
				قائمة
			</td>
		</tr>
		<tr>
			<td>
				عدد عشري
			</td>
			<td>
				قاموس
			</td>
		</tr>
		<tr>
			<td>
				قيمة بوليانية
			</td>
			<td>
				مجموعات
			</td>
		</tr>
		<tr>
			<td>
				سلسلة نصية
			</td>
			<td>
				مصفوفة بايت Bytearray
			</td>
		</tr>
		<tr>
			<td>
				مجموعة ثابتة Frozen set
			</td>
			<td>
				مصفوفة
			</td>
		</tr>
		<tr>
			<td>
				بايتات
			</td>
			<td>
				 
			</td>
		</tr>
		<tr>
			<td>
				صف Tuple
			</td>
		</tr>
	</tbody>
</table>

<p>
	فلو أعدت الكتابة في متغير ما، قد يبدو لك أنك قد غيرت قيمة الكائن الخاص به، كما في المثال التالي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_28" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="str">'hello'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="str">'hello'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="str">'goodbye'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="str">'goodbye'</span></pre>

<p>
	لكننا لم نغيّر هنا قيمة الكائن <code>'hello'</code> من <code>'hello'</code> إلى <code>'goodbye'</code>، فهما كائنان منفصلان، وكل ما فعلناه في الشيفرة السابقة هو مجرّد جعل المتغير <code>spam</code> يشير إلى الكائن <code>'goodbye'</code> بدلًا من <code>'hello'</code>، ويمكن التحقق من صحة أنهما فعلًا كائنين مستقلين باستخدام الدالة <code>()id</code> للحصول على هوية كل منهما:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="str">'hello'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">40718944</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="str">'goodbye'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">40719224</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33805576</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">'moose'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</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="str">'snake'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">[</span><span class="str">'snake'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33805576</span></pre>

<p>
	تعمل كلًا من الدالة <code>()append</code> (في السطر 1) وعملية الإسناد للعنصر (في السطر 2) على تعديل قيمة القائمة في مكانها (من أجل نفس الكائن بنفس الهوية)؛ فقد تغيرت قيمة القائمة، إلا أن هويتها قد بقيت كما هي 33805576؛ إما في حال استخدام العامل <code>+</code> لبناء تسلسل القائمة، فإننا ننشئ كائنًا جديدًا (ذو هوية جديدة) بديلًا عن ذلك السابق على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_34" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> spam </span><span class="pun">+</span><span class="pln"> </span><span class="pun">[</span><span class="str">'rat'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">[</span><span class="str">'snake'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rat'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33840064</span></pre>

<p>
	ومنه نجد أن بناء تسلسل القائمة وفق الطريق السابقة (باستخدام العامل <code>+</code>) قد أنشأ قائمة جديدة بهوية جديدة، وبمجرد حدوث ذلك يُحرّر مُجمّع المهملات القائمة القديمة من الذاكرة. لمعرفة التوابع والعمليات التي تعدل قيم الكائنات مع الحفاظ على هويتها وتلك التي تغيرها، عليك الرجوع إلى توثيق بايثون، ولكن يمكنك أخذ القاعدة التالية بالحسبان: إذا رأيت قيمةً مجردةً ضمن الشيفرة المصدرية، مثل <code>['rat']</code> في المثال السابق، فعندها سينشئ بايثون كائنًا جديدًا بهوية جديدة غالبًا، في حين أن التوابع المُستدعاة مع استخدام الكائن بمثابة وسيط لها، مثل التابع <code>()append</code>، فغالبًا ما تعدّل قيمة الكائن مُحافظةً على هويته.
</p>

<p>
	في حال التعامل مع <a href="https://academy.hsoub.com/programming/general/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%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-r1726/#%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-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9" rel="">أنواع البيانات الثابتة</a> مثل الأعداد الصحيحة والسلاسل النصية والصفوف، ستكون عمليات الإسناد هي الأبسط. لنكتب على سبيل المثال ما يلي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_36" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Goodbye'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33827584</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33863820</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish </span><span class="pun">=</span><span class="pln"> fish </span><span class="pun">+</span><span class="pln"> </span><span class="str">', world!'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish
</span><span class="str">'Hello, world!'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">fish</span><span class="pun">)</span><span class="pln">
</span><span class="lit">33870056</span><span class="pln">
</span><span class="lit">3</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fish</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="str">'J'</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> </span><span class="str">'str'</span><span class="pln"> object does </span><span class="kwd">not</span><span class="pln"> support item assignment</span></pre>

<p>
	السلاسل النصية ثابتة، بمعني أنه من غير الممكن تغيير قيمة السلسلة نفسها، ففي حين يبدو أننا قد غيرنا قيمة السلسة النصية في المتغير <code>fish</code> من القيمة <code>'Goodbye'</code> إلى القيمة <code>'Hello'</code> (في السطر رقم 1)، إلا أنّه في الواقع قد غيّرنا قيمته إلى كائن سلسلة نصية جديدة ذو هوية جديدة؛ وعلى نحوٍ مشابه، ينشئ التعبير البرمجي باستخدام بناء تسلسل القائمة كائن قائمة جديد (كما في السطر 2) ذو هوية جديدة. لا يُسمَح في الإصدار 3 من بايثون تغيير السلاسل النصية باستخدام عمليات الإسناد دون تغيير هوية الكائن.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_38" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</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">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">)</span><span class="pln">   
</span><span class="lit">39560896</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">])</span><span class="pln"> 
</span><span class="lit">40654152</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">[</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">]</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> </span><span class="str">'tuple'</span><span class="pln"> object does </span><span class="kwd">not</span><span class="pln"> support item assignment</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">].</span><span class="pln">append</span><span class="pun">(</span><span class="lit">8</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">].</span><span class="pln">append</span><span class="pun">(</span><span class="lit">10</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs
</span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</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">4</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">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">)</span><span class="pln">    
</span><span class="lit">39560896</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">[</span><span class="lit">2</span><span class="pun">])</span><span class="pln"> 
</span><span class="lit">40654152</span></pre>

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

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="125955" href="https://academy.hsoub.com/uploads/monthly_2023_05/3rd.png.b94ed90ad8a3c1f806dd3b2850746d68.png" rel=""><img alt="3rd.png" class="ipsImage ipsImage_thumbnailed" data-fileid="125955" data-unique="6e0fw0oc4" src="https://academy.hsoub.com/uploads/monthly_2023_05/3rd.png.b94ed90ad8a3c1f806dd3b2850746d68.png"> </a>
</p>

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

<h3>
	الفهارس Indexes والمفاتيح Keys والقيم المعماة Hashes
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_42" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
</span><span class="str">'cat'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">[-</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
</span><span class="str">'dog'</span></pre>

<p>
	في المثال السابق، الرقم 0 هو فهرس، إذ أن الفهرس الأول هو 0 وليس 1، إذ تستخدم بايثون ومعظم لغات البرمجة الصفر بدايةً للفهارس، أما اللغات التي تعتمد 1 بدايةً للفهارس فهي نادرة وأشهرها لغتي Lua و R، كما أن بايثون تدعم الفهارس السالبة، إذ يشير مثلًا "1-" إلى العنصر الأخير في القائمة، في حين يشير "2-" إلى العنصر ما قبل الأخير، وهكذا. يمكن فهم الفهرس السالب بالشكل <code>[spam[–n</code> مكافئًا لاستخدام <code>[spam[len(spam) – n</code>.
</p>

<p>
	<strong>ملاحظة:</strong> قال عالم الحاسوب والمغني وكاتب الأغاني ستان كيلي-بوتل Stan Kelly-Bootle مرة مازحًا: أيجب أن تبدأ فهارس المصفوفات من الصفر أو الواحد؟ كان اقتراحي بمثابة حلٍ وسطي أن تبدأ من 0.5 ولكنه رفض دون سبب وجيه على ما أعتقد.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_44" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
</span><span class="str">'moose'</span></pre>

<p>
	: كما يمكن استخدام الفهارس على قيم غير القوائم، مثل السلاسل النصية بغية الحصول على محارف معينة من السلسلة، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_46" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="str">'Hello, world'</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln">
</span><span class="str">'H'</span></pre>

<p>
	أما <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%B5%D9%81%D9%88%D9%81%D8%8C-%D8%A7%D9%84%D9%85%D8%AC%D9%85%D9%88%D8%B9%D8%A7%D8%AA-%D9%88%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-r226/" rel="">قواميس بايثون</a>، فتُرتّب على هيئة أزواج "مفتاح-قيمة"، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_48" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Zophie'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">]</span><span class="pln">
</span><span class="str">'Zophie'</span></pre>

<p>
	تنحصر فهارس القوائم بكونها أعداد صحيحة، لكن فهارس قواميس بايثون هي مفاتيح، يمكن أن تكون أي قيمة قابلة للتعمية؛ فالقيمة المعماة هي عدد صحيح شبيه بالبصمة الخاصة بالقيمة، إذ أن القيمة المعماة الخاصة بكائن ما لا تتغير طوال فترة وجود الكائن، وللكائنات المتماثلة في قيمها، قيم معماة متماثلة أيضًا. في مثالنا السابق، السلسلة النصية <code>'name'</code> هي مفتاح القيمة <code>'Zophie'</code>. وتعيد الدالة <code>()hash</code> القيمة المعماة للكائنات القابلة للتعمية. الكائنات الثابتة مثل الأعداد الصحيحة والأعداد العشرية والسلاسل النصية والصفوف قابلة للتعمية، في حين أن القوائم وغيرها من الكائنات المتغيرة غير قابلة للتعمية. لنكتب ما يلي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_50" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</span><span class="pun">(</span><span class="str">'hello'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">-</span><span class="lit">1734230105925061914</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln">
</span><span class="lit">42</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</span><span class="pun">(</span><span class="lit">3.14</span><span class="pun">)</span><span class="pln">
</span><span class="lit">322818021289917443</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</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="lit">2528502973977326415</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</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="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> unhashable type</span><span class="pun">:</span><span class="pln"> </span><span class="str">'list'</span></pre>

<p>
	تُستخدم المفاتيح المعماة لإيجاد العناصر المخزنة في القواميس وغيرها من <a href="https://academy.hsoub.com/programming/general/%D9%87%D9%8A%D8%A7%D9%83%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-data-structures/" rel="">هياكل البيانات</a>، ولهذا لا يمكن استخدام قائمة متغيرة مثل مفتاح لقاموس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_52" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> d</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="pun">=</span><span class="pln"> </span><span class="str">'some value'</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> unhashable type</span><span class="pun">:</span><span class="pln"> </span><span class="str">'list'</span></pre>

<p>
	تختلف القيمة المعماة عن الهوية، فلو كان لدينا كائنان مختلفان يتضمنان نفس القيمة، سيكون لكل منهما هويته الخاصة، أما القيمة المعماة فستكون نفسها لكليهما. لنكتب على سبيل المثال ما يلي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_54" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">a</span><span class="pun">),</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">37111992</span><span class="pun">,</span><span class="pln"> </span><span class="lit">37112136</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"> id</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">False</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</span><span class="pun">(</span><span class="pln">a</span><span class="pun">),</span><span class="pln"> hash</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(-</span><span class="lit">3478972040190420094</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">3478972040190420094</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> hash</span><span class="pun">(</span><span class="pln">a</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> hash</span><span class="pun">(</span><span class="pln">b</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">True</span></pre>

<p>
	يمتلك الصفان المُشار إليهما بواسطة <code>a</code> و <code>b</code> هويتين مختلفتين كما هو موضح في السطر 1 من الشيفرة السابقة، ولكن كونهما يحتويان على قيمتين متطابقتين فالقيم المعماة لهما متساوية كما هو موضح في السطر 2. يكون الصف قابلًا للتعمية في حال احتوائه على عناصر قابلة للتعمية، وبما أنه لا يمكن استخدام سوى عناصر قابلة للتعمية مثل مفاتيح للقواميس، فمن غير الممكن استخدام صفٍ يحتوي على قائمة غير قابلة للتعمية مثل مفتاح. لنكتب ما يلي ضمن الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_56" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> tuple1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> tuple2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'apple'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'orange'</span><span class="pun">])</span><span class="pln"> 
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </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"> spam</span><span class="pun">[</span><span class="pln">tuple1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'a value'</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">[</span><span class="pln">tuple2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'another value'</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> unhashable type</span><span class="pun">:</span><span class="pln"> </span><span class="str">'list'</span></pre>

<p>
	نلاحظ أن الصف <code>tuple1</code> قابل للتعمية، في حين أن الصف <code>tuple2</code> يتضمن قائمة فهو غير قابل للتعمية مثلها.
</p>

<h3>
	أنواع الحاويات Containers والسلاسل المفهرسة بأرقام Sequences والمفهرسة بمفاتيح Mapping والمجموعات set
</h3>

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

<p>
	السلسلة المفهرسة بأرقام هي كائن يحتوي على أي من أنواع بيانات الحاويات، ذو قيم مرتبة يمكن الوصول إليها اعتمادًا على فهارس من أعداد صحيحة. السلاسل النصية والصفوف والقوائم والمتغيرات من النوع <code>byte</code> هي أنواع بيانات من نوع السلاسل المفهرسة بأرقام، إذ يمكن الوصول إلى القيم في هذا النوع من الكائنات باستخدام عامل الفهرسة (القوس المعقوف <code>[</code> و <code>]</code>)، كما يمكن تمرير الفهرس إلى الدالة <code>()len</code>. يُقصد بكلمة "مرتبة" وجود ما يمكن تسميته القيمة الأولى والثانية وهكذا، فعلى سبيل المثال، لا يمكن أن تكون قيمتا القائمتين التاليتين متساويتين لأنهما مرتبتان على نحوٍ مختلف:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_58" style=""><span class="pun">&gt;&gt;&gt;</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">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="pun">==</span><span class="pln"> </span><span class="pun">[</span><span class="lit">3</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">1</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">False</span></pre>

<p>
	السلسلة المفهرسة بمفاتيح mapping هي كائن يحتوي على أي من أنواع بيانات الحاويات الذي يستخدم المفاتيح عوضًا عن الفهرس. يمكن لهذا النوع من السلاسل أن يكون مرتبًا أو غير مرتبًا؛ فالقواميس في الإصدار 3.4 من بايثون والإصدارات الأقدم غير مرتبة لعدم وجود ما يسمى أول أو آخر زوج "مفتاح-قيمة" في القاموس، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_60" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </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="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'d'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">}</span><span class="pln">  </span><span class="com"># This is run from CPython 3.5.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">.</span><span class="pln">keys</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="str">'d'</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"> spam</span><span class="pun">[</span><span class="str">'e'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">.</span><span class="pln">keys</span><span class="pun">())</span><span class="pln">
</span><span class="pun">[</span><span class="str">'e'</span><span class="pun">,</span><span class="pln"> </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="str">'d'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">]</span></pre>

<p>
	لا توجد ضمانات للحصول على العناصر من القواميس بترتيب متسق في الإصدارات القديمة من بايثون، ونتيجةً للطبيعة غير الترتيبية للقواميس، سيكون لقاموسين مجردين يحتويان على نفس أزواج "مفتاح-قيمة" ولكن بترتيب مختلف قيمتان متساويتان:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_62" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="str">'a'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">}</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">{</span><span class="str">'c'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">True</span></pre>

<p>
	ولكن بدءًا من الإصدار 3.6 من المفسر <code>CPython</code> أصبحت القواميس تحتفظ بترتيب إدخال أزواج "مفتاح قيمة"، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_64" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </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="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'d'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">}</span><span class="pln">  </span><span class="com"># This is run from CPython 3.6.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">spam</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"> spam</span><span class="pun">[</span><span class="str">'e'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">spam</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="str">'e'</span><span class="pun">]</span></pre>

<p>
	وتعد هذه إحدى الميزات الموجودة في الإصدار 3.6 من المفسّر CPython وليست موجودة في كافة مفسرات الإصدار 3.6 من بايثون، بينما تدعم كافة مفسرات الإصدار 3.7 من بايثون القواميس الترتيبية، والتي أصبحت معيارية في لغة بايثون في الإصدار 3.7. إلا أن حقيقة كون قاموس ما ترتيبي لا يعني أنه من الممكن الوصول إلى عناصره باستخدام فهارس من أعداد صحيحة، فمثلًا لا يُقيّم التعبير <code>[spam[0</code> على أنه العنصر الأول من القاموس الترتيبي (فيما عدا حالة كون مفتاح العنصر الأول من القاموس هو فعلًا 0). تعد القواميس الترتيبية أيضًا متطابقة إذا كانت تحتوي على نفس أزواج "مفتاح-قيمة"، حتى ولو كانت هذه الأزواج بترتيب مختلف في كل قاموس.
</p>

<p>
	تتضمّن الوحدة <code>collections</code> العديد من السلاسل المفهرسة بمفاتيح الأخرى بما يتضمن <code>OrderedDict</code> (والتي تمثّل القواميس التي تحافظ على الترتيب دائمًا) و <code>ChainMap</code> (المُستخددمة لتجميع عدة قواميس معًا) و <code>Counter</code> (التي تُخزّن العناصر مثل مفاتيح للقواميس وعددها على أنها قيم فيه) و <code>UserDict</code>، وجميعها موصوفة ضمن <a href="https://docs.python.org/3/library/collections.htm" rel="external nofollow">توثيق بايثون</a>.
</p>

<h3>
	التوابع السحرية
</h3>

<p>
	التوابع السحرية والتي تسمّى Dunder methods أو magic methods هي توابع خاصة في بايثون تبدأ أسماء كل منها وتنتهي بشرطتين سفليتين، وتُستخدم هذه التوابع لزيادة تحميل العامل. يأتي مصطلح Dunder اختصارًا للعبارة double underscore أي "شرطتين سفليتين". لعل أشهر التوابع السحرية هو <code>()__int__</code> والتي تقرأ بالشكل "dunder init dunder" أي "شرطتان سفليتان int شرطتان سفليتان" أو فقط "int"، والذي يعمل على تهيئة الكائنات. تتضمن بايثون عشراتٍ من التوابع السحرية.
</p>

<h3>
	الوحدات والحزم
</h3>

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

<p>
	الحزمة Package هي مجموعة من الوحدات التي نُشكّلها عبر إنشاء ملف باسم "init<strong>.py</strong>" ضمن المجلد المطلوب، إذ نستخدم اسم هذا المجلد اسمًا للحزمة، ويمكن أن تحتوي الحزم على وحدات متعددة (وهي ملفات ذات امتداد "py.") أو حتى حزم أخرى (أي مجلدات أخرى تحتوي على ملفات "init<strong>.py</strong>").
</p>

<h3>
	الكائنات من الدرجة الأولى First-Class Objects والقابلة للاستدعاء Callables
</h3>

<p>
	لا تقتصر الأشياء القابلة للاستدعاء في بايثون على الدوال والتوابع، بل أي كائن يتضمّن عامل الاستدعاء -أي رمز القوسين الهلاليين ()- هو كائن قابل للاستدعاء. على سبيل المثال، لو كان لدينا التعبير <code>()def hello</code>، يمكن فهم هذه الشيفرة على أنها متغير يدعى <code>hello</code> مُتضمنًا كائن دالة، إذ سيستدعي استخدام عامل الاستدعاء لهذا المتغير الدالة في المتغير بالشكل: <code>()hello</code>.
</p>

<p>
	الأصناف classes هي من مفاهيم <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة كائنية التوجه</a>، ويمثّل الصنف مثالًا على كائن قابل للاستدعاء دون أن يكون دالة أو تابع، فعلى سبيل المثال، يمكن استدعاء صنف التاريخ <code>date</code> الموجود في الوحدة <code>datatime</code> باستخدام عامل الاستدعاء كما في الشيفرة <code>(datetime.date(2020, 1, 1</code>، وبمجرد استدعاء كائن الصنف، تعمل الشيفرة الموجودة ضمن التابع <code>()__int__</code> من الصنف.
</p>

<p>
	تعد الدوال من كائنات الدرجة الأولى في بايثون، ما يعني أنه يمكن تخزينها ضمن متغيرات وتمريرها مثل وسطاء عند استدعاء الدوال الأخرى واستخدامها مثل قيم مُعادة للدوال الأخرى أو تنفيذ كل ما يمكن تنفيذه مع أي كائن آخر، وبالتالي يمكن فهم التعليمة <code>def</code> الخاصة بتعريف الدوال على أنها عملية إسناد لكائن الدالة إلى متغير ما، إذ يمكن مثلًا إنشاء دالة <code>()spam</code> لتُستدعى لاحقًا على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_66" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">():</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Spam! Spam! Spam!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span></pre>

<p>
	كما يمكن إسناد كائن الدالة <code>()spam</code> إلى متغيراتٍ أخرى، وبمجرد استدعاء المتغير الذي أسندنا الدالة إليه، ينفذ بايثون هذه الدالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_68" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> spam
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span></pre>

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

<p>
	ولعل الاستخدام الأكثر شيوعًا للدوال من الدرجة الأولى هو إمكانية تمرير الدوال مثل وسطاء لدوال أخرى، إذ يمكن مثلًا تعريف دالة باسم <code>()callTwicw</code> لنمرر لها أي دالة نريد استدعائها مرتين، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9913_70" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> callTwice</span><span class="pun">(</span><span class="pln">func</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     func</span><span class="pun">()</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     func</span><span class="pun">()</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> callTwice</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span><span class="pln">
</span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span><span class="pln"> </span><span class="typ">Spam</span><span class="pun">!</span></pre>

<p>
	كما يمكن الاكتفاء باستدعاء الدالة <code>()spam</code> مرتين بكتابتها مرتين في الشيفرة المصدرية، إلا أنه يمكن تمرير التابع المراد استدعائه مرتين إلى الدالة <code>()callTwicw</code> عوضًا عن كتابة اسم الدالة مرتين في الشيفرة المصدرية.
</p>

<h2>
	الخلاصة
</h2>

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

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

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

<p>
	ترجمة -وبتصرف- لجزء من الفصل السابع "المصطلحات البرمجية" من كتاب <a href="http://inventwithpython.com/beyond/chapter1.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%B7%D8%B1%D9%82-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%85%D9%8A%D8%B3-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA%D9%87%D8%A7-%D9%88%D8%B9%D8%A7%D9%85%D9%84%D9%87%D8%A7-%D8%A7%D9%84%D8%AB%D9%84%D8%A7%D8%AB%D9%8A-r1981/" rel="">الطرق البايثونية في استخدام قواميس بايثون ومتغيراتها وعاملها الثلاثي</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1906/" rel="">مفهوم الدوال Functions في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81-%D8%AA%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%88%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D9%84%D8%B1%D8%AD%D9%84%D8%AA%D9%83-%D9%81%D9%8A-%D8%B9%D8%A7%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r206/" rel="">كيف تتعلم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/learn-programming/" rel="">تعلم البرمجة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1982</guid><pubDate>Sun, 21 May 2023 13:01:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x637;&#x631;&#x642; &#x627;&#x644;&#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;&#x64A;&#x629; &#x641;&#x64A; &#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x642;&#x648;&#x627;&#x645;&#x64A;&#x633; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x648;&#x645;&#x62A;&#x63A;&#x64A;&#x631;&#x627;&#x62A;&#x647;&#x627; &#x648;&#x639;&#x627;&#x645;&#x644;&#x647;&#x627; &#x627;&#x644;&#x62B;&#x644;&#x627;&#x62B;&#x64A;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%B7%D8%B1%D9%82-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D9%82%D9%88%D8%A7%D9%85%D9%8A%D8%B3-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA%D9%87%D8%A7-%D9%88%D8%B9%D8%A7%D9%85%D9%84%D9%87%D8%A7-%D8%A7%D9%84%D8%AB%D9%84%D8%A7%D8%AB%D9%8A-r1981/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_05/--------.png.a7ab2a1601bc4cb4f07f923c5eecdbfc.png" /></p>
<p>
	سنقدم في هذا المقال العديد من الطرق الشائعة لكتابة شيفرات بايثون الاصطلاحية إلى جانب نظيراتها من الطرق غير البايثونية فيما يتعلق بقواميس بايثون والتعامل مع المتغيرات وعاملها الثلاثي.
</p>

<p>
	تُعد القواميس dictionaries نواة العديد من برامج بايثون نظرًا للمرونة التي توفرها أزواج القيم المفتاحية key-value pairs عبر ربط أجزاء البيانات ببعضها بعضًا، وبالتالي من المفيد أن تتعلم حول اصطلاحات قواميس بايثون الأكثر استخدامًا في الشيفرات، ويمكنك مراجعها بقراءة مقال <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>.
</p>

<h2>
	استخدام التابعين ()get و ()setdefault للتعامل مع القواميس
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_8" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'dogs'</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"> </span><span class="kwd">if</span><span class="pln"> </span><span class="str">'cats'</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> numberOfPets</span><span class="pun">:</span><span class="pln"> </span><span class="com"># Check if 'cats' exists as a key.</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I have'</span><span class="pun">,</span><span class="pln"> numberOfPets</span><span class="pun">[</span><span class="str">'cats'</span><span class="pun">],</span><span class="pln"> </span><span class="str">'cats.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I have 0 cats.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
I have </span><span class="lit">0</span><span class="pln"> cats</span><span class="pun">.</span></pre>

<p>
	تتحقق الشيفرة السابقة من وجود السلسلة النصية <code>cats</code> مثل مفتاح ضمن القاموس المسمى <code>numberOfPets</code>؛ فإذا كانت كذلك فعلًا، يُطبع محتوى القاموس الموافق لهذا المفتاح باستخدام التعليمة <code>['numberOfPets['cats</code> مثل جزء من الرسالة المعروضة للمستخدم باستخدام الدالة <code>()print</code>؛ وفي حال عدم وجود هذا المفتاح تُطبع عبارة باستخدام دالة <code>()print</code> أخرى دون الوصول إلى القاموس numberOfPets<code>كون المفتاح غير موجود وبالتالي لا تسبب بوقوع الخطأ</code>KeyError`.
</p>

<p>
	تمتلك قواميس بايثونتابع <code>()get</code>، الذي يسمح بتحديد قيمة افتراضية لتعاد في حال طلب مفتاح غير موجود في القاموس. والشيفرة البايثونية التالية تكافئ الشيفرة في المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'dogs'</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"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I have'</span><span class="pun">,</span><span class="pln"> numberOfPets</span><span class="pun">.</span><span class="pln">get</span><span class="pun">(</span><span class="str">'cats'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">),</span><span class="pln"> </span><span class="str">'cats.'</span><span class="pun">)</span><span class="pln">
I have </span><span class="lit">0</span><span class="pln"> cats</span><span class="pun">.</span></pre>

<p>
	يتحقق الاستدعاء <code>(numberOfPets.get('cats', 0</code> من كون المفتاح <code>cats</code> موجودًا في القاموس <code>numberOfPets</code>، فإذا كان موجودًا فعلًا يعيد الاستدعاء القيمة من القاموس الموافقة للمفتاح <code>cats</code>، وإلا يعيد الاستدعاء الوسيط الثاني وهو في حالتنا <code>0</code>. إذًا، يمثّل استخدام التابع <code>()get</code> لتحديد قيمة افتراضية لتعاد في حال استدعاء مفتاح غير موجود في القاموس طريقةً أقصر وأكثر مقروئية من استخدام العبارة الشرطية <code>if-else</code>.
</p>

<p>
	قد ترغب بالمقابل بتعيين قيمة افتراضية في حال عدم وجود مفتاح ما. على سبيل المثال، بفرض أن القاموس <code>numberOfPets</code> لا يتضمن المفتاح <code>'cats'</code>، ستتسبب التعليمة <code>numberOfPets['cats'] += 10</code> بخطأ من النوع <code>KeyError</code>، وقد ترغب بإضافة شيفرة مهمتها التحقق من غياب مفتاح محدد مُعينةً قيمة افتراضية على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_12" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'dogs'</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"> </span><span class="kwd">if</span><span class="pln"> </span><span class="str">'cats'</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> numberOfPets</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     numberOfPets</span><span class="pun">[</span><span class="str">'cats'</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="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets</span><span class="pun">[</span><span class="str">'cats'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets</span><span class="pun">[</span><span class="str">'cats'</span><span class="pun">]</span><span class="pln">
</span><span class="lit">10</span></pre>

<p>
	ولكن بما أن هذا النمط شائع الاستخدام أيضًا، فالقواميس تتضمن تابعًا أكثر بايثونية وهو <code>()setdefault</code>. تكافئ الشيفرة التالية تلك الموجودة في المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_14" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'dogs'</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"> numberOfPets</span><span class="pun">.</span><span class="pln">setdefault</span><span class="pun">(</span><span class="str">'cats'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="com"># Does nothing if 'cats' exists.</span><span class="pln">
</span><span class="lit">0</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets</span><span class="pun">[</span><span class="str">'cats'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> numberOfPets</span><span class="pun">[</span><span class="str">'cats'</span><span class="pun">]</span><span class="pln">
</span><span class="lit">10</span></pre>

<p>
	فبدلًا من استخدام جملة <code>if</code> شرطية للتحقق من وجود مفتاح ما في قاموس وتعيين قيمة افتراضية في حال غيابه، استخدم التابع <code>()setdefault</code>.
</p>

<h2>
	استخدام الصنف collections.defaultdict لتعيين قيم القواميس الافتراضية
</h2>

<p>
	يتيح استخدام الصنف <code>collections.defaultdict</code> إمكانية التخلص التام من أخطاء <code>KeyError</code>، إذ يُمكّنك من إنشاء قاموس افتراضي عن طريق استيراد الوحدة <code>collections</code> واستدعاء الدالة <code>()collections.defaultdict</code> مُمررًا إليها نمط معطيات تختاره ليكون قيمةً افتراضية. على سبيل المثال، في حال تمرير الدالة <code>int</code> مثل وسيط إلى الدالة <code>()collections.defaultdict</code> تكون قد أنشأت كائنًا شبيهًا بالقاموس dictionary-like object يستخدم القيمة <code>0</code> قيمةً افتراضية في حال طلب مفاتيح غير موجودة في القاموس. دعنا نكتب التالي في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> collections
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores </span><span class="pun">=</span><span class="pln"> collections</span><span class="pun">.</span><span class="pln">defaultdict</span><span class="pun">(</span><span class="pln">int</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores
defaultdict</span><span class="pun">(&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'int'</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="pun">{})</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores</span><span class="pun">[</span><span class="str">'Al'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="com"># No need to set a value for the 'Al' key first.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores
defaultdict</span><span class="pun">(&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'int'</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="pun">{</span><span class="str">'Al'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">})</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores</span><span class="pun">[</span><span class="str">'Zophie'</span><span class="pun">]</span><span class="pln"> </span><span class="com"># No need to set a value for the 'Zophie' key first.</span><span class="pln">
</span><span class="lit">0</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores</span><span class="pun">[</span><span class="str">'Zophie'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">40</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> scores
defaultdict</span><span class="pun">(&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'int'</span><span class="pun">&gt;,</span><span class="pln"> </span><span class="pun">{</span><span class="str">'Al'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Zophie'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">40</span><span class="pun">})</span></pre>

<p>
	مرّرنا في الشيفرة السابقة الدالة <code>()int</code> ولم نستدعيها، وهذا سبب إهمالنا لأقواسها إذ كتبناها بالشكل <code>int</code> ضمن استدعاء الدالة <code>(collections.defaultdict(int</code>. يمكن تمرير الدالة <code>list</code> مثل وسيط وبالتالي استخدام قائمة فارغة بمثابة قيمة افتراضية للقاموس، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_18" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> collections
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> booksReadBy </span><span class="pun">=</span><span class="pln"> collections</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="pun">&gt;&gt;&gt;</span><span class="pln"> booksReadBy</span><span class="pun">[</span><span class="str">'Al'</span><span class="pun">].</span><span class="pln">append</span><span class="pun">(</span><span class="str">'Oryx and Crake'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> booksReadBy</span><span class="pun">[</span><span class="str">'Al'</span><span class="pun">].</span><span class="pln">append</span><span class="pun">(</span><span class="str">'American Gods'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">booksReadBy</span><span class="pun">[</span><span class="str">'Al'</span><span class="pun">])</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">booksReadBy</span><span class="pun">[</span><span class="str">'Zophie'</span><span class="pun">])</span><span class="pln"> </span><span class="com"># The default value is an empty list.</span><span class="pln">
</span><span class="lit">0</span></pre>

<p>
	إذًا، في الحالات التي نحتاج فيها إلى قيمة افتراضية لكل احتمالية ممكنة للمفاتيح، فمن الأسهل استخدام الدالة <code>()collections.defaultdict</code> بدلًا من استخدام قاموس عادي واستدعاء التابع <code>()setdefault</code>.
</p>

<h2>
	استخدام القواميس بدلا من العبارة Switch
</h2>

<p>
	تمتلك <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> مثل لغة جافا العبارة البرمجية <code>switch</code>، والتي تعد أحد أنواع العبارة الشرطية <code>if-elif-else</code>، إذ أنها تشغِّل الشيفرة بناءً على القيمة التي يتضمنها متغير معين من بين مجموعة قيم، أما لغة بايثون فلا تتضمن العبارة <code>switch</code> ما يجعل مبرمجي بايثون يكتبون في بعض الحالات شيفراتٍ كما في المثال التالي، والذي يشغّل مجموعة من تعليمات الإسناد على ضوء القيمة التي يتضمنها المتغير <code>season</code> من بين مجموعة قيم، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_20" style=""><span class="com"># All of the following if and elif conditions have "season ==":</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> season </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Winter'</span><span class="pun">:</span><span class="pln">
    holiday </span><span class="pun">=</span><span class="pln"> </span><span class="str">'New Year\'s Day'</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> season </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Spring'</span><span class="pun">:</span><span class="pln">
    holiday </span><span class="pun">=</span><span class="pln"> </span><span class="str">'May Day'</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> season </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Summer'</span><span class="pun">:</span><span class="pln">
    holiday </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Juneteenth'</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> season </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Fall'</span><span class="pun">:</span><span class="pln">
    holiday </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Halloween'</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
    holiday </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Personal day off'</span></pre>

<p>
	لا يمكن عدّ الشيفرة السابقة غير بايثونية تمامًا، لكنها طريقة طويلة قليلًا، ومن الجدير بالذكر هنا أن عبارة <code>switch</code> في <a href="https://academy.hsoub.com/programming/java/" rel="">لغة جافا</a> تفرض في سياقها استخدام تعليمة <code>break</code> في نهاية كل من كتلها، وبدونها سيتابع البرنامج تنفيذ الكتلة التالية الخاصة بالحالة التالية لقيمة المتغير، وبالتالي يمثّل نسيان استخدام التعليمة <code>break</code> مصدرًا شائعًا للأخطاء. في المقابل، تتكرر العبارات <code>if-elif</code> في مثالنا السابق، وهذا ما يجعل بعض المبرمجين يفضلون إنشاء قاموس بدلًا عنها. فيما يلي صيغة بايثونية مختصرة لنفس المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_22" style=""><span class="pln">holiday </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="str">'Winter'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'New Year\'s Day'</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'Spring'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'May Day'</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'Summer'</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Juneteenth'</span><span class="pun">,</span><span class="pln">
           </span><span class="str">'Fall'</span><span class="pun">:</span><span class="pln">   </span><span class="str">'Halloween'</span><span class="pun">}.</span><span class="pln">get</span><span class="pun">(</span><span class="pln">season</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Personal day off'</span><span class="pun">)</span></pre>

<p>
	تتضمن الشيفرة السابقة تعليمة إسناد واحدة، إذ تمثّل القيمة المُخزّنة في المتغير <code>holiday</code> القيمة المعادة من استدعاء التابع <code>()get</code>، الذي يعيد القيمة الموافقة للمفتاح المُعيّن في المتغير <code>season</code>، وفي حال كون المفتاح المطلوب غير موجود، سيعيد التابع <code>()get</code> القيمة الافتراضية <code>'Personal day off'</code>. جعل استخدام قاموس من الشيفرة مختصرة، إلا أنها قد تكون أصعب قليلًا للقراءة، ويعود القرار حول استخدامها من عدمه لك.
</p>

<h2>
	التعابير الشرطية: عامل بايثون الثلاثي القبيح
</h2>

<p>
	تعمل العوامل الثلاثية Ternary operators (والتي تُسمّى في بايثون رسميًا بالتعابير البرمجية الشرطية أو تعابير الانتقاء الثلاثية) على تقييم تعبير ما إلى إحدى قيمتين بناءً على شرط ما، وهذا ما نفعله عادةً باستخدام التعبير البايثوني <code>if-else</code>، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_24" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> condition </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> condition</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access granted'</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     message </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access denied'</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> message
</span><span class="str">'Access granted'</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> valueIfTrue </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access granted'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> valueIfFalse </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access denied'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> condition </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> message </span><span class="pun">=</span><span class="pln"> valueIfTrue </span><span class="kwd">if</span><span class="pln"> condition </span><span class="kwd">else</span><span class="pln"> valueIfFalse
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> message
</span><span class="str">'Access granted'</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">valueIfTrue </span><span class="kwd">if</span><span class="pln"> condition </span><span class="kwd">else</span><span class="pln"> valueIfFalse</span><span class="pun">)</span><span class="pln">
</span><span class="str">'Access granted'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> condition </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">False</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> message </span><span class="pun">=</span><span class="pln"> valueIfTrue </span><span class="kwd">if</span><span class="pln"> condition </span><span class="kwd">else</span><span class="pln"> valueIfFalse
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> message
</span><span class="str">'Access denied'</span></pre>

<p>
	يُقيّم التعبير ذو الرقم 1 إلى القيمة الموافقة للوسيط <code>valueIfTrue</code> في حال كون متغير الشرط <code>condition</code> محققًا، أي مُقيّم على أنه <code>True</code>؛ أما في حال كونه غير محقق، أي أنه مُقيّم على أنه <code>False</code> فيُقيّم التعبير إلى القيمة الموافقة للوسيط <code>valueIfFalse</code>. وصف مبتكر لغة بايثون هذا التعبير مازحًا بأنه "قبيح عمدًا intentionally ugly"، إذ تضع معظم لغات البرمجة المُتضمنة العوامل الثلاثية الشرط بدايةً متبوعًا بالتعليمات المطلوبة في حال تحققه ثم تلك المطلوبة في حال عدم تحققه، ولكن يمكن -مع هذه الطريقة- استخدام تعبير شرطي في أي موضع نريد مكان أي قيمة أو تعبير، حتى مثل وسيط لإحدى الدوال كما هو الحال في السطر 2 من الشيفرة السابقة.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_28" style=""><span class="pln">condition </span><span class="kwd">and</span><span class="pln"> valueIfTrue </span><span class="kwd">or</span><span class="pln"> valueIfFalse</span></pre>

<p>
	إلى القيمة الموافقة للتعبير <code>valueIfTrue</code> في حال تحقق الشرط وإلى <code>valueIfFalse</code> في حال عدم تحققه (ماعدا حالة خاصة مهمة). لاحظ المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> valueIfTrue </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access granted'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> valueIfFalse </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Access denied'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> condition </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> condition </span><span class="kwd">and</span><span class="pln"> valueIfTrue </span><span class="kwd">or</span><span class="pln"> valueIfFalse
</span><span class="str">'Access granted'</span></pre>

<p>
	ينطوي العامل الثلاثي الزائف هذا على خطأ غامض خاص يحدث عند كون قيمة التعبير <code>valueIfTrue</code> من النمط الخاطئ (بمعنى أنها <code>0</code> أو <code>False</code> أو <code>None</code> أو سلسلة نصية فارغة)، فعندها سيُقيّم التعبير بصورة غير متوقعة إلى القيمة الموافقة للتعبير <code>valueIfFalse</code> عند تحقُق الشرط.
</p>

<p>
	استمر المبرمجون مع ذلك باستخدام هذا العامل الثلاثي الزائف، وأصبح السؤال "لماذا بايثون لا تتضمّن عاملًا ثلاثيًا؟" من الأسئلة الدائمة المطروحة على فريق مطوري بايثون الرئيسي. وكان من المتوقع أنه مع إنشاء التعابير الشرطية في بايثون سيتوقف المبرمجون عن طلب تضمين العامل الثلاثي وسيكفّون عن استخدام العامل الثلاثي الزائف المُتسبب بوقوع الخطأ. مع ذلك، تبقى <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D8%A8%D9%8A%D8%B1-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%D8%A5%D8%B2%D8%A7%D8%AD%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%AD%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D9%8A%D8%B6%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r285/" rel="">التعابير الشرطية</a> "قبيحة" بما يكفي لكي لا يتشجع المبرمجون على استخدامها، فرغم كون الجمال أفضل من القبح إلا أن العامل الثلاثي "القبيح" هو مثال على حكمة كون الواقع العملي غير مثالي.
</p>

<p>
	ليست التعابير الشرطية بايثونية تمامًا وليست غير بايثونية في الوقت نفسه، ففي حال استخدمتها، تجنب تداخلها:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> ageRange </span><span class="pun">=</span><span class="pln"> </span><span class="str">'child'</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">13</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="str">'teenager'</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> age </span><span class="pun">&gt;=</span><span class="pln"> </span><span class="lit">13</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> age </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">18</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="str">'adult'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> ageRange
</span><span class="str">'adult'</span></pre>

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

<h2>
	التعامل مع قيم المتغيرات
</h2>

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

<h3>
	الإسناد التسلسلي وعوامل المقارنة
</h3>

<p>
	في حال أردت التحقق من كون عدد ما ينتمي إلى مجال محدد، ستستخدم غالبًا العامل المنطقي <code>and</code> على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_34" style=""><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> spam </span><span class="kwd">and</span><span class="pln"> spam </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">99</span><span class="pun">:</span></pre>

<p>
	إلا أن بايثون تسمح بتسلسل عوامل المقارنة وبالتالي من الممكن الاستغناء عن العامل <code>and</code>. تكافئ الشيفرة التالية تلك المذكورة في المثال السابق:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_36" style=""><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> spam </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">99</span><span class="pun">:</span></pre>

<p>
	ينطبق الأمر ذاته على تسلسل عامل الإسناد <code>=</code>، إذ من الممكن تعيين عدد من المتغيرات إلى نفس القيمة ضمن سطر برمجي واحد، على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_38" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> bacon </span><span class="pun">=</span><span class="pln"> </span><span class="str">'string'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">,</span><span class="pln"> eggs</span><span class="pun">,</span><span class="pln"> bacon</span><span class="pun">)</span><span class="pln">
string string string</span></pre>

<p>
	يمكن استخدام العامل <code>and</code> للتحقق من كون المتغيرات الثلاث تخزّن فعلًا نفس القيمة، أو استخدام سلسلة من العامل <code>==</code> للتحقق من المساواة ببساطة أكبر.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> bacon </span><span class="pun">=</span><span class="pln"> </span><span class="str">'string'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> eggs </span><span class="pun">==</span><span class="pln"> bacon </span><span class="pun">==</span><span class="pln"> </span><span class="str">'string'</span><span class="pln">
</span><span class="kwd">True</span></pre>

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

<h3>
	التحقق من كون قيمة متغير تنتمي لمجموعة محددة من القيم
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_42" style=""><span class="pln">spam </span><span class="pun">==</span><span class="pln"> </span><span class="str">'cat'</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> </span><span class="str">'dog'</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> </span><span class="str">'moose` </span></pre>

<p>
	إلا أن الجزء المتكرر <code>==spam</code> يجعل من التعبير السابق غير عملي الاستخدام، ويمكن بدلًا من ذلك وضع القيم المحتملة ضمن بنية صف والتحقق من كون قيمة متغير ما موجودةً ضمن هذا الصف باستخدام العامل <code>in</code>، كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3883_44" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="str">'cat'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">(</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">True</span></pre>

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

<h2>
	الخلاصة
</h2>

<p>
	ما من <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغة برمجة</a> إلا ولديها الاصطلاحات والممارسات الأفضل الخاصة بها، وقد ركّز هذا المقال على الطرق العملية التي يستخدمها مبرمجو بايثون لكتابة شيفرات "بايثونية" للتعامل مع القواميس والمتغيرات وعامل بايثون الثلاثي.
</p>

<p>
	تمتلك القواميس التابعين <code>()get</code> و <code>()setdefault</code> بغية التعامل مع المفاتيح غير الموجودة، ولكن من الممكن استخدام قاموس من النوع <code>collections.defaultdict</code> لتخزين القيم الافتراضية للمفاتيح غير الموجودة.
</p>

<p>
	لا تتضمن لغة بايثون العبارة <code>switch</code>، لكن يمثّل استخدام القواميس طريقةً مختصرة لتطبيق ما يكافئ استخدام العبارة <code>switch</code> دون الحاجة إلى استخدام عدد كبير من عبارات <code>if-elif-else</code>، كما يمكن استخدام العوامل الثلاثية عند الحاجة إلى تقييم شرط ما إلى إحدى قيمتين.
</p>

<p>
	وتتحقق العوامل <code>==</code> من كون المتغيرات متساوية أم لا، في حين يتحقق العامل <code>in</code> من كون المتغير يمثل واحدة من مجموعة قيم ممكنة.
</p>

<p>
	ترجمة -وبتصرف- لجزء من الفصل السادس "كتابة شيفرات بايثون" من كتاب <a href="http://inventwithpython.com/beyond/chapter1.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%B5%D9%8A%D8%BA-%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%84%D9%89-%D9%86%D8%AD%D9%88-%D8%AE%D8%A7%D8%B7%D8%A6-r1971/" rel="">كتابة شيفرات بايثون: صيغ شائعة الاستخدام على نحو خاطئ</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%AA%D8%AE%D8%A7%D8%B0-%D8%A7%D9%84%D9%82%D8%B1%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%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%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1892/" rel="">اتخاذ القرار: العبارات الشرطية والحلقات التكرارية في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%81%D9%87%D9%85-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%86%D8%B7%D9%82%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r732/" rel="">فهم العمليات المنطقية في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1981</guid><pubDate>Sun, 14 May 2023 13:00:00 +0000</pubDate></item><item><title>&#x643;&#x62A;&#x627;&#x628;&#x629; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;: &#x635;&#x64A;&#x63A; &#x634;&#x627;&#x626;&#x639;&#x629; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x639;&#x644;&#x649; &#x646;&#x62D;&#x648; &#x62E;&#x627;&#x637;&#x626;</title><link>https://academy.hsoub.com/programming/python/%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%B5%D9%8A%D8%BA-%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B9%D9%84%D9%89-%D9%86%D8%AD%D9%88-%D8%AE%D8%A7%D8%B7%D8%A6-r1971/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_05/----------.png.6e59b49bc02b30d5d692c1894545f498.png" /></p>
<p>
	ما من لغة برمجة إلا وتصف نفسها بالقوة، الصفة عديمة المعنى في عالم لغات البرمجة، حتى أن كتيب بايثون التعليمي الرسمي يبدأ بالعبارة "بايثون هي لغة برمجة قوية سهلة التعلم". ولكن ما من خوارزمية تنفيذها حكر على لغة برمجة دون غيرها، وما من وحدة قياس لتحديد مدى "قوة" لغة برمجة ما (ولكن من الممكن بالطبع قياس الكم الذي يجادل به المبرمجون دفاعًا عن لغتهم المفضلة).
</p>

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

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

<h2>
	مبادئ بايثون التوجيهية العشرون
</h2>

<p>
	مبادئ بايثون التوجيهية العشرون أو ما يعرف باسم "زن بايثون The Zen of Python" الموضوعة من قبل تيم بيترز Tim Peters تختص بتصميم لغة بايثون وبرامجها. وليس من الضروري أن تتبع في برامجك كامل هذه التوجيهات، إلا أنه من المفيد تذكرها دومًا. كما أنها تمثل هديةً مخفية أو طرفة كامنة تظهر لدى تشغيل الأمر <code>import this</code> كما يلي:
</p>

<pre class="ipsCode">&gt;&gt;&gt; import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
--snip--
</pre>

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

<p>
	وبالنتيجة هذه المبادئ التوجيهية لا تتعدى كونها آراء يمكن للمبرمجين أن يؤيدوها أو يعارضوها. وكأي مجموعة من المبادئ الجيدة فإنها تناقض نفسها موفرةً أكبر قدر ممكن من المرونة. وفيما يلي تفسيري لهذه الحكم:
</p>

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

	<p data-gramm="false">
		الجمال أفضل من القبح
	</p>

	<p>
		Beautiful is better than ugly
	</p>
</blockquote>

<p>
	لعل الشيفرة الجميلة هي تلك التي تسهل قراءتها وفهمها. فغالبًا ما يكتب المبرمجون شيفراتهم بسرعة غير مكترثين بمدى قابليتها للقراءة، فالحاسوب سيشغلها على أية حال، إلا أن تصحيحها أو اكتشاف الأخطاء فيها سيكون أمرًا صعبًا بالنسبة للمبرمجين الآخرين. وجمال الشيفرة بالنتيجة هو أمر شخصي، إلا أن الشيفرة المكتوبة دون اكتراث لمدى قابليتها للفهم ستكون في نظر الآخرين قبيحة حتمًا. ولعل أهم سبب لشعبية بايثون هو كون شيفراتها لا تعمها الفوضى بعلامات ترقيم بلا جدوى كغيرها من <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> ما يسهل التعامل معها.
</p>

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

	<p data-gramm="false">
		التصريح أفضل من التضمين
	</p>

	<p>
		Explicit is better than implicit
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		البساطة أفضل من التعقيد، المعقد أفضل من المعقد المتشعب
	</p>

	<p>
		Simple is better than complex. Complex is better than complicated
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		السطحية أفضل من التداخل
	</p>

	<p>
		Flat is better than nested
	</p>
</blockquote>

<p>
	يميل المبرمجون لتنظيم شيفرتهم ضمن فئات، لاسيما تلك الفئات التي تتضمن فئات فرعية والتي تتضمن بدورها فئات فرعية أيضًا. ولا تضيف هذه البنى الهرمية عادةً إلى الشيفرة تنظيمًا بقدر ما تضيف له بيروقراطية. ولا بأس بأن تكتب شيفرتك ضمن إحدى الوحدات عالية المستوى أو ضمن بنية معطيات واحدة. ولكن إن بدت شيفرتك بالشكل <code>()spam.eggs.chicken.fish</code> أو <code>['spam['eggs']['chicken']['fish</code>، فاعلم أن شيفرتك شديدة التعقيد والتشعب.
</p>

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

	<p data-gramm="false">
		التباعد أفضل من التقارب
	</p>

	<p>
		Sparse is better than dense
	</p>
</blockquote>

<p>
	يميل المبرمجون عادةً إلى حشر أكبر كم ممكن من التعليمات ضمن أصغر جزء ممكن من الشيفرة، كما في السطر البرمجي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_12" style=""><span class="kwd">print</span><span class="pun">(</span><span class="str">'\n'</span><span class="pun">.</span><span class="pln">join</span><span class="pun">(</span><span class="str">"%i bytes = %i bits which has %i possiblevalues."</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">*</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">256</span><span class="pun">**</span><span class="pln">j</span><span class="pun">-</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> j </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </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">8</span><span class="pun">))))</span></pre>

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

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

	<p data-gramm="false">
		للمقروئية أهميتها
	</p>

	<p>
		Readability counts
	</p>
</blockquote>

<p>
	رغم كون <code>()strcmp</code> تشير وضوحًا إلى دالة مقارنة السلاسل المحرفية String Compare لشخص يعمل في ميدان البرمجة بلغة <a href="https://academy.hsoub.com/programming/c/" rel="">سي C</a> منذ السبعينيات، إلا أن الحواسيب في أيامنا تملك ما يكفي من الذاكرة لكتابة أسماء الدوال كاملةً. فلا تحذف أحرفًا من أسماء المعرفات ولا تبالغ في اختصار شيفرتك. خذ وقتك لاختيار أسماء المتغيرات والدوال لتكون وصفية ومحددة. كما أن تضمين سطر فارغ ما بين الأقسام المختلفة من شيفرتك أمر يماثل بأهميته فاصل الفقرات في الكتب المطبوعة، إذ يوضح للقارئ الأجزاء المتوجب قراءتها معًا ككتلة واحدة. هذه الحكمة تصب في نفس معنى تلك القائلة الجمال أفضل من القبح.
</p>

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

	<p data-gramm="false">
		الحالات الخاصة ليست خاصة لدرجة تسمح بكسر القواعد، رغم كون الواقع العملي غير مثالي
	</p>

	<p>
		Special cases aren’t special enough to break the rules. Although practicality beats purity
	</p>
</blockquote>

<p>
	تنطوي هاتان الحكمتان على شيء من التناقض. فمن ناحية عالم البرمجة مليء بما يسمى "أفضل الممارسات" best practices التي على المبرمجين الانصياع لها ما أمكن أثناء كتابة شيفراتهم، إلا أن الالتفاف على هذه الممارسات كالتفاف سريع قد يكون أمرًا مغريًا لكنه قد يسبب المزيد من الفوضى والتشابك لتكون الشيفرة بالنتيجة غير مُتسقة وذات مقروئية منخفضة. ومن ناحية أُخرى سيؤدي الالتزام المبالغ به بالقواعد بغض النظر عن خصوصية الواقع إلى شيفرة مجردة وبمقروئية منخفضة أيضًا. فعلى سبيل المثال، غالبًا ما يؤدي سعي <a href="https://academy.hsoub.com/programming/java/" rel="">لغة جافا</a> لموائمة كافة شيفراتها وفقًا لنموذجها <a href="https://academy.hsoub.com/programming/java/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-objects-%D9%88%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-oop-r966/" rel="">كائني التوجه</a> إلى شيفرات متداولة كثيرة حتى لأصغر البرامج. الحل إذًا بإمساك العصا من المنتصف ما بين الحكمتين، الأمر الذي سيغدو أسهل مع تراكم خبراتك، فمع الوقت لن تتعلم القواعد فحسب، بل ستتعلم متى يمكنك كسرها.
</p>

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

	<p data-gramm="false">
		الحل ليس بإسكات الأخطاء، ما لم تُسكّت عمدًا
	</p>

	<p>
		Errors should never pass silently. Unless explicitly silenced
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		احذر اغراءات التخمين في رحلة كشف الغموض
	</p>

	<p>
		In the face of ambiguity, refuse the temptation to guess
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		لابد من وجود طريقة واحدة واضحة لإنجاز الأمر، ومن المفضل وجود طريقة واحدة فقط
	</p>

	<p>
		There should be one—and preferably only one—obvious way to do it
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		قد لا تكون الأمور واضحة بدايةً مالم تكن هولنديًا
	</p>

	<p>
		Although that way may not be obvious at first unless you’re Dutch
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		أن تفعلها الآن أفضل من ألا تفعلها أبدًا، رغم كون عدم فعلها أبدًا أفضل من إلزامية فعلها في نفس اللحظة
	</p>

	<p>
		Now is better than never. Although never is often better than *right* now
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		تعد الفكرة سيئة في حال كون شرح كيفية تنفيذها أمر عسير، وقد تكون الفكرة جيدة في حال كون شرح كيفية تنفيذها أمرًا يسيرًا
	</p>

	<p>
		If the implementation is hard to explain, it’s a bad idea. If the implementation is easy to explain, it may be a good idea
	</p>
</blockquote>

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

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

	<p data-gramm="false">
		استخدام نطاقات الأسماء فكرة رائعة - لنستخدمها!
	</p>

	<p>
		Namespaces are one honking great idea—let’s do more of those
	</p>
</blockquote>

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

<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>
	لعل مبعث القلق الأكثر شيوعًا الذي نسمعه حول بايثون من المبرمجين المعتادين على استخدام لغات برمجة أخرى هو أن المسافات البادئة الإلزامية في بايثون (والتي تسمى خطأً المسافات الإلزامية) غريبة وغير مألوفة. إلا أن مقدار المسافة البادئة في بداية السطر البرمجي ذو معنى في بايثون، إذ يحدد السطور البرمجية المنتمية لكتلة واحدة من الشيفرة.
</p>

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

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9920_14" style=""><span class="com">// Java Example</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> main</span><span class="pun">(</span><span class="typ">String</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">
    </span><span class="typ">System</span><span class="pun">.</span><span class="pln">out</span><span class="pun">.</span><span class="pln">println</span><span class="pun">(</span><span class="str">"Hello, world!"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span></pre>

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

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

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

<pre class="ipsCode">&gt;&gt;&gt; from __future__ import braces
SyntaxError: not a chance
</pre>

<p>
	لن تضاف الأقواس إلى بايثون على المدى المنظور.
</p>

<h2>
	صيغ شائعة الاستخدام على نحو خاطئ
</h2>

<p>
	إذا لم تكن <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> هي أولى اللغات البرمجية التي تعلمتها، فبإمكانك كتابة شيفراتها وفق الاسترتيجيات التي اعتدت استخدامها مع لغات البرمجة الأخرى، أو لربما أنك قد تعلمت طرقًا غير معهودة لكتابة شيفرات بايثون نظرًا لعدم درايتك بوجود ممارساتٍ راسخة مُحبذة، ستعمل شيفرتك المكتوبة بالطرق غير المعهودة، ولكن من الممكن أن توفر بعضًا من الوقت والجهد بتعلمك للمزيد من المنهجيات المعيارية لكتابة شيفرات بايثونية. يشرح هذا القسم أخطاء المبرمجين الشائعة وكيفية كتابة الشيفرات متجنبًا الوقوع بها.
</p>

<h3>
	استخدم الدالة <code>()enumerate</code> بدلا من <code>()range</code>
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> animals </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</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="pln">len</span><span class="pun">(</span><span class="pln">animals</span><span class="pun">)):</span><span class="pln">
</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"> animals</span><span class="pun">[</span><span class="pln">i</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"> cat
</span><span class="lit">1</span><span class="pln"> dog
</span><span class="lit">2</span><span class="pln"> moose</span></pre>

<p>
	قد يكون الاصطلاح <code>(()range(len</code> واضح، لكنه لا يرقى لأن يعد مثاليًا نظرًا لصعوبة قراءته. فبدلًا من ذلك من الممكن تمرير القائمة أو السلسلة إلى دالة بايثون <code>()enumerate</code>، والتي ستعيد عددًا صحيحًا دالًا على رقم الفهرس مع قيمة العنصر الذي يشير إليه كل فهرس. فعلى سبيل المثال، من الممكن كتابة الشيفرة البايثونية التالية وصولًا إلى نفس النتيجة السابقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_18" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> animals </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> animal </span><span class="kwd">in</span><span class="pln"> enumerate</span><span class="pun">(</span><span class="pln">animals</span><span class="pun">):</span><span class="pln">
</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"> animal</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"> cat
</span><span class="lit">1</span><span class="pln"> dog
</span><span class="lit">2</span><span class="pln"> moose</span></pre>

<p>
	وبذلك ستكون شيفرتك أفضل مع استخدام الدالة <code>()enumerate</code> عوضًا عن التركيب <code>(()range(len</code>. وفي حال رغبتك بطباعة عناصر القائمة فقط دون رقم فهرس كل منها، فمن الممكن أيضًا المرور على عناصر القائمة بطريقة بايثونية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_20" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> animals </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> animal </span><span class="kwd">in</span><span class="pln"> animals</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">animal</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
cat
dog
moose</span></pre>

<p>
	فكل من استخدام الدالة <code>()enumerate</code> والمرور المباشر على عناصر السلسلة هي أمور مفضلة على استخدام التركيب التقليدي <code>(()range(len</code>.
</p>

<h3>
	استخدام التعليمة with بدلا من الدالتين<code>()open</code> و<code>()close</code>
</h3>

<p>
	تعيد الدالة <code>()open</code> كائن ملف يتضمّن التوابع اللازمة للقراءة من ملف أو الكتابة فيه، وعند انتهائك يعمل التابع <code>()close</code> الخاص بكائن الملف على إتاحة الملف للبرامج الأخرى لتقرأ منه أو تكتب فيه. كما من الممكن استخدام كل من هاتين الدالتين منفردة، إلا أن هذه الطريقة ليست بايثونية. فعلى سبيل المثال، لنُدخل الشيفرات التالية في الصدفة التفاعلية بغية كتابة العبارة النصية "!Hello, World" ضمن الملف المسمى spam.txt:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_22" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fileObj </span><span class="pun">=</span><span class="pln"> open</span><span class="pun">(</span><span class="str">'spam.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fileObj</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">13</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> fileObj</span><span class="pun">.</span><span class="pln">close</span><span class="pun">()</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_24" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     fileObj </span><span class="pun">=</span><span class="pln"> open</span><span class="pun">(</span><span class="str">'spam.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     eggs </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0</span><span class="pln">    </span><span class="com"># A zero divide error happens here.</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     fileObj</span><span class="pun">.</span><span class="pln">close</span><span class="pun">()</span><span class="pln">  </span><span class="com"># This line never runs.</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="kwd">except</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Some error occurred.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="typ">Some</span><span class="pln"> error occurred</span><span class="pun">.</span></pre>

<p>
	فبمجرد الوصول إلى خطأ القسمة على صفر سينتقل التنفيذ مباشرةً إلى الكتلة <code>except</code>، متجاوزًا استدعاء الدالة <code>()close</code> تاركًا بذلك الملف مفتوحًا، ما قد يؤدي بالنتيجة إلى أخطاء تلف الملفات file corruption لاحقًا، ومن الصعب تعقب الخطأ وتوقّع أن مصدره هو كتلة <code>try</code>.
</p>

<p>
	وبدلًا من الطريقة السابقة من الممكن استخدام التعليمة <code>with</code> والتي تستدعي الدالة <code>()close</code> تلقائيًا بمجرد انتهاء تنفيذ الكتلة <code>with</code>. وفيما يلي مثال مكتوب بطريقة بايثونية يؤدي نفس مهمة المثال الأول من هذه الفقرة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">with</span><span class="pln"> open</span><span class="pun">(</span><span class="str">'spam.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">as</span><span class="pln"> fileObj</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     fileObj</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	فرغم عدم استدعاء الدالة <code>()close</code> صراحةً، إلا أن التعليمة<code>with</code> ستستدعيها نلقائيًا بمجرد انتهاء تنفيذ الكتلة البرمجية هذه.
</p>

<h3>
	استخدم المعامل is بدلًا من == للمقارنة مع القيمة الخالية None
</h3>

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

<p>
	فقد يُقيّم التعبير <code>spam==None</code> على أنه صحيح True في بعض الحالات حتى في حال كون المتغير <code>spam</code> فارغًا بالمعنى المجرد، الأمر الناتج عن زيادة تحميل المعامل <code>==</code>. في حين أن التعبير <code>spam is None</code> سيتحقق من كون القيمة في المتغير <code>spam</code> هي حرفيًا <code>None</code>، إذ أنّ <code>None</code> هي القيمة الوحيدة ضمن نمط المعطيات الخالية None Type، فلا يوجد سوى كائن خالٍ None Object واحد في أي برنامج بايثون. فإن عُيّن أحد المتغيرات ليكون خاليًا None، فعندها سيُقيّم التعبير <code>is None</code> دومًا على أنه صحيح True، وفيما يلي مثال على حالة زيادة تحميل المعامل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_28" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">SomeClass</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">def</span><span class="pln"> __eq__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> other</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">if</span><span class="pln"> other </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">             </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">True</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="typ">SomeClass</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">==</span><span class="pln"> </span><span class="kwd">None</span><span class="pln">
</span><span class="kwd">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">None</span><span class="pln">
</span><span class="kwd">False</span></pre>

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

<p>
	ونهايةً، لا تستخدم المعامل <code>is</code> مع القيمتين <code>True</code> و<code>False</code> بل استخدم المعامل <code>==</code> لمقارنة هذه القيم، من قبيل <code>spam == True</code> أو <code>Spam == False</code>. والطريقة الأكثر شيوعًا في مثل هذه الحالات هي عدم استخدام المعامل والقيمة المنطقية بالمطلق، والاكتفاء بكتابة الشيفرة بالشكل <code>:if spam</code> أو <code>:if not spam</code> بدلًا من كتابة <code>:if spam == True</code> أو <code>:if spam == False</code>.
</p>

<h2>
	تنسيق السلاسل النصية
</h2>

<p>
	تظهر السلاسل النصية تقريبًا في كل برنامج بغض النظر عن لغة البرمجة المستخدمة، فهي من <a href="https://academy.hsoub.com/programming/general/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%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-r1726/" rel="">أنواع البيانات</a> الشائعة، فمن المتوقع وجود العديد من المنهجيات لمعالجة السلاسل النصية وتنسيقها. يسلط هذا القسم الضوء على اثنين من أفضل الممارسات بهذا الخصوص.
</p>

<h3>
	استخدم تنسيق السلاسل النصية الخام إذا تضمنت السلاسل عدة خطوط مائلة عكسية
</h3>

<p>
	تمكننا محارف الهروب escape characters من إدخال النصوص ضمن صياغة السلسلة النصية والتي يستحيل تضمينها فيها دون استخدامها. فعلى سبيل المثال لابد من استخدام محرف الهروب <code>\</code> في العبارة <code>Ahmad\'s chair</code> لتُفسر علامة الاقتباس الثانية على أنها جزء من السلسلة النصية وليست على أنها علامة انتهاء السلسلة. ولكن ماذا لو أردنا بالفعل تضمين الرمز <code>\</code> بحد ذاته ضمن السلسلة النصية؟ عندها يجب استخدامه بالشكل <code>\\</code>.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Unpythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'The file is in C:\\Users\\Al\\Desktop\\Info\\Archive\\Spam'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> file </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al\Desktop\Info\Archive\Spam</span></pre>

<p>
	أما باستخدام مفهوم السلاسل النصية الخام (لاحظ البادئة <code>r</code>) فسنحصل بالنتيجة على نفس السلسلة ولكن مع شيفرة ذات مقروئية أعلى:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">r</span><span class="str">'The file is in C:\Users\Al\Desktop\Info\Archive\Spam'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> file </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al\Desktop\Info\Archive\Spam</span></pre>

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

<h3>
	نسق السلاسل النصية باستخدام السلاسل النصية التنسيقية F-Strings
</h3>

<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> أو معالجتها بأنه عملية إنشاء سلاسل محرفية تتضمن سلاسل محرفية أخرى، الأمر الذي مر بالعديد من المراحل خلال تاريخ بايثون. فمن الممكن استخدام المعامل <code>+</code> لربط السلاسل المحرفية معًا، إلا أنها ستعطي بالنتيجة شيفرة مليئة بإشارات التنصيص وعلامات الزائد من قبيل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_34" style=""><span class="str">'Hello, '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> name </span><span class="pun">+</span><span class="pln"> </span><span class="str">'. Today is '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> day </span><span class="pun">+</span><span class="pln"> </span><span class="str">' and it is '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> weather </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span></pre>

<p>
	كما من الممكن استخدام مُحدّد التحويل <code>‎%s</code> الذي يجعل من الصياغة أسهل بعض الشيء بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_36" style=""><span class="str">'Hello, %s. Today is %s and it is %s.'</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">name</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> weather</span><span class="pun">)</span></pre>

<p>
	وبالنتيجة ستعمل كلا الطريقتين على إدخال السلاسل النصية الموافقة مكان كل من المتغيرات <code>name</code> و<code>day</code> و<code>weather</code> في السلسلة النصية المجردة وصولًا إلى سلسلة نصية جديدة مثل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_38" style=""><span class="str">'Hello, Al. Today is Sunday and it is sunny.'</span></pre>

<p>
	يعمل التابع <code>()format</code> الخاص بالسلاسل المحرفية على تمكين <a href="https://docs.python.org/3/library/string.html#formatspec" rel="external nofollow">لغة تخصيص التنسيق المصغرة</a> Format Specification Mini-Language والتي تتضمن استخدام أزواج الأقواس المعقوصة <code>{}</code> بطريقة مماثلة لفكرة استخدام مُحدّد التحويل <code>s%</code>، إلا أن هذه الطريقة تنطوي على شيء من التعقيد ما قد يُنتج شيفرة بمقروئية منخفضة، لذا لا أشجع استخدامها.
</p>

<p>
	إلى أن جاء الإصدار 3.6 من بايثون بميزة السلاسل النصية التنسيقية f-strings (اختصارًا لعبارة format strings) التي توفر طريقة أكثر ملائمة لإنشاء سلاسل نصية تتضمن سلاسل نصية أخرى. وكما هو الحال مع السلاسل النصية الخام والتي نستخدم لإنشائها البادئة <code>r</code> قبل علامة الاقتباس الاستهلالية، نستخدم هنا البادئة <code>f</code>، وفيها نُضمّن أسماء المتغيرات المطلوبة ضمن أقواس معقوصة لاستبدال كل منها لاحقًا بالسلاسل النصية المُخزنة فيها، على النحو:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> name</span><span class="pun">,</span><span class="pln"> day</span><span class="pun">,</span><span class="pln"> weather </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Al'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Sunday'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'sunny'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> f</span><span class="str">'Hello, {name}. Today is {day} and it is {weather}.'</span><span class="pln">
</span><span class="str">'Hello, Al. Today is Sunday and it is sunny.'</span></pre>

<p>
	كما من الممكن تضمين تعابير برمجية كاملة في الأقواس المعقوصة، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_44" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> width</span><span class="pun">,</span><span class="pln"> length </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">12</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> f</span><span class="str">'A {width} by {length} room has an area of {width * length}.'</span><span class="pln">
</span><span class="str">'A 10 by 12 room has an area of 120.'</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_42" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> f</span><span class="str">'This prints the value in spam: {spam}'</span><span class="pln">
</span><span class="str">'This prints the value in spam: 42'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> f</span><span class="str">'This prints literal curly braces: {{spam}}'</span><span class="pln">
</span><span class="str">'This prints literal curly braces: {spam}'</span></pre>

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

<p>
	وجود هذه الطرق المتعددة يخالف الحكمة القائلة "لابد من وجود طريقة واحدة واضحة لإنجاز الأمر، ومن المفضل وجود طريقة واحدة فقط" من مبادئ بايثون التوجيهية العشرون، إلا أن السلاسل النصية التنسيقية f-strings قد جاءت كتطوير للغة بايثون (من وجهة نظري)، وكما أن أحد المبادئ التوجيهية يشير إلى أن "الواقع العملي غير مثالي"، فإن كنت تستخدم الإصدار 3.6 من بايثون وما بعده فاستخدم دومًا السلاسل النصية التنسيقية. أما في حال استخدامك للإصدارات الأقدم، فأنصحك باستخدام التابع <code>()format</code> أو الاعتماد على محدد التحويل <code>s%</code>.
</p>

<h2>
	إنشاء نسخ ضحلة عن القوائم lists
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_46" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="str">'Hello, world!'</span><span class="pun">[</span><span class="lit">7</span><span class="pun">:</span><span class="lit">12</span><span class="pun">]</span><span class="pln"> </span><span class="com"># Create a string from a larger string.</span><span class="pln">
</span><span class="str">'world'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="str">'Hello, world!'</span><span class="pun">[:</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="com"># Create a string from a larger string.</span><span class="pln">
</span><span class="str">'Hello'</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eel'</span><span class="pun">][</span><span class="lit">2</span><span class="pun">:]</span><span class="pln"> </span><span class="com"># Create a list from a larger list.</span><span class="pln">
</span><span class="pun">[</span><span class="str">'rat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eel'</span><span class="pun">]</span></pre>

<p>
	نضع رمز النقطتين الرأسيتين <code>:</code> بين فهرسي عنصر البداية والنهاية للسلسلة الجديدة المراد إنشاؤها، ولدى إهمال وضع فهرس البداية قبل النقطتين الرأسيتين كما في المثال <code>'[Hello, world!'[:5</code>، فيُعيّن حينها افتراضيًا إلى القيمة <code>0</code>، أما إذا أهملنا فهرس النهاية بعد النقطتين الرأسيتين كما في المثال <code>[:cat', 'dog', 'rat', 'eel'][2']</code>، فيُعيّن افتراضيًا إلى فهرس العنصر الأخير من السلسلة الأم.
</p>

<p>
	أما إذا أهملت تعيين كلا الفهرسين، فسيتم تعيين فهرس البداية إلى <code>0</code> (أي بداية القائمة أو السلسلة) وفهرس النهاية إلى نهاية القائمة، الأمر الذي يمثل طريقة فعالة لإنشاء نسخة عن السلسلة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_48" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eel'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> spam</span><span class="pun">[:]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs
</span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eel'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">False</span></pre>

<p>
	ومن الجدير بالملاحظة في المثال السابق أن هويات القائمتين <code>spam</code> و<code>eggs</code> مختلفتين رغم تطابق قيمهما، إذ أن السطر البرمجي <code>[:]eggs = spam</code> ينشئ نسخة ضحلة عن القائمة <code>spam</code>، في حين أن التعليمة <code>eggs=spam</code> ستنسخ فعليًا مرجع القائمة <code>spam</code> وتسنده إلى القائمة <code>eggs</code>، إلا أن استخدام التعليمة <code>[:]</code> قد يبدو غريبًا بعض الشيء، واستخدام الدالة <code>()copy</code> من وحدة النسخ copy module لإنشاء نسخة ضحلة من القائمة تعد الطريقة الأعلى مقروئية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9920_50" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Pythonic Example</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> copy
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'rat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eel'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> eggs </span><span class="pun">=</span><span class="pln"> copy</span><span class="pun">.</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">spam</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> id</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">False</span></pre>

<p>
	فمن المفضل معرفتك لهذه الصياغة الغريبة لحالات مصادفتك لشيفرات بايثون قد استخدمتها، أما في شيفراتك الخاصة، فلا ننصحك باستخدامها. وتذكر أن كلًا من <code>[:]</code> و <code>()copy.copy</code> تُنشآن نسخًا ضحلة.
</p>

<h2>
	الخلاصة
</h2>

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

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

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

<p>
	ورغم كون العديد من مبرمجي بايثون يستخدمون التركيب <code>(()range(len</code> للحلقات التكرارية، إلا أن الدالة <code>()enumerate</code> توفّر منهجية أوضح للحصول على رقم الفهرس والقيمة الموافقة له لدى المرور على سلسلة ما. وكذلك الأمر بالنسبة للعبارة <code>with</code> الأوضح والأقل تسببًا بالأخطاء للتعامل مع الملفات مقارنةً باستدعاء التابعين <code>()open</code> و<code>()close</code> يدويًا، إذ تضمن العبارة <code>with</code> استدعاء التابع <code>()close</code> عند انتهاء التنفيذ وخروجه من الكتلة الخاصة بها.
</p>

<p>
	ولدى بايثون العديد من الطرق للتعامل مع السلاسل النصية ومعالجتها، ولعل الطريقة الأقدم هي استخدام محدد التحويل <code>s%</code> لتحديد المواضع المراد تضمينها ضمن السلسلة الرئيسية كجزء منها، أما الطريقة الأحدث والتي غدت موجودة اعتبارًا من الأصدار 3.6 فهي استخدام السلاسل النصية التنسيقية f-strings، وتُستخدم من خلال البادئة f قبل السلسلة النصية المراد صياغتها وبحصر الأجزاء المراد تضمينها في السلسلة ضمن أقواس معقوصة.
</p>

<p>
	أما الصيغة <code>[:]</code> المستخدمة لإنشاء نسخ ضحلة عن القوائم قد غدت قديمة نسبيَا وقد لا تعد طريقة بايثونية، إلا أنها قد غدت طريقة شائعة لإنشاء النسخ الضحلة بسرعة.
</p>

<p>
	ترجمة -وبتصرف- لجزء من الفصل السادس "كتابة شيفرات بايثون" من كتاب <a href="http://inventwithpython.com/beyond/chapter1.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AE%D8%B1%D8%A7%D9%81%D8%A7%D8%AA-%D8%AD%D9%88%D9%84-%D9%85%D9%85%D8%A7%D8%B1%D8%B3%D8%A7%D8%AA-%D8%AA%D8%AC%D9%86%D8%A8-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%85%D8%AD%D8%AA%D9%85%D9%84%D8%A9-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1945/" rel="">خرافات حول ممارسات تجنب أخطاء محتملة في شيفرات لغة بايثون</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%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D9%86%D8%B5%D9%88%D8%B5-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r409/" rel="">كيفية تنسيق النصوص في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1944/" rel="">اكتشاف دلالات الأخطاء في شيفرات لغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1971</guid><pubDate>Fri, 05 May 2023 13:00:00 +0000</pubDate></item><item><title>&#x623;&#x647;&#x645; 10 &#x645;&#x643;&#x62A;&#x628;&#x627;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x62A;&#x633;&#x62A;&#x62E;&#x62F;&#x645; &#x641;&#x64A; &#x627;&#x644;&#x645;&#x634;&#x627;&#x631;&#x64A;&#x639; &#x627;&#x644;&#x635;&#x63A;&#x64A;&#x631;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-10-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_05/502560097_.png.c64f901fd0a03d252b59bac587ab0979.png" /></p>
<p>
	تعد مكتبات بايثون إحدى أبرز نقاط قوة هذه اللغة، ومن أبرز المقولات الشهيرة التي تخص عالم برمجة البايثون هو أن المطورين والمبرمجين يدخلون عالم لغة بايثون من أجل تعلم هذه اللغة لسهولتها ولكنهم يبقون عالقين فيها بسبب مجتمع مطوريها الذي يوفر الكثير من المكتبات المفيدة والغنية بالمميزات.
</p>

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

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

<h2>
	ما معنى مكتبة بايثون؟
</h2>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="123665" href="https://academy.hsoub.com/uploads/monthly_2023_04/1073399473_.png.8f9e4dcfd36d64c07af5796fbda8de2a.png" rel=""><img alt="مكتبات بايثون" class="ipsImage ipsImage_thumbnailed" data-fileid="123665" data-ratio="62.67" data-unique="13a3n737m" style="width: 600px; height: auto;" width="900" src="https://academy.hsoub.com/uploads/monthly_2023_04/.thumb.png.2d4ad164610b6d3ac9bc00c0b3176b46.png"></a>
</p>

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

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5463_7" style=""><span class="pln">num </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">4</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">9</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">num</span><span class="pun">)</span><span class="pln">
get_sum </span><span class="pun">=</span><span class="pln"> sum</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
mean </span><span class="pun">=</span><span class="pln"> get_sum </span><span class="pun">/</span><span class="pln"> n
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Average = "</span><span class="pun">,</span><span class="pln">mean</span><span class="pun">)</span></pre>

<p>
	الآن لو أردنا لاستعانة بإحدى المكتبات التي توفر دالة جاهزة لحساب المتوسط سنجد العديد منها مثل مكتبة statistics و NumPy، على سبيل المثال سنستورد مكتبة NumPy في بداية الكود البرمجي كما يلي
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5463_11" style=""><span class="kwd">import</span><span class="pln"> numpy</span></pre>

<p>
	بعدها سنتمكن من كتابة الكود المكافئ للكود السابق لحساب المتوسط الحسابي بتعليمات أقل كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5463_9" style=""><span class="pln">num </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">4</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">9</span><span class="pun">]</span><span class="pln">
mean </span><span class="pun">=</span><span class="pln"> numpy</span><span class="pun">.</span><span class="pln">average</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Average = "</span><span class="pln"> </span><span class="pun">,</span><span class="pln">mean</span><span class="pun">)</span></pre>

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

<h2>
	أهم مكتبات بايثون للمشاريع الصغيرة
</h2>

<p>
	دعنا الآن نتعرف على أهم عشر مكتبات في لغة بايثون يمكنك استعمالها في المشاريع البرمجية المتنوعة:
</p>

<ul>
	<li>
		Dataset
	</li>
	<li>
		Beautiful Soup
	</li>
	<li>
		Requests
	</li>
	<li>
		Click
	</li>
	<li>
		Python Slugify
	</li>
	<li>
		Pluggy
	</li>
	<li>
		Datasette
	</li>
	<li>
		Envparse
	</li>
	<li>
		Pillow
	</li>
	<li>
		Tkinter
	</li>
</ul>

<p>
	لنتعرف على مزيد من التفاصيل حول كل مكتبة من هذه المكتبات ونتعرف على وظيفتها الأساسية.
</p>

<h2>
	Dataset: مكتبة بايثون لحفظ البيانات في قاعدة البيانات بشكل سريع
</h2>

<p>
	تُستخدم مكتبة <a href="https://dataset.readthedocs.io/en/latest/" rel="external nofollow">Dataset</a> ععندما نحتاج إلى جمع البيانات وحفظها في قاعدة البيانات قبل أن نكتشف ما هو الشكل النهائي لجداول قاعدة البيانات. حيث تُعتبر Dataset بسيطة ولكنها مع ذلك توفر <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> قوي يقدم طريقة سهلة لحفظ البيانات داخلها ثم تصنيفها لاحقًا.
</p>

<p>
	بنيت مكتبة Dataset فوق SQLAlchemy ويمكن استخدامها ضمن<a href="https://academy.hsoub.com/programming/python/django/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-django%C2%A0-r353/" rel=""> إطار عمل جانغو Django</a> من خلال تعليمات الإدارة <a href="https://docs.djangoproject.com/en/2.1/ref/django-admin/#django-admin-inspectdb" rel="external nofollow">inspectdb </a>المبنية داخل جانغو.
</p>

<h2>
	Beautiful Soup: مكتبة لاستخراج البيانات من صفحات الويب
</h2>

<p>
	تستخرج مكتبة <a href="https://www.crummy.com/software/BeautifulSoup" rel="external nofollow">Beautiful Soup</a> المعلومات من صفحات HTML كما أنها تستخدم في تحويل البيانات غير المنظمة أو غير المهيكلة unstructured data في HTML إلى بيانات مهيكلة structured data، كما أنها تعمل بشكل رائع مع بيانات XML صعبة القراءة.
</p>

<h2>
	Requests: مكتبة بايثون للعمل مع طلبات HTTP
</h2>

<p>
	يمكن القول أن مكتبة <a href="http://docs.python-requests.org/en/master" rel="external nofollow">Requests</a> هي من أفضل المكتبات المعيارية التي تعمل على محتوى بروتوكول HTTP وتجعل جعل طلبات HTTP أبسط، ففي أي وقت تحتاج لطلب صفحة HTML أو حتى واجهة برمجة تطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> في مشروعك ستقوم مكتبة Requests بتغليف هذا الطلب وتوثيقه بشكل جيد ومفهوم.
</p>

<h2>
	Click: مكتبة لكتابة الأوامر الخاصة بسطر الأوامر command-line
</h2>

<p>
	تعد مكتبة <a href="https://click.palletsprojects.com" rel="external nofollow">Click</a> من المكتبات المفضلة عندما تحتاج لكتابة نص برمجي بلغة بايثون ضمن سطر الأوامر command-line، حيث توفر هذه المكتبة واجهة برمجة تطبيقات <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> بسيطة ومدروسة جيدًا فهي لا تحتوي إلا القليل من النماذج التي نحتاج لتذكرها بالإضافة إلى أنها تمتلك مستندات توثق طريقة عملها بشكل جيد وهذا يسهل عليك عملية البحث عن الميزات المتقدمة ضمن المكتبة.
</p>

<h2>
	Python Slugify: مكتبة لتسمية الأشياء ضمن مشروع بايثون
</h2>

<p>
	تقدم مكتبة <a href="https://github.com/un33k/python-slugify" rel="external nofollow">Python Slugify</a> خدمة تسمية الأسماء وفلترتها وتمكنك من تحويل العناوين أو الأوصاف إلى مُعرِّفات مميزة. وهي ضرورية بشكل خاص لمطوري الويب ففي حال كنت تعمل على مشروع ويب يمكنك استخدامها لتحويل روابط URL لصفحات موقعك إلى روابط صديقة لمحركات البحث SEO فهي تجعل عملية التسمية أمرًا سهلًا ومباشرًا.
</p>

<h2>
	Pluggy: مكتبة بايثون للعمل مع الإضافات
</h2>

<p>
	تعد مكتبة <a href="https://pluggy.readthedocs.io/en/latest" rel="external nofollow">Pluggy</a> من مكتبات بايثون الحديثة نسبيًا ولكنها من أفضل وأسهل الطرق لإضافة الإضافات أو الملحقات plugins إلى تطبيقك الحالي من أجل تعديل جوانب معينة منه أو إضافة ميزات جديدة له، وفي حال تعاملت سابقًا مع إطار اختبار pytest في بايثون فإنك بالتأكيد استخدمت مكتبة Pluggy من دون أن تعرف.
</p>

<h2>
	Datasette: مكتبة بايثون لتحويل ملفات CSV إلى <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>
</h2>

<p>
	تعتبر مكتبة <a href="https://github.com/simonw/datasette" rel="external nofollow">Datasette</a> من مكتبات بايثون الرائعة وسهلة الاستخدام لتحويل ملفات CSV إلى تطبيقات REST JSON كاملة المميزات ولكنها تكون تطبيقات قراءة فقط وتمتلك هذه المكتبة الكثير من الميزات المهمة بما في ذلك المخططات والخرائط التفاعلية، وهي سهلة التطبيق ضمن البرامج باستخدام حاوية container أو مضيف ثالث في الويب.
</p>

<h2>
	Envparse: مكتبة للتعامل مع متغيرات البيئة في بايثون
</h2>

<p>
	في حال كنت تحتاج إلى تفسير متغيرات البيئة environment variables مباشرة لأنك لا تريد حفظ مفاتيح <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> أو أي معلومات أخرى هامة عن قاعدة البيانات ضمن الشيفرات البرمجية للتطبيق source code، عندها تحتاج إلى استخدام مكتبة <a href="https://github.com/rconradharris/envparse" rel="external nofollow">Envparse</a> التي تعد واحدة من أفضل مكتبات بايثون التي تعالج متغيرات البيئة وملفات ENV وأنماط المتغيرات، وتساعدك كذلك في إجراء المعالجات المسبقة Preprocessors واللاحقة Postprocessors لهذا المتغيرات عند الضرورة.
</p>

<h2>
	Pillow: مكتبة بايثون قوية لعرض ومعالجة الصور
</h2>

<p>
	توفر مكتبة <a href="https://github.com/python-pillow" rel="external nofollow">Pillow</a> ميزات رائعة للتعامل مع الصور في بايثون فإذا كنت تحتاج إلى معالجة وفتح وحفظ ملفات الصور في مشروعك أنصحك بتجربة هذه المكتبة التي تدعم تنسيقات مختلفة للصور كما تدعم الكثير من التعديلات والفلاتر على الصور مثل تغيير حجم الصورة وتدويرها وتعديل الألوان وتحسين تباينها.
</p>

<h2>
	Tkinter: مكتبة بايثون قياسية لبناء الواجهات الرسومية
</h2>

<p>
	تفيد مكتبة <a href="https://docs.python.org/3/library/tkinter.html" rel="external nofollow">Tkinter</a> القياسية أي مطور يحتاج لطريقة سهلة وسريعة لإنشاء <a href="https://academy.hsoub.com/programming/python/%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1501/" rel="">واجهة مستخدم رسومية GUI في بايثون </a>وتوفر العديد من عناصر الواجهة الرسومية الاحترافية كالأزرار ومربعات النصوص والقوائم ...إلخ وما يميزها عن غيرها من مكتبات الواجهة الرسومية هو أنها متوافقة مع أنظمة التشغيل الأساسية ويندوز ولينكس وماك أو إس، كما أناه تعرض عناصر الواجهة باستخدام عناصر نظام التشغيل الأساسي لذا ستبدو التطبيقات التي تم إنشاؤها باستخدامها وكأنها تنتمي إلى النظام الأساسي الذي يتم تشغيلها فيه دون الحاجة لأي تعديلات في الشيفرة لكل نظام على حدا.
</p>

<p>
	كانت هذه بعض من مكتبات بايثون وهناك بالطبع العديد من المكتبات الغنية بالميزات لكننا سنكتفي بهذه المكتبات العشر ونترك لك حرية اكتشاف العديد منها على متجر مكتبات بايثون الرسمي <a href="https://pypi.org/" rel="external nofollow">PyPI</a>.
</p>

<h2>
	نصائح لاختيار مكتبات بايثون الأنسب لمشروعك
</h2>

<p>
	كما ذكرنا سابقًا يمكن أن تجد العديد من المكتبات التي تخدم غرضك عندما تعمل على مشروع برمجي معين وتتساءل أي مكتبة علي أن اختار؟ إليك يلي بعض الأمور الهامة التي عليك مراعاتها عند اختيار مكتبة ما:
</p>

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

<h2>
	الخلاصة
</h2>

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

<p>
	هل تستخدم أيًا مكتبات بايثون التي استعرضناها في الأعلى أو غيرها؟ شاركنا باسم هذه المكتبة وعرفنا على أبرز الفوائد التي جنيتها من استخدامك لها في مشاريعك البرمجية؟
</p>

<p>
	ترجمة وبتصرّف للمقال <a href="https://opensource.com/article/18/9/python-libraries-side-projects" rel="external nofollow">8‎ great Python libraries for side projects‎‎‎</a> لصاحبيه Lacey Williams Henschel و Jeff Triplett.
</p>

<p>
	<span style="color:#999999;"><em>نشر المقال بتاريخ 06/01/2019 وجرى تحديثه.</em></span>
</p>
]]></description><guid isPermaLink="false">654</guid><pubDate>Mon, 17 Apr 2023 23:07:00 +0000</pubDate></item><item><title>&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_04/-----.png.739da9f420cd1c5d7c33c6db993fead4.png" /></p>
<p>
	سنتعرف في مقال اليوم على أهم تطبيقات لغة بايثون Python التي ابتكرها المبرمج الهولندي جيدو فان روسوم في أواخر 1989 وكان هدفه الأساسي من تطويرها هو تطوير لغة برمجة جديدة عامة الأغراض تجمع بين البساطة والقوة وتمكن المطور من تحقيق ما يريد بطريقة ممتعة وبأقل عدد من الشيفرات البرمجية وهو ما لم يكن متوفرًا في أي من لغات البرمجة المعروفة آنذاك!
</p>

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

<h2>
	ما هي لغة بايثون Python؟
</h2>

<p>
	لغة بايثون Python هي لغة برمجة متعددة الأغراض وسهلة التعلم تعتمد قواعد مرنة وصياغة بسيطة وتعليماتها البرمجية مشابهة للغة الإنجليزية بشكل كبير ما يجعلها واحدة من أسهل <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> للمبتدئين في التعلم، كما تتميز لغة بايثون بامتلاكها لمجتمع دعم كبير ومصادر تعلم هائلة وتوفيرها لمئات المكتبات وأطر العمل التي تقلل وقتك وجهدك في كتابة الكود كما تشمل بذلك مختلف مجالات البرمجة والتطوير.
</p>

<p>
	ورغم بساطة لغة بايثون إلا أنها في نفس الوقت لغة فعالة وموثوقة وعالية الأداء ويمكن تشغيلها على جميع <a href="https://academy.hsoub.com/apps/operating-systems/%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84/" rel="">أنظمة التشغيل</a> سواءً الحاسوب والجوال وحتى الحواسيب الصغيرة والأنظمة المدمجة وهي محبوبة بشدة بين أوساط المطورين.
</p>

<p>
	ومن أهم <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> هو أنها متعددة الأغراض والاستخدامات، فهي تستخدم اليوم على نطاق واسع لتنفيذ كافة أنواع التطبيقات في مختلف القطاعات، ونظرًا لتنوع تطبيقات لغة بايثون فهي مطلوبة بشدة في سوق العمل وتوفر الكثير من الخيارات والفرص الوظيفية ذات المردود المرتفع.
</p>

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

<p>
	ما يميز بايثون هو توفر الكثير من الموارد التعليمية المتاحة عبر الإنترنت والمتاحة لأي شخص يشق طريقه في <a href="https://academy.hsoub.com/learn-programming/" rel="">تعلم البرمجة</a>، فضلًا عن كونها لغة سهلة التعلم للمبتدئين وتركيب تعليماتها كما ذكرنا مشابه بشكل كبير للغة الإنجليزية المحكية وتمكن المبتدئ من تعلم <a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" 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>

<p>
	بناء على ذلك، تُعتمد في مجال التعليم في التخصصات التقنية أو حتى في مراحل دراسية مبكرة اعتمادًا كبيرًا وتُفضل على غيرها من اللغات، وعمومًا إذا كنت مهتمًا بالاطلاع على لغات برمجة أخرى تناسب المبرمجين المبتدئين أنصحك بقراءة مقال <a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D9%87%D9%84-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">أسهل لغات البرمجة</a> للمبتدئين.
</p>

<h2>
	أهم تطبيقات لغة بايثون
</h2>

<p>
	<img alt="تطبيقات لغة بايثون.png" class="ipsImage ipsImage_thumbnailed" data-fileid="142369" data-ratio="50.00" data-unique="o0njtk5fn" width="800" src="https://academy.hsoub.com/uploads/monthly_2024_01/280612481_.png.729904ab40ef05abc97cd79d9320f705.png">
</p>

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

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

<ol>
	<li>
		أتمتة المهام المتكررة
	</li>
	<li>
		الرياضيات والهندسة
	</li>
	<li>
		علم البيانات
	</li>
	<li>
		الذكاء الاصطناعي والتعلم الآلي
	</li>
	<li>
		تطوير مواقع الويب
	</li>
	<li>
		استخراج بيانات الويب
	</li>
	<li>
		برمجة العتاد وإنترنت الأشياء
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8/" rel="">تطوير تطبيقات سطح المكتب</a>
	</li>
	<li>
		تطوير الألعاب
	</li>
	<li>
		معالجة الصور والتصميم الرسومي
	</li>
</ol>

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

<h3>
	1. أتمتة المهام المتكررة في بايثون
</h3>

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

<p>
	لغة بايثون مثالية لأتمتة المهام بالمقارنة مع لغات برمجة أخرى مثل جافا أو C++‎ أو روبي حيث تتميز بايثون ببساطتها وسرعتها كما أنها توفر لك العديد من هياكل البيانات مثل <a href="https://wiki.hsoub.com/Python/list" rel="external" target="_blank">اللوائح Lists</a> و<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="">القواميس Dictionaries</a> و<a href="https://wiki.hsoub.com/Python/set" rel="external" target="_blank">المجموعات sets</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="">الصفوف tuples</a> …إلخ. وباختيارك لنمط البيانات المناسب، ستتمكن من تخزين البيانات بأفضل طريقة ومعالجتها بكفاءة وتحقيق أفضل أداء لتطبيقاتك وبرامجك الصغيرة التي تؤدي مهامًا بسيطة مؤتمتة.
</p>

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

<p>
	على سبيل المثال تتضمن بايثون مكتبة قياسية مدمجة بها هي smtplib والتي تساعدك بشكل رائع في أتمتة عملية إرسال رسائل البريد الإلكتروني عبر بروتوكول SMTP من داخل برامج وتطبيقات بايثون، ومكتبة Beautiful Soup التي تمكنك من سحب البيانات المخبأة في <a href="https://academy.hsoub.com/programming/html/%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-html-r1702/" rel="">ملفات HTML</a> أو غيرها من الأنواع واستخراجها بسهولة بالغة.
</p>

<h3>
	2. تطبيقات لغة بايثون في الرياضيات والهندسة
</h3>

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

<p>
	ومن أشهر مكتبات بايثون في هذا المجال مكتبة <a href="http://scipy.org/" rel="external nofollow" target="_blank">SciPy</a> الشهيرة والرهيبة وهي تجميعة من الحزم المخصصة للاستخدام في المجال العملي ومجال الرياضيات والهندسة حتى الحوسبة العلمية.
</p>

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

<h3>
	3. تطبيقات بايثون في علم البيانات
</h3>

<p>
	تستخدم لغة بايثون بشكل كبير في تطبيقات <a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA/" rel="">علم البيانات</a> وهو علم مهم يشهد انتشارًا واسعًا في الآونة الأخيرة ويهتم بكل أساسي بتحليل البيانات وتمثيلها رسوميًا واستنتاج المعرفة منها لمساعدة أصحاب الأعمال والمنظمات التي تجمع كل يوم كميات ضخمة من المعلومات المختلفة عن العملاء والمنتجات وعمليات البيع والشراء والمعاملات المالية …إلخ على الاستفادة من هذه المعلومات بأفضل صورة ممكنة.
</p>

<p>
	توفر لغة بايثون أفضل الطرق للتعامل مع البيانات المعقدة ومعالجتها وتحليلها من خلال مكتباتها العديدة التي تساعد علماء البيانات في تنفيذ مهامهم بسهولة مثل مكتبة <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/" rel="">NumPy</a> و Pandas التي توفر أدوات حسابية ورياضية تساعد في معالجة وتحليل البيانات، ومكتبة Seaborn و Matplotlib التي توفر وظائف لتمثيل البيانات بشكل بياني وتسهل فهمها واستخلاص النتائج منها واتخاذ القرارات بناءً عليها، إضافة لتوفيرها لمكتبات قوية في مجال التعلم الآلي مثل Theano و TensorFlow التي تساعد على تنفيذ مهام تنظيف ونمذجة البيانات وتمثيلها وعرضها.
</p>

<h3>
	4. الذكاء الاصطناعي والتعلم الآلي
</h3>

<p>
	تلعب لغة بايثون دورًا حيويًا في <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%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/" rel="">تطبيقات الذكاء الاصطناعي</a> والتعلم الآلي وتطبيقات لغة بايثون كثيرة في هذا المجال لكونها لغة مستقرة وآمنة وتوفر مكتبات احترافية تتضمن أهم <a href="https://academy.hsoub.com/programming/advanced/%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D8%A7%D8%AA/" rel="">خوارزميات </a>التعلم الآلي وتسهل التعامل مع العمليات الحسابية اللازمة لبناء نماذج التعلم الآلي ومن أهم هذه المكتبات نذكر <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D8%A7%D9%87%D9%8A%D9%85-%D9%85%D8%AA%D9%82%D8%AF%D9%85%D8%A9-%D8%AD%D9%88%D9%84-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-numpy-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1809/" rel="">NumPy</a> و Keras و SciPy و pandas …إلخ.
</p>

<p>
	من خلال هذه المكتبات ستتمكن من إنشاء تطبيقات رائعة في <a href="https://academy.hsoub.com/programming/artificial-intelligence/%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/" rel="">مجال الذكاء الاصطناعي</a> وتنجز الكثير من مهام تحليل وهندسة البيانات وتطبيقات التعرف على الصور والعديد من التطبيقات الأخرى بمنتهى السهولة.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة الذكاء الاصطناعي
		</p>

		<p class="banner-subtitle">
			احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة.
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/artificial-intelligence" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<a href="https://academy.hsoub.com/learn/artificial-intelligence" rel=""><img alt="دورة الذكاء الاصطناعي AI" src="https://academy.hsoub.com/learn/assets/images/courses/artificial-intelligence.png"></a>
	</div>
</div>

<h3>
	5. تطوير مواقع الويب من أهم تطبيقات لغة بايثون
</h3>

<p>
	يعد <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8/" rel="">تطوير مواقع الويب</a> من أهم تطبيقات لغة بايثون وهي لغة برمجة أساسية تستخدم في برمجة الواجهة الخلفية لأكبر مواقع الويب والتطبيقات في العالم مثل انستغرام وفيسبوك وكورا و Dropbox و Reddit و Netflex …إلخ.
</p>

<p>
	كما توفر بايثون أطر عمل مميزة تسهل عمل مطوري الويب أبرزها فلاسك Flask وجانغو Django وإطار العمل هو ببساطة مجموعة من الأكواد والوحدات والمكتبات البرمجية المجمعة مع بعضها البعض والتي تجعل عملية <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8/" rel="">تطوير الويب</a> آمنة وموثوقة وتبسط عمليات التفاعل مع قاعدة البيانات وإدارة المحتوى وتقلل من وقت تطوير مواقع الويب بشكل كبير.
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-controller="core.front.core.autosizeiframe" data-embedauthorid="3889" data-embedcontent="" data-embedid="embed5280337771" src="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/?do=embed" style="overflow: hidden; height: 473px; max-width: 502px; margin: auto;"></iframe>






<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			احصل على موقع إلكتروني مخصص لأعمالك
		</p>

		<p class="banner-subtitle">
			أبهر زوارك بموقع احترافي ومميز بالاستعانة بأفضل خدمات تطوير وتحسين المواقع على خمسات
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://khamsat.com/create-website" rel="external">أنشئ موقعك الآن</a>
		</div>
	</div>
</div>





<h3>
	6. استخراج بيانات الويب
</h3>

<p>
	تتميز بايثون بكونها لغة شائعة الاستخدام في مجال استخراج البيانات من مواقع الويب وصفحات الويب Web scraping بسهولة وسرعة وتتيح الاستفادة منها في عدة استخدامات مثل البحث عن قوائم الوظائف ومقارنة الأسعار وغيرها الكثير من المجالات.
</p>

<p>
	فبدلًا من نسخ هذه البيانات ولصقها يدويًا في مستندات جديدة يمكن بسهولة استخدام أدوات مؤتمتة تقوم بنسخ البيانات ولصقها في البيانات جداول بتنسيق CSV أو JSON. ومن أهم مكتبات بايثون التي تساعدك في استخراج بيانات الويب نذكر BeautifulSoup و MechanicalSoup و Scrapy وغيرها.
</p>

<h3>
	7. برمجة العتاد وإنترنت الأشياء
</h3>

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

<p>
	فإذا كنت مهتمًا ببرمجة العتاد وتطبيقات <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-%D8%A7%D9%84%D8%A3%D8%B4%D9%8A%D8%A7%D8%A1-iot-r1514/" rel="">إنترنت الأشياء IoT</a> يمكنك التفكير في استخدام لغة بايثون كلغة لتطوير البرامج المضمنة في هذه الأجهزة فهي توفر لك سرعة في كتابة التعليمات البرمجية كما توفر عددًا كبير من المكتبات المتوافقة مع كافة الأنظمة.
</p>

<p>
	ولعل أبرز تطبيقات بايثون في مجال إنترنت الأشياء والأنظمة المدمجة شريحة <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-raspberry-pi-%D9%84%D9%84%D8%B9%D9%85%D9%84-r1417/" rel="">Raspberry Pi </a> التي تثبت بايثون بشكل مدمج وافتراضي فيها وكل ما عليك هو البدء بكتابة أكواد بايثون الخاصة بك لتعمل مباشرة.
</p>

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

<h3>
	8. تطوير تطبيقات سطح المكتب
</h3>

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

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

<p>
	وإن أردت تعلم المزيد حول بناء واجهات المستخدم الرسومية في بايثون، فارجع إلى السلسلة التالية <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-tkinter-r1378/" rel="">برمجة الواجهات الرسومية باستخدام Tkinter</a>.
</p>

<h3>
	9. تطبيقات لغة بايثون في تطوير الألعاب
</h3>

<p>
	توفر لغة بايثون العديد من المكتبات المفيدة في مجال تطوير الألعاب التفاعلية مثل PySoy وهو <a href="https://academy.hsoub.com/programming/game-development/%D9%85%D8%AD%D8%B1%D9%83%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D9%84%D8%B9%D8%A7%D8%A8-game-engines/" rel="">محرك ألعاب</a> ثلاثي الأبعاد يدعم بايثون، و PyGame وهي مكتبة مفتوحة المصدر تستخدم على نطاق واسع لتطوير الألعاب وتطوير المشاريع التجارية وتتميز بكونها قابلة للاستخدام على شرائح Raspberry Pi.
</p>

<p>
	وقد استخدمت لغة بايثون في تطوير العديد من الألعاب الشهيرة الاحترافية مثل Battlefield 2 و Vega Strike و World of Tanks فإذا كنت تفكر في احتراف تطوير ألعاب الفيديو ففكر في لغة بايثون بدلًا من استخدام C++‎ أو C#‎ أو جافا سكربت أو جافا لأنها ستسهل عليك مهمتك وتوفر عليك الكثير من الوقت.
</p>

<p>
	يمكنك الرجوع إلى سلسلة <a href="https://academy.hsoub.com/programming/python/%D8%A8%D9%86%D8%A7%D8%A1-%D9%84%D8%B9%D8%A8%D8%A9-%D9%86%D8%B1%D8%AF-%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1703/" rel="">بناء لعبة نرد بسيطة بلغة بايثون</a> لبدء تعلم استخدام لغة بايثون في مجال برمجة الألعاب.
</p>

<h3>
	10. بايثون ومعالجة الصور والتصميم الرسومي
</h3>

<p>
	من تطبيقات لغة بايثون الناجحة إضافة لكل ما سبق، مجال معالجة الصور والتصميم الرسومي فهي تستخدم في تطوير مجموعة من البرامج الرائدة في مجال الرسم ثنائي الأبعاد مثل <a href="https://academy.hsoub.com/design/illustration/inkscape/" rel="">Inkscape</a> و <a href="https://academy.hsoub.com/design/graphic/gimp/" rel="">GIMP</a> و <a href="https://academy.hsoub.com/design/graphic/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A8%D8%AF%D8%A1-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D8%AC-%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D9%88%D8%B3-scribus-r582/" rel="">Scribus</a>. كما تستخدم لغة بايثون في العديد من تطبيقات الرسم والنمذجة ثلاثية الأبعاد وأبرزها Autodesk 3ds Max و Blender ومايا Maya و Cinema 4D و Panda3D.
</p>

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

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

<p>
	ولعلك لاحظت أن تعدد تطبيقات لغة بايثون هو من أبرز نقاط قوة هذه اللغة إلى جانب سهولتها ومرونتها وهو ما يجعل شعبيتها وجاذبيتها تزداد باضطراد في أوساط الطلاب والمبرمجين والمطورين المبتدئين والمحترفين على حد سواء لاختيار تعلم لغة بايثون كوجهة للتخصص في <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>.
</p>

<p>
	وإذا كنت مهتمًا بمعرفة المزيد من المعلومات حول لغة بايثون والتعرف على تطبيقات لغة بايثون وأهم مميزاتها وكيفية تثبيتها على جهازك وكتابة برنامجك الأول في بايثون أنصحك بمشاهدة هذا الفيديو:<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="350" id="ips_uid_5920_6" src="https://academy.hsoub.com/applications/core/interface/index.html" title="YouTube video player" width="800" data-embed-src="https://www.youtube.com/embed/y4v8qtXVKUU"></iframe>
</p>

<h2>
	الخلاصة
</h2>

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

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

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

<ul>
	<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/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">أساسيات البرمجة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/%D8%A8%D9%8A%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-ide-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1772/" rel="">بيئات التطوير IDE المستخدمة في تطوير تطبيقات بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1957</guid><pubDate>Mon, 17 Apr 2023 15:04:00 +0000</pubDate></item><item><title>&#x62E;&#x631;&#x627;&#x641;&#x627;&#x62A; &#x62D;&#x648;&#x644; &#x645;&#x645;&#x627;&#x631;&#x633;&#x627;&#x62A; &#x62A;&#x62C;&#x646;&#x628; &#x623;&#x62E;&#x637;&#x627;&#x621; &#x645;&#x62D;&#x62A;&#x645;&#x644;&#x629; &#x641;&#x64A; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%AE%D8%B1%D8%A7%D9%81%D8%A7%D8%AA-%D8%AD%D9%88%D9%84-%D9%85%D9%85%D8%A7%D8%B1%D8%B3%D8%A7%D8%AA-%D8%AA%D8%AC%D9%86%D8%A8-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%85%D8%AD%D8%AA%D9%85%D9%84%D8%A9-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1945/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_04/--.png.83d47a351610e09401da5bc4a3810c8b.png" /></p>
<p>
	تعرفنا في <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1944/" rel="">المقال السابق</a> على مفهوم روائح الشيفرات Code Smells في <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>، والتي تعني دلالات وقوع الأخطاء، فبعض الإشارات قد تدل على وجود أخطاء خفية أو محتملة أو على كون مقروئية الشيفرة ضعيفة.
</p>

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

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

<h2>
	خرافة أن الدالة يجب أن تتضمن تعليمة قيمة معادة return وحيدة وفي نهايتها
</h2>

<p>
	أتت فكرة "مُدخل وحيد – مُخرج وحيد" من نصيحة مُساءة الفهم من أيام <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة assembly و FORTRAN</a>، إذ كانت هذه اللغات تسمح بإدخال إجراء فرعي (وهي بنية شبيهة بالدالة) عند أي نقطة من الشيفرة، حتى في وسطها، ما يجعل من الصعب تنقيح الأجزاء التي تم تنفيذها من هذا الإجراء الفرعي، إلا أن الدوال الحالية لا تعاني من هذه المشكلة، إذ يبدأ تنفيذ الدالة من بدايتها دومًا، ومع ذلك بقيت النصيحة قائمة ليكون مفادها "يجب أن تتضمن <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r292/" rel="">الدوال</a> والتوابع تعليمة <code>return</code> واحدة والتي يجب أن تكون تحديدًا في نهاية الدالة أو التابع".
</p>

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

<h2>
	خرافة أن الدالة يجب أن تتضمن تعليمة try واحدة على الأكثر
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6670_8" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> os
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> deleteWithConfirmation</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'Delete '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> filename </span><span class="pun">+</span><span class="pln"> </span><span class="str">', are you sure? Y/N'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Y'</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">             os</span><span class="pun">.</span><span class="pln">unlink</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">except</span><span class="pln"> </span><span class="typ">FileNotFoundError</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'That file already did not exist.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	إذ يجادل مؤيدو خرافة دلالة الخطأ آنفة الذكر بأنه طالما أن الدالة معنية بتأدية مهمة واحدة، وطالما أن التعامل مع الأخطاء هو مهمة واحدة، لذا يجب تقسيم الدالة السابقة إلى دالتين. كما يجادلون بأنه عند استخدام التعليمة <code>try-except</code> ضمن الدالة، فيجب أن تكون هي التعليمة الأولى ضمنها، حاصرةً كامل شيفرة الدالة لتبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6670_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> os
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> handleErrorForDeleteWithConfirmation</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         _deleteWithConfirmation</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">except</span><span class="pln"> </span><span class="typ">FileNotFoundError</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'That file already did not exist.'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> _deleteWithConfirmation</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">input</span><span class="pun">(</span><span class="str">'Delete '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> filename </span><span class="pun">+</span><span class="pln"> </span><span class="str">', are you sure? Y/N'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Y'</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         os</span><span class="pun">.</span><span class="pln">unlink</span><span class="pun">(</span><span class="pln">filename</span><span class="pun">)</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	وهي شيفرة معقدة بلا ضرورة، إذ تم تعيين الدالة <code>()_deleteWithConfirmation</code> لتكون خاصة باستخدام البادئة <code>_</code> للدلالة على عدم إمكانية استدعائها مباشرةً، وإنما بشكل غير مباشر من خلال استدعاء الدالة <code>()handleErrorForDeleteWithConfirmation</code>، إذ أن اسم هذه الدالة الجديدة غير ملائم، فنحن نستدعيها بنية حذف ملف، لا بنية <a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r1342/" rel="">التعامل مع الأخطاء</a> الناتجة أثناء حذف ملف.
</p>

<p>
	إذًا يجب أن تكون الدوال صغيرة وبسيطة، ولكن هذا لا يعني أنها يجب أن تكون محدودة لأداء "أمر واحد" (بالمعنى الذي تفهمه)، فمن الجيد أن تتضمن الدوال عدة تعليمات <code>try-except</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>
	خرافة أن الوسيط المنطقي خيار سيئ
</h2>

<p>
	يطلق على الوسطاء من النوع <a href="https://wiki.hsoub.com/Python/boolean" rel="external">قيم منطقية Boolean</a> الممررة لدى استدعاء الدوال أو التوابع اسم وسطاء الأعلام أو الرايات flag arguments، والراية في البرمجة هي قيمة تشير إلى عملية إعداد أو ضبط وفق النظام الثنائي، كما في السمتين <code>enabled</code> الدالة على التمكين و<code>disabled</code> الدالة على إلغاء التمكين، إذ غالبًا ما يعبّر عن الراية بقيمة منطقية، وبذلك يمكننا التعبير عن هذه الإعدادات بأنها إما معيّنة True أو ملغاة False.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6670_12" style=""><span class="kwd">def</span><span class="pln"> someFunction</span><span class="pun">(</span><span class="pln">flagArgument</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> flagArgument</span><span class="pun">:</span><span class="pln">
        </span><span class="com"># Run some code...</span><span class="pln">
    </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
        </span><span class="com"># Run some completely different code…</span></pre>

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

<h2>
	خرافة أن المتغيرات العامة خيار سيئ
</h2>

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

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

<p>
	فعلى سبيل المثال، لنتمعن في الدالة <code>()calculateSlicesPerGuest</code> (التي تعني حساب عدد قطع الحلوى لكل ضيف) من البرنامج <code>partyPlanner.py</code> (منسق الحفلة) المُفترض، إذ ضمّنا فيه أرقام الأسطر لتقديم فكرة عن حجم البرنامج الكبير:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6670_14" style=""><span class="lit">1504.</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> calculateSlicesPerGuest</span><span class="pun">(</span><span class="pln">numberOfCakeSlices</span><span class="pun">):</span><span class="pln">
</span><span class="lit">1505.</span><span class="pln">     </span><span class="kwd">global</span><span class="pln"> numberOfPartyGuests
</span><span class="lit">1506.</span><span class="pln">     </span><span class="kwd">return</span><span class="pln"> numberOfCakeSlices </span><span class="pun">/</span><span class="pln"> numberOfPartyGuests</span></pre>

<p>
	وبفرض أننا واجهنا لدى تشغيل البرنامج الاستثناء التالي:
</p>

<pre class="ipsCode">Traceback (most recent call last):
  File "partyPlanner.py", line 1898, in &lt;module&gt;
    print(calculateSlicesPerGuest(42))
  File "partyPlanner.py", line 1506, in calculateSlicesPerGuest
    return numberOfCakeSlices / numberOfPartyGuests
ZeroDivisionError: division by zero
</pre>

<p>
	يعرض البرنامج خطأ القسمة على صفر، وهو ناتج عن سطر القيمة المعادة <code>return numberOfCakeSlices / numberOfPartyGuests</code>، وبالتالي لا بد من ان قيمة المتغير <code>numberOfPartyGuests</code> تساوي الصفر ما سبب ظهور هذا الخطأ، والسؤال: أين تم إسناد قيمة الصفر لهذا المتغير؟ فهو متغير عام، وبالتالي من الوارد أن يتم هذا الأمر في أي مكان ضمن آلاف الأسطر التي يتكون منها هذا البرنامج، لكننا نعلم من معلومات متتبع الأخطاء أن استدعاء الدالة <code>()calculateSlicesPerGuest</code> قد تم في السطر رقم 1898 من البرنامج.
</p>

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

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

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

<h2>
	خرافة أن التعليقات غير ضرورية
</h2>

<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%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> سيئة هو أمرٌ أسوأ من حالة عدم وجود تعليقات بالمطلق، فالتعليق المُتضمن لمعلومات قديمة أو مشوشة سيزيد من عبء العمل على المبرمج بدلًا من مساعدته في تحقيق فهم أفضل، إلا أنّ هذه المشكلة المحتملة في التعليقات قد اتُخذت ذريعةً للتعميم بأن التعليقات ككل سيئة، ويجادل أصحاب هذا الرأي بأنه بدلًا من إضاعة الوقت بالتعليقات، يجب استبدالها بشيفرات عالية المقروئية (لا تحتاج لتعليقات أصلًا) لدرجة أنهم يرون بأن البرامج يجب ألا تحتوي على تعليقاتٍ بالمطلق.
</p>

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

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

<h1>
	الخاتمة
</h1>

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

<p>
	ولكن ليست كل دلالات الأخطاء فعلية، فبعضها لا يتعدى كونه خرافات، كالنصائح البرمجية التي لم تعد صالحة أو تلك التي أثبتت أنها تعود على المبرمج بنتائج عكسية، كخرافة وجوب استخدام تعليمة <code>return</code> أو كتلة <code>try-except</code> واحدة ضمن بناء الدالة، مع عدم استخدام وسطاء الأعلام أو المتغيرات العامة بالمطلق، ناهيك عن الاعتقاد القائل بأن التعليقات غير ضرورية.
</p>

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

<p>
	ترجمة -وبتصرف- للجزء الثاني من الفصل الخامس Finding Code Smells من كتاب <a href="https://inventwithpython.com/beyond/chapter5.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigarti.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1944/" rel="">اكتشاف دلالات الأخطاء في شيفرات لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%AB%D9%84%D8%A7%D8%AB%D8%A9-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B9%D9%84%D9%8A%D9%83-%D8%AA%D9%81%D8%A7%D8%AF%D9%8A%D9%87%D8%A7-%D8%B9%D9%86%D8%AF-%D8%AA%D8%B9%D9%84%D9%85-%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-r543/" rel="">ثلاثة أخطاء عليك تفاديها عند تعلم البرمجة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%B1%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1856/" rel="">التعامل مع رسائل الأخطاء في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1945</guid><pubDate>Sun, 09 Apr 2023 15:00:00 +0000</pubDate></item><item><title>&#x627;&#x643;&#x62A;&#x634;&#x627;&#x641; &#x62F;&#x644;&#x627;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x641;&#x64A; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1944/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_04/-----CODE-SMELLS.png.87e9e22ca78bce419fbaf7ed915fce57.png" /></p>
<p>
	مما لا شك فيه أن الشيفرة التي تسبب توقف عمل البرنامج هي خاطئة حُكمًا، والسؤال: هل هذا النوع من الأعطال هو الدليل الوحيد على وجود مشاكل في البرنامج؟ بالطبع لا، فبعض الإشارات قد تدل على وجود أخطاء خفية أو على كون مقروئية الشيفرة ضعيفة. وكما هو الحال مع رائحة الغاز التي قد تشير إلى وجود تسرّب في الغاز أو رائحة الدخان التي قد تشير لنشوب حريق، "فرائحة" الشيفرة Code Smells هي نمط للشيفرة المصدرية يشير لوجود أخطاء محتملة، ولا يعني بالضرورة وجود مشكلة، إلا أنه يدل على ضرورة التحقق من الشيفرة.
</p>

<p>
	سنقدم في هذا المقال عددًا من "روائح" الشيفرات الأكثر شيوعًا التي يحتمل أن تحمل أخطاءً، وانطلاقًا من مبدأ درهم وقاية خير من قنطار علاج، سيستغرق <a href="https://academy.hsoub.com/programming/python/%D8%AB%D9%84%D8%A7%D8%AB%D8%A9-%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%B9%D9%84%D9%8A%D9%83-%D8%AA%D9%81%D8%A7%D8%AF%D9%8A%D9%87%D8%A7-%D8%B9%D9%86%D8%AF-%D8%AA%D8%B9%D9%84%D9%85-%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-r543/" rel="">تجنب وقوع الأخطاء</a> وقتًا وجهدًا أقل من مواجهتها وفهمها وإصلاحها لاحقًا، فلكل مبرمج مغامراته في قضاء ساعات بالتنقيح ليكتشف لاحقًا أن إصلاح الخطأ يشمل سطر برمجي واحد من الشيفرة، ولهذا السبب حتى أبسط دلالة على خطأ محتمل يجب أن تستوقفك، موجهةً إياك لإجراء المزيد من التحقق والتأكد من كونك لا تتسبب بحدوث مشاكل مستقبلية.
</p>

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

<p>
	قبل التعرف على كيفية اكتشاف أخطاء الشيفرات في لغة بايثون، ندعوك للتعرف على الأخطاء البرمجية عامةً أولًا والتعرف على كيفية التعامل معها:
</p>

<p>
	<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="603" src="https://academy.hsoub.com/applications/core/interface/index.html" title="كيفية التعامل مع الأخطاء البرمجية" width="1072" data-embed-src="https://www.youtube.com/embed/Pgje6nWuDkg"></iframe>
</p>

<p>
	والآن دعونا نتحدث عن دلالات وجود الأخطاء في شيفرات لغة بايثون.
</p>

<h2>
	تكرار الشيفرات
</h2>

<p>
	إحدى أكثر دلالات الأخطاء (روائح الشيفرات) شيوعًا هي الشيفرات المكررة، وهي بالتعريف أي شيفرة مصدرية مُنشأة باستخدام نسخ ولصق أجزاءً من شيفرة أُخرى ضمن شيفرتك الحالية عدة مرات، فمثلًا يتضمن البرنامج التالي شيفراتٍ مكررة، إذ نلاحظ أنها تسأل المستخدم عن حاله (?How are you feeling) ثلاث مرات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_6" style=""><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good morning!'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good afternoon!'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good evening!'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span></pre>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_8" style=""><span class="kwd">def</span><span class="pln"> askFeeling</span><span class="pun">():</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
    feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good morning!'</span><span class="pun">)</span><span class="pln">
askFeeling</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good afternoon!'</span><span class="pun">)</span><span class="pln">
askFeeling</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good evening!'</span><span class="pun">)</span><span class="pln">
askFeeling</span><span class="pun">()</span></pre>

<p>
	أما في المثال التالي، فتخلصنا من <a href="https://academy.hsoub.com/programming/python/%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1-loops-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r291/" rel="">التكرار</a> عبر حصر الجزء المكرر ضمن حلقة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_10" style=""><span class="kwd">for</span><span class="pln"> timeOfDay </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">[</span><span class="str">'morning'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'afternoon'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'evening'</span><span class="pun">]:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> timeOfDay </span><span class="pun">+</span><span class="pln"> </span><span class="str">'!'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
    feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_12" style=""><span class="kwd">def</span><span class="pln"> askFeeling</span><span class="pun">(</span><span class="pln">timeOfDay</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Good '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> timeOfDay </span><span class="pun">+</span><span class="pln"> </span><span class="str">'!'</span><span class="pun">)</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you feeling?'</span><span class="pun">)</span><span class="pln">
    feeling </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'I am happy to hear that you are feeling '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> feeling </span><span class="pun">+</span><span class="pln"> </span><span class="str">'.'</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> timeOfDay </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">[</span><span class="str">'morning'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'afternoon'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'evening'</span><span class="pun">]:</span><span class="pln">
    askFeeling</span><span class="pun">(</span><span class="pln">timeOfDay</span><span class="pun">)</span></pre>

<p>
	ونلاحظ أن الشيفرة المسؤولة عن عرض رسائل الترحيب "!Good morning/afternoon/evening" أي صباح/ظهر/مساء الخير الناتجة بعض التخلص من التكرار متشابهة ولكنها غير متطابقة، ففي التطوير الثالث لحل المشكلة ثبتنا الأجزاء المتطابقة من الشيفرة لتجنب التكرار، في حين يحل المعامل <code>timeOfDay</code> ومتغير الحلقة <code>timeOfDay</code> محل الأجزاء المتغيرة، وبذلك وبعد التخلص من التكرار عبر إزالة النسخ الزائدة، ما علينا سوى التعديل في مكان واحد متى ما احتجنا ذلك.
</p>

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

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

<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>
	ليس عجبًا إن قلنا أنّ البرمجة تتضمن استخدام الأرقام، إلا أن بعض الأرقام التي تظهر ضمن شيفرتك المصدرية قد تكون مصدر إرباك لمبرمج آخر يقرؤها (أو حتى لك أنت بعد مرور عدة أسابيع على كتابتك لها) وهي ما ندعوه بالأرقام السحرية magic numbers أي تلك الأرقام في الشيفرة التي قد تبدو عشوائية أو عديمة السياق والمعنى، فعلى سبيل المثال، لاحظ الرقم <code>604800</code> في السطر البرمجي التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_14" style=""><span class="pln">expiration </span><span class="pun">=</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">604800</span></pre>

<p>
	تعيد الدالة <code>()time.time</code> رقمًا صحيحًا يمثل الوقت الحالي، ويمكننا فهم أن المتغير <code>expiration</code> والذي يعني وقت الانتهاء يمثل لحظة زمنية ما بعد مرور زمن قدره 604800 ثانية، إلا أن هذا الرقم هو مصدر الإرباك الأساسي، وأول ما سيتبادر إلى الذهن "ما مغزى تاريخ انتهاء الصلاحية هذا؟"، وفي الواقع، تعليق بسيط قد يحل المشكلة، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_16" style=""><span class="pln">expiration </span><span class="pun">=</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">604800</span><span class="pln">  </span><span class="com"># Expire in one week.</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_18" style=""><span class="com"># Set up constants for different time amounts:</span><span class="pln">
SECONDS_PER_MINUTE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln">
SECONDS_PER_HOUR   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_MINUTE
SECONDS_PER_DAY    </span><span class="pun">=</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_HOUR
SECONDS_PER_WEEK   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">  </span><span class="pun">*</span><span class="pln"> SECONDS_PER_DAY

</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">

expiration </span><span class="pun">=</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">()</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> SECONDS_PER_WEEK  </span><span class="com"># Expire in one week.</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_20" style=""><span class="pln">NUM_CARDS_IN_DECK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">52</span><span class="pln">
NUM_WEEKS_IN_YEAR </span><span class="pun">=</span><span class="pln"> </span><span class="lit">52</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'This deck contains'</span><span class="pun">,</span><span class="pln"> NUM_CARDS_IN_DECK</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cards.'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'The 2-year contract lasts for'</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"> NUM_WEEKS_IN_YEAR</span><span class="pun">,</span><span class="pln"> </span><span class="str">'weeks.'</span><span class="pun">)</span></pre>

<p>
	ولدى تشغيل الشيفرة السابقة، سيبدو الخرج بالشكل:
</p>

<pre class="ipsCode">This deck contains 52 cards.
The 2-year contract lasts for 104 weeks.
</pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_23" style=""><span class="pln">NUM_CARDS_IN_DECK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">53</span><span class="pln">
NUM_WEEKS_IN_YEAR </span><span class="pun">=</span><span class="pln"> </span><span class="lit">52</span></pre>

<p>
	كما من الممكن إسقاط مصطلح الرقم السحري على بعض القيم غير الرقمية، فمن الممكن مثلًا استخدام قيم من <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%A6%D9%85-%D9%88%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-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r223/" rel="">سلاسل نصية</a> كثوابت، فلنأخذ مثلًا الشيفرة التالية التي تطلب من المستخدم إدخال اتجاه من الاتجاهات الأربعة لتعيد رسالة تحذيرية في حال كون الاتجاه المدخل هو الشمال north، فإن الخطأ الطباعي في كتابة كلمة "شمال" على الصورة "nrth" ستؤدي لوقوع مشكلة ستمنع البرنامج من عرض رسالة التحذير المطلوبة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_25" style=""><span class="kwd">while</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Set solar panel direction:'</span><span class="pun">)</span><span class="pln">
    direction </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">().</span><span class="pln">lower</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> direction </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">(</span><span class="str">'north'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'south'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'east'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'west'</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">break</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Solar panel heading set to:'</span><span class="pun">,</span><span class="pln"> direction</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"> direction </span><span class="pun">==</span><span class="pln"> </span><span class="str">'nrth'</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Warning: Facing north is inefficient for this panel.'</span><span class="pun">)</span></pre>

<p>
	والواقع أن هذا الخطأ من أنواع الأخطاء التي يصعب اكتشافها، نظرًا لكون السلسلة النصية <code>nrth</code> الواردة في السطر رقم 1 صحيحة من وجهة نظر <a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">بايثون</a> رغم كونها خاطئة لغويًا، وبالتالي لن يتوقف البرنامج عن العمل، ولكن سنلاحظ عدم ظهور رسالة التحذير المتوقعة، أما في حال وقوعنا بنفس هذا الخطأ الطباعي مع استخدام الثوابت، فسيتوقف البرنامج عارضًا رسالة خطأ مفادها عدم وجود ثابت باسم <code>NRTH</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_27" style=""><span class="com"># Set up constants for each cardinal direction:</span><span class="pln">
NORTH </span><span class="pun">=</span><span class="pln"> </span><span class="str">'north'</span><span class="pln">
SOUTH </span><span class="pun">=</span><span class="pln"> </span><span class="str">'south'</span><span class="pln">
EAST </span><span class="pun">=</span><span class="pln"> </span><span class="str">'east'</span><span class="pln">
WEST </span><span class="pun">=</span><span class="pln"> </span><span class="str">'west'</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="kwd">True</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Set solar panel direction:'</span><span class="pun">)</span><span class="pln">
    direction </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">().</span><span class="pln">lower</span><span class="pun">()</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> direction </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">(</span><span class="pln">NORTH</span><span class="pun">,</span><span class="pln"> SOUTH</span><span class="pun">,</span><span class="pln"> EAST</span><span class="pun">,</span><span class="pln"> WEST</span><span class="pun">):</span><span class="pln">
        </span><span class="kwd">break</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Solar panel heading set to:'</span><span class="pun">,</span><span class="pln"> direction</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"> direction </span><span class="pun">==</span><span class="pln"> NRTH</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Warning: Facing north is inefficient for this panel.'</span><span class="pun">)</span></pre>

<p>
	إن السطر رقم 1 من الشيفرة السابقة مع الخطأ الطباعي في كلمة <code>NRTH</code> سيثير لدى تشغيله استثناء NameError جاعلًا مصدر الخطأ جليًا على الفور:
</p>

<pre class="ipsCode">Set solar panel direction:
west
Solar panel heading set to: west
Traceback (most recent call last):
  File "panelset.py", line 14, in &lt;module&gt;
    if direction == NRTH:
NameError: name 'NRTH' is not defined
</pre>

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

<h2>
	إلغاء الشيفرات بتحويلها إلى تعليقات ومفهوم الشيفرة الميتة
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_30" style=""><span class="pln">doSomething</span><span class="pun">()</span><span class="pln">
</span><span class="com">#doAnotherThing()</span><span class="pln">
doSomeImportantTask</span><span class="pun">()</span><span class="pln">
doAnotherThing</span><span class="pun">()</span></pre>

<p>
	تثير هذه الشيفرة العديد من التساؤلات، لم حوّلت الدالة <code>()doAnotherThing</code> إلى تعليق؟ هل من المتوقع أن نحتاجها لاحقًا؟ لمَ لم يتم إقصاؤها لدى استدعائها للمرة الثانية؟ هل كانت هذه الشيفرة في الأصل تستدعي الدالة <code>()doAnotherThing</code> مرتين؟ أم أنه استدعاء واحد أصلًا وتم نقله إلى ما بعد استدعاء الدالة <code>()doSomeImportantTask</code>؟ هل من سبب واضح لعدم حذف هذه الدالة المستبعدة؟ في الواقع، ما من إجابات متاحة بسهولة لكل هذه التساؤلات.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> random
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> coinFlip</span><span class="pun">():</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">if</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">randint</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="pun">...</span><span class="pln">         </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'Heads!'</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'Tails!'</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">return</span><span class="pln"> </span><span class="str">'The coin landed on its edge!'</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">coinFlip</span><span class="pun">())</span><span class="pln">
</span><span class="typ">Tails</span><span class="pun">!</span></pre>

<p>
	في الشيفرة السابقة، يمكن عد القيمة المعادة "!The coin landed on its edge" كشيفرة ميتة، إذ أن الشيفرة ستعيد قيم لحالات تحقق وعدم تحقق الشرط قبل أن يتمكن التنفيذ من بلوغ هذا السطر. قد تسبب الشيفرات الميتة الضياع لأن المبرمج القارئ لهذه الشيفرة سيعتبرها كجزء فعال من البرنامج في حين أن تأثيرها على الخرج لا يتعدى تأثير التعليقات عليه.
</p>

<p>
	يُستثنى من دلالات الأخطاء الشيفرة النائب Stubs، وهي عبارة عن مواضع مؤقتة للشيفرات المستقبلية، كالدوال والأصناف التي لم يتم تطبيقها بعد، فبدلًا من استخدام شيفرات حقيقية، يتضمن النائب عبارة مرور pass فقط، والتي لا تقوم بأي دور فعليًا (تسمى أيضًا العبارة عديمة الدور no operation أو no-op)، فالتعليمة pass موجودة لتستخدمها في الأماكن المفروض استخدام تعليمات فيها، في حين أنك لا ترغب بإضافتها الآن، لتنشئ بدلًا من ذلك شيفرة نائب مؤقتة، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_34" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> exampleFunction</span><span class="pun">():</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">pass</span><span class="pln">
</span><span class="pun">…</span></pre>

<p>
	إن استدعاء الدالة السابقة لن يقوم بأي وظيفة، سوى الإشارة إلى أنه ستتم إضافة شيفرات له لاحقًا.
</p>

<p>
	وكبديل عن استدعاء تابع لا يقوم بأي دور، يمكنك جعله يعرض بالنيابة (عن دوره المتوقع المستقبلي) رسالة مفادها أن هذه الدالة ليست جاهزة للاستدعاء بعد باستخدام التعليمة <code>raise NotImplementedError</code>، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_36" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> exampleFunction</span><span class="pun">():</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">NotImplementedError</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> exampleFunction</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> exampleFunction
</span><span class="typ">NotImplementedError</span></pre>

<p>
	ظهور الرسالة <code>NotImplementedError</code> سيمثل تنبيه لحالة استدعاء البرنامج لدالة أو تابع نائب عن طريق الصدفة.
</p>

<p>
	إذًا تعد كل من الشيفرات الملغاة بتحويلها إلى تعليقات والشيفرات الميتة من مؤشرات وقوع أخطاء، إذ أنها قد تضيع المبرمج بظنها جزء يجب تنفيذه من الشيفرة، واحذف بدلًا من ذلك هذه الشيفرات واستخدم نظام إدارة شيفرة مثل <a href="https://academy.hsoub.com/programming/workflow/git/%D9%85%D8%A7-%D9%87%D9%88-git%D8%9F-r1592/" rel="">Git</a> أو Subversion مما يتيح لك تتبع التغييرات دائمًا، فباستخدام هذه الأنظمة يمكنك حذف أي أجزاء تريد من الشيفرة وإعادتها لاحقًا بسهولة متى رغبت.
</p>

<h2>
	التنقيح باستخدام دالة الطباعة
</h2>

<p>
	التنقيح باستخدام دالة الطباعة هو الإجراء المتمثل باستدعاء الدالة <code>()print</code> مؤقتًا ضمن البرنامج بغية عرض قيم المتغيرات قبل تشغيل البرنامج، وعادةً ما تمر هذه العملية بالخطوات التالية:
</p>

<ol>
	<li>
		ملاحظة وجود خطأ في البرنامج.
	</li>
	<li>
		إضافة بعض الاستدعاءات للدالة <code>()print</code> لبعض المتغيرات في محاولة معرفة ما تحتويه.
	</li>
	<li>
		إعادة تشغيل البرنامج.
	</li>
	<li>
		إضافة المزيد من الاستدعاءات للدالة <code>()print</code> لأن الاستدعاءات السابقة لم تعرض ما يكفي من معلومات.
	</li>
	<li>
		إعادة تشغيل البرنامج.
	</li>
	<li>
		تكرار الخطوتين السابقتين عدة مرات إلى حين اكتشاف موضع الخطأ.
	</li>
	<li>
		إعادة تشغيل البرنامج.
	</li>
	<li>
		إدراك أنك قد نسيت حذف بعضًا من استدعاءات الدالة <code>()print</code>، فتحذف ما تبقى منها.
	</li>
</ol>

<p>
	إن <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> باستخدام دالة الطباعة مغرٍ ببساطته، إلا أنه يتطلب في الغالب إعادة تشغيل البرنامج مراتٍ ومرات قبل استعراض المعلومات التي تحتاجها فعلًا لإصلاح الخطأ، ويكون الحل البديل باستخدام منقح الأخطاء أو إنشاء مجموعة من الملفات السجل logfiles لبرنامجك، فباستخدام منقح الأخطاء يمكنك تنفيذ شيفرتك سطرًا تلو الآخر فاحصًا أي متغير تريد، وقد يبدو استخدام منقح الأخطاء هذا أبطأ من مجرد إضافة استدعاءات لدالة الطباعة ببساطة، إلا أنّه يوفّر عليك الوقت الضائع بالتشغيل المتكرر.
</p>

<p>
	في حين أن ملفات السجل قادرة على توفير كمية كبيرة من المعلومات حول برنامجك عبر مقارنة ملف سجل حالي بآخر سابق، وتوفر الوحدة <code>logging</code> في بايثون آلية سهلة لإنشاء ملفات السجل باستخدام شيفرة بسيطة مكونة من ثلاث سطور فقط:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_38" style=""><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">filename</span><span class="pun">=</span><span class="str">'log_filename.txt'</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"> format</span><span class="pun">=</span><span class="str">'%(asctime)s - %(levelname)s - %(message)s'</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="str">'This is a log message.'</span><span class="pun">)</span></pre>

<p>
	فبعد استيراد وحدة السجل <code>logging</code> وضبط إعداداتها الرئيسية، يصبح من الممكن استدعاء التابع <code>()logging.debug</code> لكتابة معلومات السجل ضمن مستند نصي، في حين أن الدالة <code>()print</code> تعرض معلوماتها على شاشة الخرج.
</p>

<p>
	وعلى النقيض من التنقيح باستخدام دالة الطباعة، فإن استدعاء الدالة <code>()logging.debug</code> يجعل من الواضح أي أجزاء من الخرج هي معلومات تنقيحية وأيها خرج البرنامج الفعلي.
</p>

<h2>
	المتغيرات ذات اللاحقات الرقمية
</h2>

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

<p>
	وإلى جانب أن هذه الأسماء لا تعبّر عن مضمون المتغيرات أو الاختلافات فيما بينها، فهي لا تشير أيضًا إلى عدد المتغيرات المشابهة الإجمالي، تاركةً القارئ في حيرة متسائلًا: أيوجد متغير أيضًا باسم <code>password3</code> أو <code>password4</code> ربما؟ فحاول دائمًا استخدام أسماء معبرة ومميزة <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r221/" rel="">للمتغيرات</a> ولا تتكاسل بمجرد إضافة لاحقة رقمية لاسم المتغير السابق، ولعل أفضل تسمية للمتغيرين في مثالنا هذا هي <code>password</code> للأول و<code>confirm_password</code> للثاني.
</p>

<p>
	لنأخذ مثالًا آخر، بفرض أنه لدينا تابع يتعامل مع إحداثيات بداية ونهاية، فقد تسمي المعاملات حينها <code>x1</code> و <code>y1</code> و <code>x2</code> و <code>y2</code> على التوالي، إلا أن هذه الأسماء لا تقدّم معلوماتٍ كما لو أسميتها <code>start_x</code> و <code>start_y</code> و <code>end_x</code> و <code>end_y</code>، ناهيك عن كون الاسمين <code>start_x</code> و <code>start_y</code> أكثر ترابطًا من <code>x1</code> و<code>y1</code> كتعبير عن تمثيلهما لإحداثيات نقطة البداية start.
</p>

<p>
	أما في حال تجاوز عدد المتغيرات ذات اللواحق الرقمية لاثنين، فعندها من المستحسن استخدام بنية معطيات كالقائمة list أو المجموعة set لتخزين هذه البيانات ضمن هيكلية، فمثلًا لو كان لدينا مجموعة من المتغيرات بالأسماء <code>pet1Name</code> و <code>pet1Name</code> و<code>pet1Name</code> وهكذا فمن الممكن تخزين قيمها ضمن قائمة واحدة باسم <code>petNames</code>.
</p>

<p>
	ومن الجدير بالملاحظة أن اللاحقة الرقمية لا تعد دلالة على الخطأ في أي متغير منتهٍ برقم، فمثلًا يعتبر الاسم <code>enableIPV6</code> مثاليًا لمتغير، لأن الرقم 6 هو جزء من اسم <a href="https://academy.hsoub.com/devops/networking/%D8%A7%D9%84%D8%A5%D8%B5%D8%AF%D8%A7%D8%B1-%D8%A7%D9%84%D8%B3%D8%A7%D8%AF%D8%B3-%D9%85%D9%86-%D8%A8%D8%B1%D9%88%D8%AA%D9%88%D9%83%D9%88%D9%84-ip-r504/" rel="">البروتوكول "IPV6"</a> ولا يمثّل لاحقة رقمية. أما في حال كنت ممن يستخدمون اللواحق الرقمية لتسمية سلسلة من المتغيرات، فمن المفضّل بدلًا من ذلك تخزين قيمها ضمن بنية معطيات ما، كقائمة أو قاموس أو غيرها.
</p>

<h2>
	الأصناف التي يجب أن تكون مجرد دوال أو توابع
</h2>

<p>
	اعتاد المبرمجون ممن يستخدمون لغات برمجة مثل <a href="https://academy.hsoub.com/programming/java/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%85%D8%A7-%D9%87%D9%8A%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7-java-r1515/" rel="">جافا Java</a> على إنشاء الأصناف بغية تنظيم شيفرات برامجهم، لنأخذ على سبيل المثال الصنف التالي المسمى <code>Dice</code> (بمعنى حجر النرد) والمتضمّن للتابع <code>()roll</code> (والمقصود به رمي حجر النرد):
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> random
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Dice</span><span class="pun">:</span><span class="pln">
</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"> sides</span><span class="pun">=</span><span class="lit">6</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">sides </span><span class="pun">=</span><span class="pln"> sides
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">def</span><span class="pln"> roll</span><span class="pun">(</span><span class="pln">self</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         </span><span class="kwd">return</span><span class="pln"> random</span><span class="pun">.</span><span class="pln">randint</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">sides</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Dice</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You rolled a'</span><span class="pun">,</span><span class="pln"> d</span><span class="pun">.</span><span class="pln">roll</span><span class="pun">())</span><span class="pln">
</span><span class="typ">You</span><span class="pln"> rolled a </span><span class="lit">1</span></pre>

<p>
	فقد تبدو الشيفرة السابقة بأنها شيفرة عالية التنظيم، ولكن ماذا لو فكرنا باحتياجاتنا الفعلية من هذه الشيفرة؟ أليست مجرد الحصول على رقم عشوائي محصور بين 1 و 6، وبالتالي من الممكن استبدال كامل الصنف السابق باستدعاء بسيط لتابع بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_42" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You rolled a'</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="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">))</span><span class="pln">
</span><span class="typ">You</span><span class="pln"> rolled a </span><span class="lit">6</span></pre>

<p>
	فبالمقارنة مع <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> الأخرى، تستخدم <a href="https://wiki.hsoub.com/Python" rel="external">لغة بايثون</a> منهجية غير رسمية في تنظيم الشيفرات، لأن شيفراتها لا تتطلب تضمينها في صنف أو أي بنية متداولة أخرى، فإن كنت تُنشئ الكائنات بغية استدعاء تابع وحيد ضمنها، أو تُنشئ الأصناف لتحتوي فقط على توابع ساكنة غير مرتبطة بالكائنات، فكل هذه الإجراءات من دلالات الأخطاء التي تشير لأفضلية كتابة دوال اعتيادية بدلًا منها.
</p>

<p>
	إذ أننا نستخدم في بايثون الوحدات لتجميع <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r292/" rel="">الدوال</a> مع بعضها البعض بدلًا من استخدام الأصناف، ذلك لأن الأصناف بحد ذاتها يجب أن تتواجد ضمن وحدات بطبيعة الحال، ما يجعل تضمين الدوال في أصناف مجرد إضافة غير ضرورية لمستوى تنظيمي جديد لشيفرتك، وتناقش الفصول من 15 حتى 17 في كتابنا هذا مبادئ التصميم كائني التوجّه تفصيليًا، كما تحدث Jack Diederich’s في خطابه ضمن مؤتمر بايثون لعام 2012 تحت عنوان Stop Writing Classes "كفوا عن كتابة الأصناف" حول العديد من الطرق التي يستخدمها المبرمجون، مضيفين بذلك تعقيدًا غير ضروريًا لشيفراتهم المكتوبة في بايثون.
</p>

<h2>
	بنى اشتمالات القوائم المتداخلة
</h2>

<p>
	يعد اشتمال القوائم List comprehensions طريقة مختصرة لإنشاء قائمة ذات قيم معقدة، فمثلًا لإنشاء قائمة سلاسل محرفية متضمنةً الأرقام من 0 حتى 100 باستثناء مضاعفات العدد 5، فعادةً ما ستستخدم حلقة <code>for</code> بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_44" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</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">100</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</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="pln"> </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">         spam</span><span class="pun">.</span><span class="pln">append</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="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">[</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'3'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'4'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'7'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'12'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'13'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'14'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'16'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'17'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
</span><span class="str">'86'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'87'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'88'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'89'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'91'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'92'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'93'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'94'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'96'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'97'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'98'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'99'</span><span class="pun">]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_46" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</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">for</span><span class="pln"> number </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">100</span><span class="pun">)</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="pln"> </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">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">[</span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'3'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'4'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'7'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'12'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'13'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'14'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'16'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'17'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
</span><span class="str">'86'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'87'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'88'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'89'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'91'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'92'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'93'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'94'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'96'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'97'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'98'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'99'</span><span class="pun">]</span></pre>

<p>
	كما تمتلك لغة بايثون صيغًا لاشتمال كل من القواميس والمجموعات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_48" style=""><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</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">for</span><span class="pln"> number </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">100</span><span class="pun">)</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="pln"> </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">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">{</span><span class="str">'39'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'31'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'96'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'76'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'91'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'71'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'24'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'22'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'14'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'62'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
</span><span class="str">'4'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'57'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'49'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'51'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'63'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'78'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'93'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'86'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'92'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'64'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'37'</span><span class="pun">}</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam </span><span class="pun">=</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"> number </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">100</span><span class="pun">)</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="pln"> </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">&gt;&gt;&gt;</span><span class="pln"> spam
</span><span class="pun">{</span><span class="str">'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="str">'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="str">'3'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="str">'4'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="str">'7'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="str">'8'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">11</span><span class="pun">,</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
</span><span class="str">'92'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">92</span><span class="pun">,</span><span class="pln"> </span><span class="str">'93'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">93</span><span class="pun">,</span><span class="pln"> </span><span class="str">'94'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">94</span><span class="pun">,</span><span class="pln"> </span><span class="str">'96'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">96</span><span class="pun">,</span><span class="pln"> </span><span class="str">'97'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">97</span><span class="pun">,</span><span class="pln"> </span><span class="str">'98'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">98</span><span class="pun">,</span><span class="pln"> </span><span class="str">'99'</span><span class="pun">:</span><span class="pln"> </span><span class="lit">99</span><span class="pun">}</span></pre>

<p>
	أنشأنا في السطر ذو الرقم 1 بنية اشتمال مجموعة باستخدام الأقواس المعقوصة بدلًا من المعقوفة لتُنتج مجموعة من القيم، أما في السطر ذو الرقم 2 فأنشأنا بنية اشتمال قاموس باستخدام محرف النقطتين الرأسيتين لفصل المفتاح عن القيم ضمن الاشتمال.
</p>

<p>
	وبذلك نجد أن بنى الاشتمال مختصرة وقادرة على زيادة مقروئية شيفراتك، ومن الجدير بالملاحظة أن الاشتمالات تولّد قائمة أو مجموعة أو قاموس اعتمادًا على كائن تكراري (ففي مثالنا السابق حصلنا على القيمة المعادة من الكائن range من خلال الاستدعاء <code>(range(100</code>)، فالقوائم والمجموعات والقواميس بطبيعتها كائنات تكرارية، ما يعني إمكانية استخدام اشتمالات متداخلة كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_50" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedIntList </span><span class="pun">=</span><span class="pln"> </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="pln"> </span><span class="lit">3</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="pun">[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</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">9</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedStrList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[[</span><span class="pln">str</span><span class="pun">(</span><span class="pln">i</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"> sublist</span><span class="pun">]</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> sublist </span><span class="kwd">in</span><span class="pln"> nestedIntList</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedStrList
</span><span class="pun">[[</span><span class="str">'0'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'3'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'4'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'5'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'7'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">]]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_52" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedIntList </span><span class="pun">=</span><span class="pln"> </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="pln"> </span><span class="lit">3</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="pun">[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</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">9</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedStrList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> sublist </span><span class="kwd">in</span><span class="pln"> nestedIntList</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     nestedStrList</span><span class="pun">.</span><span class="pln">append</span><span class="pun">([</span><span class="pln">str</span><span class="pun">(</span><span class="pln">i</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"> sublist</span><span class="pun">])</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedStrList
</span><span class="pun">[[</span><span class="str">'0'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'1'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'2'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'3'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'4'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'5'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'6'</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'7'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'8'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9'</span><span class="pun">]]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_54" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedList </span><span class="pun">=</span><span class="pln"> </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="pln"> </span><span class="lit">3</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="pun">[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</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">9</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> flatList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">num </span><span class="kwd">for</span><span class="pln"> sublist </span><span class="kwd">in</span><span class="pln"> nestedList </span><span class="kwd">for</span><span class="pln"> num </span><span class="kwd">in</span><span class="pln"> sublist</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> flatList
</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="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"> </span><span class="lit">5</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">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">9</span><span class="pun">]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_56" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> nestedList </span><span class="pun">=</span><span class="pln"> </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="pln"> </span><span class="lit">3</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="pun">[</span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</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">9</span><span class="pun">]]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> flatList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> sublist </span><span class="kwd">in</span><span class="pln"> nestedList</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"> num </span><span class="kwd">in</span><span class="pln"> sublist</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">         flatList</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> flatList
</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="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"> </span><span class="lit">5</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">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">9</span><span class="pun">]</span></pre>

<p>
	إذًا تعد الاشتمالات كاختصارات قادرة على اختصار الشيفرات شريطة عدم المبالغة والذهاب نحو خيار الاشتمالات المتداخلة صعبة القراءة والفهم.
</p>

<h2>
	كتل الاستثناءات except الفارغة ورسائل الأخطاء الضعيفة
</h2>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_58" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     num </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">(</span><span class="str">'Enter a number: '</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     num </span><span class="pun">=</span><span class="pln"> int</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="kwd">except</span><span class="pln"> </span><span class="typ">ValueError</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">pass</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="typ">Enter</span><span class="pln"> a number</span><span class="pun">:</span><span class="pln"> forty two
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> num
</span><span class="str">'forty two'</span></pre>

<p>
	لن تتوقف الشيفرة السابقة عن العمل في حال تمرير القيمة النصية 'forty two' إلى الدالة <code>()int</code>، ذلك لأنه قد تم التعامل مع خطأ القيمة <code>ValueError</code> الذي تنتجه الدالة <code>()int</code> في حالة تمرير نص بدلًا من رقم إليها من خلال عبارة الاستثناء، إلا أن عدم القيام بأي إجراء حيال الخطأ والاكتفاء بالهروب منه باستخدام استثناء فارغ قد يكون أسوأ من توقف البرنامج نتيجة هذا الخطأ، إذ أن البرامج بتوقفها تتفادى إكمال التنفيذ ببيانات خاطئة أو بنى غير مكتملة، التي قد تؤدي لأخطاء أكبر لاحقًا.
</p>

<p>
	على سبيل المثال، برنامجنا السابق لا يتوقف عن العمل حتى في حال تمرير محارف غير عددية إلى الدالة <code>()int</code>، وبذلك يصبح المتغير <code>num</code> متضمنًا لسلسلة نصية بدلًا من رقم صحيح، ما قد يؤدي لوقوع أخطاء في أي مكان يُستخدم فيه هذا المتغير، فنستنتج أن عبارة الاستثناء هذه لا تقوم بما هو أكثر من إخفاء الخطأ بدلًا من مواجهته والتعامل معه.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8784_60" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     num </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">(</span><span class="str">'Enter a number: '</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     num </span><span class="pun">=</span><span class="pln"> int</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="kwd">except</span><span class="pln"> </span><span class="typ">ValueError</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'An incorrect value was passed to int()'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="typ">Enter</span><span class="pln"> a number</span><span class="pun">:</span><span class="pln"> forty two
</span><span class="typ">An</span><span class="pln"> incorrect value was passed to int</span><span class="pun">()</span></pre>

<p>
	إن الشيفرة السابقة لن تتوقف عن العمل، وهو أمر جيد، إلا أنها بالمقابل لا تعطي المستخدم معلوماتٍ كافية لإرشاده حول كيفية إصلاح الخطأ، فيجب ألا ننسى أن رسائل الخطأ موجهة للمستخدمين وليست للمبرمجين، ففي رسالة الخطأ السابقة ناهيك كونها تتضمن معلومات تقنية لن يفهمها المستخدم العادي، كالإشارة إلى الدالة <code>()int</code>، إلا أنها لا تخبر المُستخدم بما عليه فعله لإصلاح الخطأ، فالأصل أن تشرح رسالة الخطأ ما حدث مُرشدةً المستخدم لكيفية التعامل معه.
</p>

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

<h1>
	الخاتمة
</h1>

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

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

<p>
	أما تنقيح الأخطاء المعتمد على دالة الطباعة فيعني استدعاء الدالة <code>()print</code> بغية عرض معلومات تنقيحية، ورغم سهولة هذه الطريقة، إلا أنه من الأسرع الاعتماد على منقح الأخطاء وملفات السجلات في تشخيص الأخطاء.
</p>

<p>
	ولعل الإجراء الأفضل للتعامل مع المتغيرات ذات اللواحق الرقمية مثل <code>x1</code> و <code>x2</code> و <code>x3</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> نستخدم الوحدات بدلًا من الأصناف في تجميع الدوال، فالصنف المتضمن لتابع وحيد أو لتوابع ساكنة هو أحد دلالات الأخطاء، إذ من المحبذ تضمين هذه الشيفرة في وحدة بدلًا من الصنف. أما بالنسبة لبنى اشتمال القوائم ورغم كونها طريقة مختصرة في إنشاء قوائم القيم، إلا أن تداخل هذه البنى يجعلها غير مقروءة.
</p>

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

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

<p>
	ترجمة -وبتصرف- للجزء الأول من الفصل الخامس Finding Code Smells من كتاب <a href="https://inventwithpython.com/beyond/chapter5.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigarti.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D8%A3%D8%B3%D9%85%D8%A7%D8%A1-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%85%D9%81%D9%87%D9%88%D9%85%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1932/" rel="">اختيار أسماء برمجية مفهومة في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AD%D9%84-%D8%A7%D9%84%D9%85%D8%B4%D9%83%D9%84%D8%A7%D8%AA-%D9%88%D8%A3%D9%87%D9%85%D9%8A%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D8%A7%D8%AD%D8%AA%D8%B1%D8%A7%D9%81-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r760/" rel="">حل المشكلات وأهميتها في احتراف البرمجة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1944</guid><pubDate>Sun, 02 Apr 2023 15:09:00 +0000</pubDate></item><item><title>&#x627;&#x62E;&#x62A;&#x64A;&#x627;&#x631; &#x623;&#x633;&#x645;&#x627;&#x621; &#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; &#x645;&#x641;&#x647;&#x648;&#x645;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1-%D8%A3%D8%B3%D9%85%D8%A7%D8%A1-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%85%D9%81%D9%87%D9%88%D9%85%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1932/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_03/1620108199_.png.d76d860b03b9ffe1a93b9e626233ccd3.png" /></p>
<p>
	"المسألتان الأصعب في <span ipsnoautolink="true">علم الحاسوب</span> هما ثلاثة! اختيار الأسماء وحذف أو استبدال محتويات <a href="https://academy.hsoub.com/programming/os-embedded-systems/%D9%86%D8%B8%D8%B1%D8%A9-%D8%B9%D9%85%D9%8A%D9%82%D8%A9-%D8%B9%D9%84%D9%89-%D8%AA%D8%B3%D9%84%D8%B3%D9%84-%D8%A7%D9%84%D8%B0%D9%88%D8%A7%D9%83%D8%B1-%D8%A7%D9%84%D9%87%D8%B1%D9%85%D9%8A-%D9%88%D8%A7%D9%84%D8%B0%D8%A7%D9%83%D8%B1%D8%A9-%D8%A7%D9%84%D9%85%D8%AE%D8%A8%D8%A6%D9%8A%D8%A9-%D9%81%D9%8A-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%D9%8A%D8%A9-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8-r1720/" rel="">الذاكرة المخبئية cache invalidation</a> وتجنب أخطاء التكرار المنطقية off-by-one" هي إحدى أقدم الدعابات البرمجية، المنسوبة إلى ليون بامبريك والمستوحاة من اقتباس لفيل كارلتون، إلا أنها تشير إلى حقيقة جوهرية، مفادها أن ابتكار أسماء جيدة للمتغيرات والدوال والأصناف وغيرها مما يسمى إجمالًا بالمعرفات ليست بالمهمة السهلة.
</p>

<p>
	باختصار، الأسماء القادرة على توصيف وظيفة ومضمون الأشياء مهمة لمقروئية الشيفرة البرمجية، إلا أن القول أسهل من الفعل في عملية اختيار الأسماء، فلنفرض مثلًا أنك تنتقل إلى منزل جديد، فإن كتابة كلمة "أغراض أو متاع" على كافة الصناديق المنقولة سيكون اسمًا مختصرًا ولكنه ليس معبّرًا عن محتويات كل صندوق. أو لدى اختيار اسم معبّر لكتاب برمجي، فقد يكون "ابتكر ألعاب الكمبيوتر بنفسك باستخدام <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>" ولكنه ليس مختصرًا.
</p>

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

<p>
	ومما لا شك فيه أن اختيار الأسماء هو قرار شخصي أنت المسؤول عنه، إذ لا يمكن لأداة تنسيق آلي من قبيل <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%86%D8%B3%D9%82-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%B5%D8%A7%D8%B1%D9%85-black-r1923/" rel="">المنسّق Black</a>، الذي أتينا على شرحه في المقال السابق، أن يختار الأسماء للمتغيرات الخاصة بك.
</p>

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

<h2>
	المتغيرات ذات الأسماء المؤقتة البديلة
</h2>

<p>
	عادة ما نستخدم المتغيرات ذات الأسماء المؤقتة البديلة Metasyntactic في المواد التعليمية أو في أمثلة الشيفرات البرمجية كعنصر نائب، إذ نحتاج إلى مجرد اسم فريد للمتغير. فغالبًا ما تسمى المتغيرات في أمثلة <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> بأسماء عشوائية من قبيل <code>spam</code> و <code>eggs</code> حين يكون اختيار الاسم غير مهم، ولهذا السبب نستخدم في كتابنا هذا النوع من الأسماء في أمثلة الشيفرات التي لا يكون مطلوبًا منك استخدامها في برامجك الفعلية، إذ اقتبسنا هذه الأسماء من مشهد تمثيلي لمجموعة مونتي بايثون البريطانية للكوميديا السيريالية بعنوان البريد العشوائي "Spam (Monty Python sketch)‎".
</p>

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

<h2>
	التنسيق المتعلق بحالة الحروف
</h2>

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

<p>
	وإحدى هذه الطرق هي طريقة الثعبان مع الحروف الصغيرة <code>snake_case</code>، وفيها نفصل بين الكلمات في اسم المعرف الواحد بشرطة سفلية، والتي تبدو كثعبان متمدد بين الكلمات، وتملي هذه الطريقة على استخدام الحروف الصغيرة بالكامل، عدا في حالات التصريح عن الثوابت، إذ تُستخدم حينها طريقة الثعبان مع أحرف كبيرة <code>UPPER_SNAKE_CASE</code> في الغالب.
</p>

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

<p>
	وطريقة باسكال <code>PascalCase</code>، والتي تُنسب تسميتها إلى استخدامها في لغة البرمجة باسكال، فهي مشابهة لطريقة <code>camelCase</code> إلا أن أول كلمة تبدأ أيضا بحرف كبير.
</p>

<p>
	إن حالة الحروف هي قضية تنسيقية تم تغطيتها في <a href="https://academy.hsoub.com/programming/python/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%B1-%D8%A7%D9%84%D9%85%D9%86%D8%B3%D9%82-black-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1919/" rel="">المقال السابق</a> من هذه السلسلة. والطرق الأكثر استخدامًا في تسمية المعرفات هي نمط الثعبان <code>snake_case</code> وسنام الجمل <code>camelCase</code>، وكلاهما جيدتان ولا أفضلية لإحداهما على الأخرى طالما أنك ملتزم باستخدام إحداهما فقط في مشروعك كاملًا.
</p>

<h2>
	اصطلاحات التسمية وفق دليل بايثون الإرشادي PEP 8
</h2>

<p>
	تقدم وثيقة PEP 8 بعضًا من التوصيات حيال اصطلاحات التسميات في بايثون، ومنها:
</p>

<ul>
	<li>
		كل الحروف يجب أن تكون وفق نظام الآسكي ASCII، أي حروف إنجليزية بحالتيها الكبيرة والصغيرة دون إشارات الحركات.
	</li>
	<li>
		يجب تسمية الوحدات بأسماء قصيرة وبحروف صغيرة.
	</li>
	<li>
		يجب تسمية الأصناف وفق طريقة <code>PascalCase</code>.
	</li>
	<li>
		يجب تسمية الثوابت وفق طريقة <code>UPPER_SNAKE_CASE</code>.
	</li>
	<li>
		يجب تسمية <a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">الدوال</a> والتوابع و<a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r221/" rel="">المتغيرات</a> وفق طريقة <code>snake_case</code> بحروف صغيرة.
	</li>
	<li>
		يجب تسمية أول وسيط في التوابع باستخدام حروف صغيرة.
	</li>
	<li>
		يجب تسمية أول وسيط في تابع الصنف بالاسم <code>cls</code> وبحروف صغيرة.
	</li>
	<li>
		يجب أن تبدأ السمات الخاصة في الصنف دائما بعلامة الشرطة السفلية.
	</li>
	<li>
		يجب ألا تبدأ السمات العامة في الصنف بعلامة الشرطة السفلية أبدًا.
	</li>
</ul>

<p>
	يمكنك التغاضي عن هذه القواعد وفق الضرورات، فمثلًا وعلى الرغم من كون اللغة الإنجليزية هي المألوفة برمجيًا، إلا أنك تستطيع استخدام محارف أي لغة أخرى، فمثلًا <code>'コンピューター = 'laptop</code> هي شيفرة برمجية صالحة نحويًا في بايثون، وكذلك يمكن استخدام اللغة العربية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_6" style=""><span class="pun">コンピューター</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'laptop'</span><span class="pln">
</span><span class="pun">المنتج</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'laptop'</span></pre>

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

<p>
	كما يمكنك الاطلاع على قسم "اصطلاحات التسمية" في دليل PEP 8 كاملًا بزيارة <a href="https://www.python.org/dev/peps/pep-0008/#naming-conventions." rel="external nofollow">python.org</a>.
</p>

<h2>
	اختيار الطول المناسب للاسم
</h2>

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

<h3>
	أسماء قصيرة جدا
</h3>

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

<ul>
	<li>
		الأسماء المكونة من حرف أو اثنين، كالاسم <code>g</code> الذي يشير عادةً لكلمة تبدأ بهذا الحرف، وما أكثرها! فرغم كون الاختصارات والأسماء المكونة من حرف واحد أو حرفين سهلة للكتابة بالنسبة لك، إلا أنها صعبة القراءة والفهم لغيرك.
	</li>
	<li>
		الاختصارات، فاختصار مثل <code>mon</code> يشير إلى عدد كبير من الكلمات مثل monitor و month و monster وغيرها الكثير.
	</li>
	<li>
		الأسماء المكونة من كلمة واحدة قد تكون غامضة أيضًا، كالاسم <code>start</code> والذي يعني "بداية"، ولكن بداية ماذا؟ إذ يفتقد هذا النوع من الأسماء إلى السياق الواضح عند قراءة الشيفرة من قبل غير كاتبها.
	</li>
</ul>

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

<p>
	وفيما يلي بعض الاستثناءات التي يكون من المناسب فيها استخدام الأسماء القصيرة، فمثلًا من الشائع استخدام <code>i</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> التي تمر على نطاق من الأعداد أو مؤشرات قائمة ما، كما من الشائع استخدام كلًا من الحرفين <code>j</code> و <code>k</code> (كونهما الحرفان التاليان للحرف i أبجديًا) في حال استخدامك لعدّة حلقات متداخلة، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_8" style=""><span class="pun">&gt;&gt;&gt;</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">10</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"> j </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">3</span><span class="pun">):</span><span class="pln">
</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"> j</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="lit">0</span><span class="pln">
</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="lit">2</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="pln">snip</span><span class="pun">--</span></pre>

<p>
	كما أنّ استخدام الحرفين <code>x</code> و <code>y</code> في تمثيل الإحداثيات الديكارتية يمثّل استثناءً آخر. وفيما عدا ذلك لا أنصح باستخدام أسماء بحرفٍ واحد على الإطلاق، فرغم كونها جذابة للاستخدام، كأن تستخدم الاسم <code>w</code> للدلالة على العرض width والاسم <code>h</code> للدلالة على الارتفاع height والاسم <code>n</code> للدلالة على عدد ما number، إلا أنها لن تكون واضحة ومفهومة للآخرين.
</p>

<h4>
	لا تختصر حروفا من شيفرتك المصدرية
</h4>

<p>
	كانت طريقة اختصار الأحرف من الكلمات شائعة الاستخدام في الفترة ما قبل تسعينيات القرن الماضي في لغة البرمجة C، كأن نستخدم الاسم <code>memcpy</code> للدلالة على نسخة ذاكرة memory copy أو <code>strcmp</code> للدلالة على المقارنة بين السلاسل النصية string compare، إلا أن هذه الطريقة تعد نمطًا غير مقروء من أنماط التسمية ويجب عدم استخدامها في أيامنا، فإن كان من الصعب نطق هذا الاسم، فما بالك بفهمه؟ لن يكون سهلًا بالطبع.
</p>

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

<h3>
	أسماء طويلة جدا
</h3>

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

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

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

<h2>
	استخدام البادئات في الأسماء
</h2>

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

<p>
	ومن الممارسات المشابهة والتي قد عفا عليها الزمن هي اتباع الطريقة الهنغارية في ترميز الأسماء، والتي تنص على تضمين اختصار لنمط البيانات الذي سيتضمنه المتغير ضمن اسمه، فمثلًا وفق هذه الطريقة يشير اسم المتغير <code>strName</code> على أنّ هذا المتغير يتضمّن بيانات من النوع <a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d8%a7%d9%84%d9%82%d9%88%d8%a7%d8%a6%d9%85-%d9%88%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-%d9%84%d8%ba%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r223/" rel="">سلسلة نصية</a>، والاسم <code>iVacationDays</code> يشير إلى أن المتغير يتضمّن بيانات من النوع عدد صحيح. أما في وقتنا الحاضر فإن اللغات الحديثة وبيئات التطوير المتكاملة قادرة على تزويد المبرمج بهذه المعلومات دون الحاجة لاستخدام البادئات، جاعلةً من الطريقة الهنغارية إجراءً غير ضروريًا، فإن كنت ممن اعتادوا تضمين نمط البيانات ضمن الأسماء، ابدأ بالتخلي عن هذه الطريقة.
</p>

<p>
	ولكن ومن ناحية أخرى، فإنّه من المفيد استخدام بادئات من قبل <code>is</code> بمعنى "أهو؟ أو هو يكون" و <code>has</code> بمعنى "لديه أو ذي" ضمن أسماء المتغيرات المُتضمنة لقيم منطقية أي من النوع Boolean، أو ضمن أسماء الدوال والتوابع التي تعيد قيمًا منطقية، لما لذلك من دور في زيادة المقروئية، فمثلًا في المثال التالي، لاحظ استخدام متغير باسم <code>is_vehicle</code> بمعنى "فإنه مركبة" وتابع باسم <code>()has_key</code> بمعنى "يملك المفتاح":
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_10" style=""><span class="kwd">if</span><span class="pln"> item_under_repair</span><span class="pun">.</span><span class="pln">has_key</span><span class="pun">(</span><span class="str">'tires'</span><span class="pun">):</span><span class="pln"> 
  is_vehicle </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">True</span></pre>

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

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

<p>
	فمثلًا، فُقد مسبار المريخ الفضائي الآلي المداري عام 1999 بسبب اختلاف وحدات قياس الحسابات الناتجة عن البرمجيات التي أنتجتها شركة Lockheed Martin والتي استخدمت وحدات القياس البريطانية، وتلك الناتجة عن أنظمة وكالة الفضاء الدولية (ناسا) والتي استخدمت وحدات القياس المترية، ما أدى كنتيجة إلى تحديد المسار بشكل خاطئ، وخسائر قدرت بنحو 125 مليون دولار أمريكي.
</p>

<h2>
	اللاحقات الرقمية المتتالية
</h2>

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

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

<p>
	كذلك الأمر بالنسبة للدوال ذات الأسماء من قبيل <code>(makePayment1(amount</code> و<code>(makePayment2(amount</code> وهكذا، والتي يجب استبدالها بدالة وحيدة تقبل وسيطًا من النوع عدد صحيح، ليصبح استدعاؤها بالشكل: <code>(makePayment(1, amount</code> و<code>(makePayment(2, amount</code> وهكذ.
</p>

<p>
	أما في حال كون تلك الدوال ذات وظائف مختلفة، بما يفرض استخدام دوال مستقلة، فمن الحري بنا في هذه الحالة استبدال الرقم في الاسم بما يوضح دور الدالة، مثل:
</p>

<ul>
	<li>
		<code>(makeLowPriorityPayment(amount</code> لتدل على المدفوعات ذات الأولوية الأقل
	</li>
	<li>
		<code>(makeHighPriorityPayment(amount</code> للدلالة على المدفوعات ذات الأولوية الأعلى
	</li>
	<li>
		<code>(make1stQuarterPayment(amount</code> للدلالة على مدفوعات الربع الأول من السنة
	</li>
	<li>
		<code>(make2ndQuarterPayment(amount</code> للدلالة على مدفوعات الربع الثاني من السنة
	</li>
</ul>

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

<h2>
	استخدم أسماء يسهل البحث عنها
</h2>

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

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

<p>
	فمع التزامك بهذه القواعد، سيصبح اختيار أسماء توصيفية دقيقة بدلًا من تلك العامة المختصرة أمرًا بديهيًا بالنسبة لك، فلا تقتصر أهمية اختيار الأسماء المناسبة على تحسين المقروئية وحسب، بل تجعل من مهمة البحث عن المتغير ضمن الشيفرة أمرًا أسهل، فاختيارك مثلًا للاسم <code>email</code> سيكون مبهمًا، في حين أن إضافة بعض التفاصيل من قبيل <code>emailAddress</code> أو <code>downloadEmailAttachment</code> أو <code>emailMessage</code> أو <code>replyToAddress</code> سيكون أفضل بكثير لكلا الجانبين آنفي الذكر.
</p>

<h2>
	تجنب النكات والتورية والإشارات الثقافية
</h2>

<p>
	خلال عملي -يقول المؤلف- في إحدى شركات تطوير البرمجيات، صادفتني دالة باسم <code>()gooseDownload</code>، ولم يكن لدي أي تصور حول ما تعنيه، "تنزيل الإوزة!" إذ لم يكن <a href="http://xn--pgbe4eafg" rel="external nofollow">للمنتج</a> الذي نعمل عليه أي صلة بالطيور أو تحميل الطيور، ولدى إيجادي لشريك العمل الأقدم الذي كتب هذه الدالة، شرح لي بأن كلمة إوزة هنا يُقصد بها فعل وليس اسم، كما في الجملة goose the engine (بمعنى تهيئة محرك السيارة بإعطاءه دفعة كبيرة من الوقود مُصدرًا صوتًا يشبه صوت الإوزة).
</p>

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

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

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

<p>
	ولعل الإجراء الأفضل هو كتابة شيفرتك بطريقة تجعل أي متحدث غير ناطق بالإنجليزية يفهمها بسهولة، فلتكن طريقتك مهذبة ومباشرة وبعيدة عن روح الدعابة، فبلا شك قد ظن زميلي السابق في العمل أن طرفته حول الإوزة <code>()gooseDownload</code> مضحكة، ولكن في الواقع العدو الأكبر للنكات؛ شرحها.
</p>

<h2>
	لا تستخدم الأسماء المحجوزة
</h2>

<p>
	يجب عليك ألا تستخدم كلمات بايثون المحجوزة كأسماء لمتغيراتك، فمثلًا لو اخترت أحد الاسمين set أو list لأحد المتغيرات، فإنك قد استخدمت أسماءً محجوزة للدوال <code>()set</code> و<code>()list</code> في بايثون، ما قد يؤدي لظهور أخطاء لاحقًا في شيفرتك، ففي حين أن الدالة <code>()list</code> مسؤولة عن إنشاء القوائم، إلا أن استخدام اسمها المحجوز لغير هذا الغرض سيؤدي لظهور أخطاء، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_12" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">5</span><span class="pun">))</span><span class="pln">
</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="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">
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">range</span><span class="pun">(</span><span class="lit">5</span><span class="pun">))</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> </span><span class="str">'list'</span><span class="pln"> object </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> callable</span><span class="pun">```</span></pre>

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

<p>
	ولمعرفة فيما إذا كان اسمًا معينًا محجوزًا في بايثون أم لا، يكفي كتابته ضمن الصدفة التفاعلية أو أن نحاول استيراده، فلو حصلنا على أحد الخطأين NameError أو ModuleNotFoundError، فهذا يعني أن الاسم غير محجوز، فمثلًا الأسماء <code>open</code> و <code>test</code> محجوزة في بايثون، في حين <code>spam</code> و <code>eggs</code> ليست كذلك:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_14" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> open 
</span><span class="pun">&lt;</span><span class="pln">built</span><span class="pun">-</span><span class="kwd">in</span><span class="pln"> function open </span><span class="pun">&gt;</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> test
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> spam 
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">NameError</span><span class="pun">:</span><span class="pln"> name </span><span class="str">'spam'</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> defined
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> eggs 
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">ModuleNotFoundError</span><span class="pun">:</span><span class="pln"> </span><span class="typ">No</span><span class="pln"> module named </span><span class="str">'eggs'</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_18" style=""><span class="pln">all any data email file format hash id input list min max object open random set str sum test type</span></pre>

<p>
	فلا تستخدم هذه الأسماء للمعرفات بأنواعها.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_984_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="com"># Run this code with a file named pyperclip.py in the current folder.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> pyperclip </span><span class="com"># This imports your pyperclip.py, not the real one.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> pyperclip</span><span class="pun">.</span><span class="pln">copy</span><span class="pun">(</span><span class="str">'hello'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">AttributeError</span><span class="pun">:</span><span class="pln"> module </span><span class="str">'pyperclip'</span><span class="pln"> has no attribute </span><span class="str">'copy'</span></pre>

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

<h2>
	أسوأ أسماء المتغيرات على الإطلاق
</h2>

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

<p>
	فلطفًا لو احتجت لمتغير يعبّر عن التباين الاحصائي لبيانات درجة الحرارة، اختر الاسم <code>temperatureVariance</code> غير مباليًا بدلالات الثلاثي الشهير <code>tempVarData</code>.
</p>

<h2>
	الخاتمة
</h2>

<p>
	رغم كون اختيار الأسماء ليس ذو أثرٍ مباشر على <a href="https://academy.hsoub.com/programming/advanced/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%AE%D9%88%D8%A7%D8%B1%D8%B2%D9%85%D9%8A%D8%A7%D8%AA-r1282/" rel="">الخوارزميات</a> أو <a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">علوم الحاسوب</a>، إلا أنه أمر ذو دور حيوي في كتابة شيفرات عالية المقروئية. وبالنتيجة فإن اختيار الأسماء في شيفراتك هو أمر عائد إليك أولًا وأخيرًا، ومع ذلك كن متيقظًا للإرشادات العديدة حول هذا الأمر، إذا يوصي الدليل PEP 8 بالعديد من الاصطلاحات، كاستخدام الأحرف الصغيرة لأسماء الوحدات وطريقة <code>PascalCase</code> لأسماء الأصناف، كما أن الأسماء لا يجب أن تكون قصيرة أو طويلة جدًا، ومع ذلك يبقى الخطأ باتجاه الأسماء الأطول الأكثر تفصيلًا أفضل من استخدام أسماء قصيرة مبهمة.
</p>

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

<p>
	ورغم كون العديد من الاقتراحات الواردة في هذا المقال لا تتعدى كونها إرشادات، إلا أنه من الضروري تجنب استخدام الأسماء المحجوزة في <a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">بايثون ومكتباتها</a> المعيارية فاستخدامها قد يؤدي إلى ظهور أخطاء مبهمة في شيفرتك.
</p>

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

<p>
	ترجمة -وبتصرف- للفصل الرابع Code Formatting With Black من كتاب <a href="https://inventwithpython.com/beyond/chapter4.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigarti.
</p>

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

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">مدخل إلى لغة بايثون البرمجية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">أساسيات البرمجة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d8%a7%d9%84%d9%82%d9%88%d8%a7%d8%a6%d9%85-%d9%88%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-%d9%84%d8%ba%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r223/" rel="">التعامل مع القوائم والسلاسل النصية في لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%83%D8%AA%D8%B4%D8%A7%D9%81-%D8%AF%D9%84%D8%A7%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1944/" rel="">اكتشاف دلالات الأخطاء في شيفرات لغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1932</guid><pubDate>Sat, 18 Mar 2023 17:04:00 +0000</pubDate></item><item><title>&#x645;&#x62E;&#x62A;&#x635;&#x631; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629; &#x643;&#x627;&#x626;&#x646;&#x64A;&#x629; &#x627;&#x644;&#x62A;&#x648;&#x62C;&#x647; OOP &#x648;&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x647;&#x627; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D8%AE%D8%AA%D8%B5%D8%B1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-oop-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1926/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_03/------copy.png.343c9842f9a14258684a19c64849d66b.png" /></p>
<p>
	تُعَدّ البرمجة كائنية التوجه Object Oriented Programming -أو <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr> اختصارًا- نمطًا من أنماط البرمجة التي يُكتَب فيها البرنامج على صورة كائنات تحتوي على خاصيات ومهام -أي دوال- فيمكن مثلًا التفكير في السيارة على أساس كائن، إذ يكون لون السيارة ولون إطاراتها واسم الشركة المصنعة للسيارة خاصيات لها؛ أما مهمة حركة السيارة ومهمة إنقاص سرعة السيارة ومهمة زيادة سرعة السيارة، فهي دوال.
</p>

<p>
	كما يمكن التفكير أيضًا في الأقلام على أنها كائنات، يكون لون القلم واسم الشركة المصنعة له خاصيات؛ أما مهمة الكتابة فهي دالة، كذلك الأشخاص يمكن التفكير فيهم من وجهة نظر البرمجة الكائنية على أساس كائنات لها خاصيات و<a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">دوال</a>، إذ يكون اسم الشخص ولون بشرته وطول قامته خاصيات؛ أما مهمة المشي ومهمة الجري ومهمة الأكل فهي دوال، وكذلك مهمة النوم والجلوس والعمل، …إلخ فهي كلها دوال موجودة في الكائن.
</p>

<p>
	ليست كل <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> تدعم نمط <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-object-oriented-programming-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r309/" rel="">البرمجة كائنية التوجه</a>، إذ لا يتوفر هذا النمط في لغات مثل C، ومع ذلك فإنّ معظم لغات البرمجة المستخدَمة في هذا العقد تدعم البرمجة الكائنية، لكن العمل بذلك النمط ليس فرضًا أثناء عملك باللغات التي تدعم ذلك النمط مثل <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a>؛ إذ يوجد على سبيل المثال نمط آخر يدعى <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="">بالبرمجة الإجرائية Procedural Programing</a> والتي تنفِّذ البرنامج على صورة كتل من الشيفرات تمثِّل كل واحدة منها خطوةً من خطوات تنفيذ البرنامج، وهو ما استخدمناه بالفعل في الأمثلة.
</p>

<h2>
	مفهوم الصنف class والكائن object
</h2>

<p>
	إنّ أنواع البيانات البدائية الموجودة بصورة مدمجة في <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> هي نصوص وأعداد وقوائم، …إلخ، ولكن توفِّر البرمجة الكائنية بناء هيكل بيانات جديد خاص ببرنامجك، إذ تُنشأ الكائنات باستخدام صنف Class يحَّدد له مسبقًا الخاصيات والدوال، ويمكن التفكير مثلًا في الشخص أحمد على أنه كائن من الصنف إنسان، ولذلك يجب عند إنشاء أي كائن تحديد صنفه أولًا، كما يمكن عدّ ذلك الصنف نوعًا جديدًا من <a href="https://academy.hsoub.com/programming/general/%D9%87%D9%8A%D8%A7%D9%83%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-data-structures/" rel="">هياكل البيانات</a> المصمم من قبلك خصيصًا لبرنامجك، إذ تُخزَّن تلك الكائنات في النهاية في متغيرات، فيصبح بذلك نوع البيانات المخزن في المتغير هو صنف الكائن المخزن به.
</p>

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

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

<p>
	أما <a href="https://academy.hsoub.com/programming/java/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-objects-%D9%88%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-oop-r966" rel="">الكائنات Objects</a> أو تُدعى في بعض الأحيان نسخ Instances، فهي ليست أفكارًا أو مخططات، وإنما هي نسخة واقعية تحمل قيمًا في خاصياتها وتحمل دوالًا جاهزةً للاستخدام أخذتها نسخةً من الصنف، إذ يكون الكائن في حالة الصنف إنسان شخصًا حقيقيًا، يحمل قيمًا للخصائص التي يوفرها الصنف ويستطيع تنفيذ المهام، لذلك فإنه غالبًا عندما يُنشَأ كائن جديد، فإنه تُسنَد قيم لخاصياته الأساسية أثناء الإنشاء.
</p>

<h2>
	إنشاء صنف في بايثون
</h2>

<p>
	لإنشاء صنف جديد في بايثون، نستطيع استخدام الكلمة المفتاحية <code>class</code> متبوعةً باسم الصنف الذي من المفضَّل أن يبدأ بحرف كبير وليس شرطًا، ثم نبدأ كتلةً تحتوي على الخاصيات والدوال بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_6" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">pass</span></pre>

<p>
	عرَّفنا في المثال السابق صنفًا جديدًا باسم <code>Human</code>، ولا تحمل كتلته أيّ تعليمات حاليًا لذلك أضفنا الكلمة المفتاحية <code>pass</code> التي ذكرناها سابقًا بأنها تُستَعمل في حالة عدم وجود أيّ تعليمات في كتلة الشيفرة في <a href="https://academy.hsoub.com/programming/python/%d8%ad%d9%84%d9%82%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1-loops-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r291/" rel="">حلقات التكرار</a> وقواعد اتخاذ القرارات، وكذلك تستخدَم في أيّ كتلة شيفرة فارغة في أيّ قاعدة من قواعد اللغة.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_8" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">:</span><span class="pln">
    name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Adam'</span><span class="pln">
    age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</span></pre>

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

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_10" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">:</span><span class="pln">
    name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Adam'</span><span class="pln">
    age </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30</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>__init__</code> وإسنادها إلى خاصيات الكائن.
</p>

<h2>
	إنشاء الكائنات والتعامل معها
</h2>

<p>
	عند إنشاء كائن جديد من صنف تمرَّر معامِلات دالة الإنشاء <code>__init__</code>، إذ تُنفَّذ تلك الدالة كما ذكرنا عند إنشاء كائن جديد، كما يُسنَد الكائن الجديد في متغير، إذ أنه يُعَد نوعًا جديدًا من أنواع البيانات الذي عرَّفته أنت بنفسك عند إنشاء صنف جديد.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_12" style=""><span class="pln">ahmed </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">(</span><span class="str">'Ahmed'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</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">ahmed</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="pln"> </span><span class="pun">(</span><span class="pln">ahmed</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Ahmed</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">23</span></pre>

<p>
	حسنًا، ما حدث لا يزيد عن إنشاء متغير جديد يحمل الاسم <code>ahmed</code> من الصنف الذي كتبناه مسبقًا <code>Human</code>، والذي تحتاج دالة <code>__init__</code> فيه إلى معاملين هما الاسم والعمر واللذين مرِّرا بين الأقواس بعد اسم الصنف في المثال السابق.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_14" style=""><span class="pln">ahmed </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">(</span><span class="str">'Ahmed'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">)</span><span class="pln">
ahmed</span><span class="pun">.</span><span class="pln">age </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">ahmed</span><span class="pun">.</span><span class="pln">age</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">24</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_16" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">:</span><span class="pln">
    name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Adam'</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"> walk</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="pln"> </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 walking now ..'</span><span class="pun">)</span><span class="pln">
ahmed </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">(</span><span class="str">'Ahmed'</span><span class="pun">)</span><span class="pln">
ahmed</span><span class="pun">.</span><span class="pln">walk</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Ahmed</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> walking now </span><span class="pun">..</span></pre>

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

<h2>
	وراثة الأصناف وإنشاء أصناف فرعية
</h2>

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

<p>
	لنكتب مثالًا يحتوي على صنف <code>Programmer</code> الذي يرث الصنف <code>Human</code> مع إضافة خاصية اللغة <code>language</code> التي تحمل بدورها اسم <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%87%D9%85%D9%8A%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D8%A3%D9%87%D9%85-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1854/" rel="">لغة البرمجة</a> المتخصص فيها المبرمج، ثم سنعدِّل على دالة <code>__init__</code> لاستقبال قيمة للخاصية الجديدة وهي اللغة، وبذلك نكون قد أنشأنا صنفًا فرعيًا وراثيًا، وأضفنا خاصيةً له، ثم عدّلنا على دالة من دوال الصنف الأب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9718_18" style=""><span class="kwd">class</span><span class="pln"> </span><span class="typ">Human</span><span class="pun">:</span><span class="pln">
    name </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Adam'</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"> walk</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="pln"> </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 walking now ..'</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Programmer</span><span class="pun">(</span><span class="typ">Human</span><span class="pun">):</span><span class="pln">
    language </span><span class="pun">=</span><span class="pln"> </span><span class="str">'PHP'</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"> language</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="pun">;</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">language </span><span class="pun">=</span><span class="pln"> language
ahmed </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Programmer</span><span class="pun">(</span><span class="str">'Ahmed'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Python'</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">ahmed</span><span class="pun">.</span><span class="pln">language</span><span class="pun">);</span><span class="pln"> ahmed</span><span class="pun">.</span><span class="pln">walk</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Python</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Ahmed</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> walking now </span><span class="pun">..</span></pre>

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

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D9%87%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%AF%D9%85%D8%AC%D8%A9-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1907/" rel="">تعرف على أهم الدوال المدمجة في لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">دليلك إلى أنواع لغات البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%83%D8%A7%D8%A6%D9%86%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D9%88%D8%AC%D9%87-r1375/" rel="">مفهوم البرمجة كائنية التوجه</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1926</guid><pubDate>Sun, 12 Mar 2023 13:04:00 +0000</pubDate></item><item><title>&#x645;&#x646;&#x633;&#x642; &#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x627;&#x644;&#x635;&#x627;&#x631;&#x645; Black</title><link>https://academy.hsoub.com/programming/python/%D9%85%D9%86%D8%B3%D9%82-%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%B5%D8%A7%D8%B1%D9%85-black-r1923/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_03/----Black.png.8626578a063c88b74cbafc44efacc44b.png" /></p>
<p>
	تعرفنا في المقال السابق <a href="https://academy.hsoub.com/programming/python/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%B1-%D8%A7%D9%84%D9%85%D9%86%D8%B3%D9%82-black-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1919/" rel="">قواعد تنسيق الشيفرات ودور المنسق Black في بايثون</a> من هذه السلسلة على مفهوم تنسيق الشيفرة مبينين مجموعة من القواعد الواجب تطبيقها على الشيفرة المصدرية لمنحها مظهرًا معينًا. كما تعرفنا على منسِّق Black وهو أداة لتنسيق الشيفرات، إذ تنسق الشيفرة المصدرية تلقائيًا إلى شكلٍ مقروء ومتناغم، دون التأثير على سلوك البرنامج وأداءه؛ وسنتعرف في هذا المقال على آلية تثبيت واستخدام وتخصيص هذه الأداة.
</p>

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

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

<h2>
	تثبيت الأداة Black
</h2>

<p>
	نثبّت Black باستخدام أداة تثبيت الحزم <code>pip</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>. ولإجراء ذلك، في حال استخدامك <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">لنظام التشغيل</a> ويندوز، افتح نافذة <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر أوامر</a>، واكتب ضمنها ما يلي:
</p>

<pre class="ipsCode">C:\Users\Al\&gt;python -m pip install --user black
</pre>

<p>
	أما إذا كنت تستخدم أحد نظاميّ ماك أو <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس</a>، فافتح نافذة موجه الأوامر مُستخدمًا الأمر <code>python3</code> بدلًا من <code>python</code> كما هو الحال في ويندوز (الأمر الواجب مراعاته في كافّة تعليمات بايثون الواردة في هذا المقال):
</p>

<pre class="ipsCode">$ python3 -m pip install --user black
</pre>

<p>
	ويعد الخيار <code>m-</code> مسؤولًا عن إعلام بايثون لتشغيل الوحدة <code>pip</code> كتطبيق، مع ملاحظة أن بعض الوحدات في بايثون مضبوطة لتعمل كتطبيق افتراضيًا.
</p>

<p>
	ثمّ نتحقق من كون التثبيت قد تم بنجاح عبر تشغيل الأمر <code>python -m black</code>، وعندها يجب أن تظهر رسالة مفادها عدم وجود مسارات معطاة No paths given أو ما من شيء لفعله Nothing to do، بدلًا من ظهور رسالة تفيد بعدم وجود وحدة باسم black أو No module named black.
</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>
	تشغيل Black من سطر الأوامر
</h2>

<p>
	من الممكن تشغيل المنسّق Black لأي ملف بايثون باستخدام سطر الأوامر، كما أنّ محررات النصوص وبيئات التطوير المتكاملة قادرة على تشغيل Black في الخلفية أثناء عملك ضمنها. وللحصول على التعليمات المتعلقة بكيفية تشغيل Black مع محررات نصوص مثل <a href="https://academy.hsoub.com/devops/linux/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%87%D9%8A%D8%A6%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82-%D8%A7%D9%84%D9%85%D9%81%D9%83%D8%B1%D8%A9-jupyter-notebook-%D9%84%D9%84%D8%B9%D9%85%D9%84-%D9%85%D8%B9-%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-python-3-r388/" rel="">Jupyter</a> و Visual Studio Code و PyCharm وغيرها، من خلال زيارة الصفحة الرئيسية للمنسّق Black على <a href="https://github.com/psf/black" rel="external nofollow">psf/black</a>.
</p>

<p>
	فعلى سبيل المثال، لنفرض أننا نريد تنسيق ملف باسم yourScript.py تلقائيًا، لذا نفتح نافذة سطر الأوامر ونكتب فيها الأمر التالي ونشغله (مع مراعاة تبديل الأمر <code>python</code> إلى <code>python3</code> في حال استخدام أحد نظامي ماك أو لينكس):
</p>

<pre class="ipsCode">C:\Users\Al&gt;python -m black yourScript.py
</pre>

<p>
	وبمجرد تشغيل الأمر السابق، سينُسَق محتوى الملف yourScript.py وفقًا لقواعد تنسيق Black.
</p>

<p>
	وفي حال كون متغير البيئة <code>PATH</code> مضبوطًا ليشغّل Black مباشرةً، عندها يكفي كتابة الشيفرة التالية لتنسيق الملف yourScript.py تلقائيًا:
</p>

<pre class="ipsCode">C:\Users\Al&gt;black yourScript.py
</pre>

<p>
	كما من الممكن جعل Black يعمل على كل الملفات ذات اللاحقة <code>py.</code> ضمن مجلد معين، وذلك بتحديد هذا المجلد ضمن الأمر بدلًا من تحديد اسم ملف معيّن، فمثلًا الأمر التالي في ويندوز سينسّق كافة الملفات ذات اللاحقة <code>py.</code> الموجودة ضمن المجلد C:\yourPythonFiles بما يتضمّن الملفات الموجودة في المجلدات الفرعية منه:
</p>

<pre class="ipsCode">C:\Users\Al&gt;python -m black C:\yourPythonFiles
</pre>

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

<p>
	ورغم كون Black صارمًا في طريقة تنسيقه للشيفرات، إلا أن الفقرات الثلاث التالية تتضمّن بعض الخيارات الممكن تغيرها فيه، وللاطلاع على كامل الخيارات التي يوفرها Black، شغّل الأمر <code>python -m black --help</code> في نافذة سطر الأوامر.
</p>

<h3>
	تعديل إعدادات طول السطر في Black
</h3>

<p>
	إن الطول المعياري للسطر الواحد في بايثون هو 80 محرفًا، ويعود تاريخ الأسطر ذات الثمانين محرفًا إلى حقبة الحوسبة باستخدام <a href="https://ar.wikipedia.org/wiki/%D8%A8%D8%B7%D8%A7%D9%82%D8%A9_%D9%85%D8%AB%D9%82%D8%A8%D8%A9" rel="external nofollow">البطاقات المُثقبّة punch cards</a> في عشرينيات القرن الماضي، حين طرحت شركة IBM بطاقات مثقبة ذات 80 عمود و 12 سطر، ليستمر استخدام معيار الثمانين محرفًا في الطابعات والشاشات ونوافذ سطر الأوامر لعدّة عقود لاحقة.
</p>

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

<p>
	يستخدم Black افتراضيًا أسطرًا ذات 88 محرفًا، مضيفًا 10% زيادة عن القيمة المعيارية (80 محرف)، أما عن تفضيلي الشخصي فهو 120 محرف للسطر، ولجعل Black ينسق الشيفرة جاعلًا الحد الأعظمي لطول السطر 120 محرفًا على سبيل المثال، نستخدم خيار سطر الأوامر <code>l 120-</code>، إذ يبدو الأمر في نظام ويندوز كما يلي:
</p>

<pre class="ipsCode">C:\Users\Al&gt;python -m black -l 120 yourScript.py
</pre>

<p>
	وبغض النظر عما تختاره بخصوص الحد الأقصى لعدد المحارف بالسطر، الأهم أن يكون هذا الخيار موحدًا لكافّة ملفات <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> في المشروع الواحد.
</p>

<h3>
	تعطيل إعداد حصر السلاسل النصية بعلامات اقتباس مزدوجة
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2064_7" style=""><span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Al\'s cat, Zophie.'</span><span class="pln">
d </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Zophie said, "Meow"'</span><span class="pln">
e </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Zophie said, \"Meow\""</span><span class="pln">
f </span><span class="pun">=</span><span class="pln"> </span><span class="str">'''Hello'''</span></pre>

<p>
	وبتشغيل Black على الملف السابق، سينسقه ليصبح بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2064_9" style=""><span class="lit">1</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pln">
b </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pln">
c </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Al's cat, Zophie."</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Zophie said, "Meow"'</span><span class="pln">
e </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Zophie said, "Meow"'</span><span class="pln">
</span><span class="lit">3</span><span class="pln"> f </span><span class="pun">=</span><span class="pln"> </span><span class="str">"""Hello"""</span></pre>

<p>
	إن تفضيل Black لاستخدام علامات الاقتباس المزدوجة لإحاطة السلاسل النصية يجعل من الشيفرة المكتوبة <a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">بلغة بايثون</a> شبيهة بتلك المكتوبة <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">بلغات برمجة</a> أخرى، إذ تستخدم معظم اللغات الأخرى علامات الاقتباس المزدوجة لصياغة <a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d8%a7%d9%84%d9%82%d9%88%d8%a7%d8%a6%d9%85-%d9%88%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-%d9%84%d8%ba%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r223/" rel="">السلاسل النصية</a>.
</p>

<p>
	ومن الجدير بالملاحظة أنه وباستخدام Black على الشيفرة السابقة فأن السلاسل النصية في المتغيرات a و b و c قد حُصرت ضمن علامات اقتباس مزدوجة، في حين بقيت علامة الاقتباس المفردة للسلسلة في المتغير d لتجنب الخلط مع العلامة المزدوجة الموجودة أصلًا ضمن السلسلة في السطر 2، كما نلاحظ أن Black قد استبدل علامات الاقتباس المفردة الثلاثية في السطر 3 الدالة على كون هذه السلسة متعددة الأسطر multiline، بعلامة اقتباس مزدوجة ثلاثية.
</p>

<p>
	وفي حال رغبتك بترك علامات الاقتباس على حالها دون تغييرها من قبل Black، فاستخدم ضمن استدعاءه الخيار <code>S-</code> في نافذة سطر الأوامر (مع ملاحظة أنّ حرف S كبير هنا)، فعلى سبيل المثال، في حال تشغيل Black على الملف yourScript.py الأصلي في نظام ويندوز، سيظهر الخرج التالي:
</p>

<pre class="ipsCode">C:\Users\Al&gt;python –m black -S yourScript.py
All done!
1 file left unchanged.
</pre>

<p>
	كما من الممكن استخدام كلا خياري الحد الأقصى لمحارف السطر <code>l-</code> وخيار عدم تغيير علامات الاقتباس <code>S-</code> في سطرٍ واحد، بالشكل:
</p>

<pre class="ipsCode">C:\Users\Al&gt;python –m black –l 120 -S yourScript.py
</pre>

<h3>
	استعراض التغييرات التي أجراها Black
</h3>

<p>
	رغم كون تعديلات Black تنسيقية بحتة لا تشتمل مثلًا على تغيير أسماء المتغيرات أو أي تغيير في سلوك الشيفرة البرمجي، إلا أنك قد لا تفضل التغييرات التنسيقية التي أجراها، وفي حال رغبتك بالرجوع إلى تنسيقات شيفرتك الأصلية، فبإمكانك إما استخدام <a href="https://academy.hsoub.com/programming/workflow/git/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%85%D8%B9-%D9%86%D8%B8%D8%A7%D9%85-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D8%A5%D8%B5%D8%AF%D8%A7%D8%B1%D8%A7%D8%AA-%D8%AC%D9%8A%D8%AA-git-r1593/" rel="">نظام إدارة الإصدارات</a> أو الرجوع إلى نسخك الاحتياطية الخاصة.
</p>

<p>
	ولعل الخيار البديل الأفضل هو معاينة التغييرات التي سيجريها Black قبل تطبيقها الفعلي من خلال تشغيل Black مع استخدام خيار سطر الأوامر <code>diff--</code>، والذي يبدو في نظام ويندوز بالشكل:
</p>

<pre class="ipsCode">C:\Users\Al&gt;python -m black --diff yourScript.py
</pre>

<p>
	سيعطي هذا الأمر خرجًا يمثّل التغييرات التي سيجريها Black في صياغة لبيان الاختلافات شبيهة بتلك شائعة الاستخدام في برمجيات إدارة الشيفرات، إلا أنها مقروءة وواضحة للبشر. فمثلًا لو تضمّن الملف yourScript.py السطر البرمجي<code>[weights=[42.0,3.1415,2.718</code>، وبتشغيل الخيار <code>diff--</code> مع Black، سيكون الخرج بالشكل:
</p>

<pre class="ipsCode">C:\Users\Al\&gt;python -m black --diff yourScript.py
--- yourScript.py       2020-12-07 02:04:23.141417 +0000
+++ yourScript.py       2020-12-07 02:08:13.893578 +0000
@@ -1 +1,2 @@
-weights=[42.0,3.1415,2.718]
+weights = [42.0, 3.1415, 2.718]
</pre>

<p>
	تشير علامة الناقص إلى أن Black سيحذف السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2762_7" style=""><span class="pln">weights</span><span class="pun">=[</span><span class="lit">42.0</span><span class="pun">,</span><span class="lit">3.1415</span><span class="pun">,</span><span class="lit">2.718</span><span class="pun">]</span></pre>

<p>
	ليستبدله إلى لسطر المشار إليه بعلامة الزائد، أي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2762_9" style=""><span class="pln">weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.718</span><span class="pun">]</span></pre>

<p>
	وتذكّر دائمًا أنه ما من طريقة للرجوع عن التغييرات التي يجريها Black بعد تنفيذها، وما من سبيل سوى أن تنشئ نسخًا احتياطية من شيفرتك أو أن تستخدم إحدى برمجيات إدارة الشيفرات مثل <a href="https://academy.hsoub.com/programming/workflow/git/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A5%D8%AF%D8%A7%D8%B1%D8%A9-%D8%A7%D9%84%D9%86%D8%B3%D8%AE-vcs-r248/" rel="">Git</a> وذلك قبل تطبيق تغييرات Black عليها.
</p>

<h2>
	تعطيل عمل Black على أجزاء محددة من الشيفرة
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2064_12" style=""><span class="com"># Set up constants for different time amounts:</span><span class="pln">
SECONDS_PER_MINUTE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln">
SECONDS_PER_HOUR   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_MINUTE
SECONDS_PER_DAY    </span><span class="pun">=</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_HOUR
SECONDS_PER_WEEK   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">  </span><span class="pun">*</span><span class="pln"> SECONDS_PER_DAY</span></pre>

<p>
	ومع استخدام Black على هذا الجزء، فإنه سيحذف الفراغات الإضافية قبل معامل الإسناد <code>=</code>، جاعلًا مقروئية التعليمات أقل من وجهة نظري، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2064_14" style=""><span class="com"># Set up constants for different time amounts:</span><span class="pln">
SECONDS_PER_MINUTE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln">
SECONDS_PER_HOUR </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_MINUTE
SECONDS_PER_DAY </span><span class="pun">=</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_HOUR
SECONDS_PER_WEEK </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_DAY</span></pre>

<p>
	ولإعلام Black برغبتنا بعدم إجراء أي تغييرات على مقطع برمجي معيّن، يكفي حصره ما بين التعليقين <code>fmt: off #</code> و <code>fmt: on #</code>، ليتابع بعده إجراء التنسيقات بشكل طبيعي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_2064_16" style=""><span class="com"># Set up constants for different time amounts:</span><span class="pln">
</span><span class="com"># fmt: off</span><span class="pln">
SECONDS_PER_MINUTE </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln">
SECONDS_PER_HOUR   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_MINUTE
SECONDS_PER_DAY    </span><span class="pun">=</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> SECONDS_PER_HOUR
SECONDS_PER_WEEK   </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">  </span><span class="pun">*</span><span class="pln"> SECONDS_PER_DAY
</span><span class="com"># fmt: on</span></pre>

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

<h2>
	الخاتمة
</h2>

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

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

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

<p>
	ترجمة -وبتصرف- للجزء الثاني من الفصل الثالث Code Formatting With Black من كتاب <a href="https://inventwithpython.com/beyond/chapter3.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigarti.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%B1-%D8%A7%D9%84%D9%85%D9%86%D8%B3%D9%82-black-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1919/" rel="">قواعد تنسيق الشيفرات ودور المنسق Black في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/%D8%A8%D9%8A%D8%A6%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-ide-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1772/" rel="">بيئات التطوير IDE المستخدمة في تطوير تطبيقات بايثون</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%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>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D9%86%D8%B5%D9%88%D8%B5-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r409/" rel="">كيفية تنسيق النصوص في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1923</guid><pubDate>Sat, 11 Mar 2023 13:07:00 +0000</pubDate></item><item><title>&#x642;&#x648;&#x627;&#x639;&#x62F; &#x62A;&#x646;&#x633;&#x64A;&#x642; &#x627;&#x644;&#x634;&#x64A;&#x641;&#x631;&#x627;&#x62A; &#x648;&#x62F;&#x648;&#x631; &#x627;&#x644;&#x645;&#x646;&#x633;&#x642; Black &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%82%D9%88%D8%A7%D8%B9%D8%AF-%D8%AA%D9%86%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%AF%D9%88%D8%B1-%D8%A7%D9%84%D9%85%D9%86%D8%B3%D9%82-black-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1919/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_03/1765938051_-------Black.png.f0db632599fb3776e1f6bb48af0f279e.png" /></p>
<p>
	يعرَّف تنسيق الشيفرة بأنه تطبيق مجموعة من القواعد على الشيفرة المصدرية لمنحها مظهرًا معينًا. ورغم عدم أهمية تنسيق الشيفرة بالنسبة للحاسوب المُحلِّل للبرامج، إلا أنه أمر بالغ الأهمية من ناحية سهولة قراءة الشيفرة، وهذا ما يسهل مراجعتها. فإذا كانت الشيفرة صعبة الفهم على البشر (عليك أو على أحد زملائك) فما بالك بإصلاح الأخطاء فيها أو إضافة ميزات جديدة إليها، سيكون الأمر أصعب بكل تأكيد، فتنسيق الشيفرة ليس بالمسألة الجمالية فحسب، ولعل أحد أهم أسباب شعبية لغة بايثون هي سهولة قراءتها.
</p>

<p>
	سنتعرف في هذا المقال على منسِّق الشيفرات Black في <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> وهو أداة لتنسيق الشيفرات، إذ تنسق الشيفرة المصدرية تلقائيًا إلى شكلٍ مقروء ومتناغم، دون التأثير على سلوك البرنامج وأداءه، وتكمن أهمية Black في كونها تجنب المستخدم التنسيق المُمل للشيفرات في محرر النصوص أو بيئة التطوير المتكاملة IDE، إذ سنتعرف على آلية اختيار Black لنمط الشيفرة المحدد.
</p>

<h2>
	فوضى شيفراتك ستفقدك أصدقائك وتنفر زملائك في العمل
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_7" style=""><span class="pln">spam </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'dog'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cat'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'moose'</span><span class="pun">]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_9" style=""><span class="pln">spam</span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln"> </span><span class="str">'dog'</span><span class="pln">  </span><span class="pun">,</span><span class="str">'cat'</span><span class="pun">,</span><span class="str">"moose"</span><span class="pun">]</span></pre>

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

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

<p>
	فالبرمجة بطبيعتها في الغالب نشاط جماعي مشترك، حتى لو كانت انطلاقتك فيها فردية. فلو فرضنا وجود عدد من المبرمجين يعملون معًا على شيفرة مصدرية واحدة، فكيف ستكون النتيجة النهائية في حال كتب كل منهم شيفراته بطريقته الخاصّة؟ فوضى وعدم تناسق بالطبع، حتى ولو عملت الشيفرة بالنتيجة دون <a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r1342/" rel="">أخطاء برمجية</a>. والأسوأ مثلًا أن يعمل كل منهم على تعديل تنسيق شيفرة الآخر إلى الشكل المفهوم بالنسبة له، الأمر الذي سيضيع الوقت مؤديًا إلى جدالات عديدة.
</p>

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

<h2>
	الدليل الإرشادي PEP 8 لكيفية تنسيق الشيفرات
</h2>

<p>
	لعلّ اتباع دليل إرشادي يمثّل طريقة سهلة لكتابة شيفرات بمقروئية عالية، والدليل الإرشادي بالتعريف هو مستند يتضمن مجموعة من قواعد التنسيق التي يجب اتباعها أثناء إنشاء أي مشروع برمجي، وما PEP8 الذي هو الإصدار الثامن من مستند تحسين مقروئية <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>، سوى دليل إرشادي مكتوب من قبل فريق تطوير بايثون، إلّا أنّ بعض الشركات البرمجية أنشأت دليلها الإرشادي الخاص.
</p>

<p>
	يمكنك الاطلاع على الدليل PEP 8 بزيارة <a href="https://www.python.org/dev/peps/pep-0008/" rel="external nofollow">python.org</a>. ويرى العديد من مبرمجي بايثون الدليل PEP 8 كمجموعة من القواعد المبالغ بصرامتها، في حين يرى منشؤوه العكس. إذ يذكّر القسم "رفض التغيير هو سمة العقول غير الناضجة" من الدليل القراء بأن الدافع الرئيسي لاتباع دليل إرشادي موحّد هو زيادة مقروئية الشيفرات في المشاريع من خلال الحفاظ على تنسيق معيّن بدلًا من التنسيقات الفردية المختلفة.
</p>

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

<p>
	ونظرًا لاستخدامنا منسّق Black، فإن شيفراتنا ستتبع في تنسيقها دليل Black الإرشادي المتوافق تمامًا مع قواعد PEP 8. ولابد من تعلمك لهذه الأصول وكيفية تطبيقها يدويًا، فقد لا يكون منسّق Black متوفر دائمًا بسهولة، ناهيك عن كون القواعد التنسيقية التي ستتعلمها في هذا المقال عامّة وتتطبق على <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> الأخرى، والتي قد لا تتضمّن منسقًا تلقائيًا.
</p>

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

<h3>
	استعمال مفتاح المسافة الفارغة Space لإنشاء مسافة بادئة
</h3>

<p>
	تعرّف المسافة البادئة بأنها ذلك الفراغ المتموضع في بداية أحد أسطر الشيفرة، ولإضافتها من الممكن استخدام أحد مفتاحي إضافة المحارف الفارغة في لوحة المفاتيح، وهما مفتاح المسافة الفارغة Space ومفتاح الجدولة Tab. ورغم كون أي منهما يؤدّي هذا الغرض، إلا أن استخدام مفتاح المسافة الفارغة يعد الإجراء الأفضل.
</p>

<p>
	والسبب في ذلك يعود لكون كل من المفتاحين يعمل بطريقة مختلفة، ففي حين يُصيَّر مفتاح Space على الشاشة بهيئة قيمة محرفية تساوي فراغًا واحدًا بالشكل ‘ ‘، إلا أن مفتاح Tab يُصيّر على هيئة قيمة محرفية تقابل محرف الهروب <code>t\</code> ما يجعل حجم الفراغات غامضًا، فعلى الغالب يعرض هذا المفتاح حجمًا متغيرًا للفراغات مُحددًا علامة جدولة ليبدأ النص التالي بعدها، إذا تتموضع علامة الجدولة عند كل ثمان فراغات وفقًا لعرض المستند، والمثال التالي يبيّن الفرق من خلال شيفرة مكتوبة في الصَدَفَة التفاعلية، إذ استخدمنا بدايةً مفتاح Space للفصل بين الكلمات ومن ثم مفتاح Tab:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_15" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello there, friend!\nHow are you?'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Hello</span><span class="pln"> there</span><span class="pun">,</span><span class="pln"> friend</span><span class="pun">!</span><span class="pln">
</span><span class="typ">How</span><span class="pln"> are you</span><span class="pun">?</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello\tthere,\tfriend!\nHow\tare\tyou?'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Hello</span><span class="pln">   there</span><span class="pun">,</span><span class="pln">  friend</span><span class="pun">!</span><span class="pln">
</span><span class="typ">How</span><span class="pln">     are     you</span><span class="pun">?</span></pre>

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

<p>
	كما أنه من غير الممكن استخدام كلا المفتاحين في إنشاء المسافات البادئة في نفس الكتلة من الشيفرة، ولطالما كان استخدامهما معًا في إنشاء المسافات البادئة مصدرًا لأحد الأخطاء المزعجة في إصدارات بايثون القديمة، لدرجة أن <a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%af%d9%84%d9%8a%d9%84-%d8%a7%d9%84%d8%b3%d8%b1%d9%8a%d8%b9-%d8%a5%d9%84%d9%89-%d9%84%d8%ba%d8%a9-%d8%a7%d9%84%d8%a8%d8%b1%d9%85%d8%ac%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-python-3-r535/" rel="">الإصدار الثالث من بايثون</a> لن يشغّل شيفرة بمسافات بادئة مبنية بهذه الطريقة، مُظهرًا رسالة الاستثناء الآتي:
</p>

<pre class="ipsCode" id="ips_uid_8553_6"> TabError: inconsistent use of tabs and spaces in indentation </pre>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_18" style=""><span class="kwd">def</span><span class="pln"> getCatAmount</span><span class="pun">():</span><span class="pln">
</span><span class="pun">....</span><span class="pln">numCats </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">(</span><span class="str">'How many cats do you have?'</span><span class="pun">)</span><span class="pln">

</span><span class="pun">....</span><span class="kwd">if</span><span class="pln"> int</span><span class="pun">(</span><span class="pln">numCats</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">6</span><span class="pun">:</span><span class="pln">

</span><span class="pun">........</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'You should get more cats.'</span><span class="pun">)</span></pre>

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

<h3>
	التباعد ضمن السطر الواحد
</h3>

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

<h4>
	استخدم فراغ واحد ما بين العمليات والمعرفات
</h4>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_20" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> blanks </span><span class="pun">=</span><span class="pln"> blanks</span><span class="pun">[:</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> secretWord</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> blanks</span><span class="pun">[</span><span class="pln">i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">:]</span></pre>

<p>
	وفي حال حذف تلك الفراغات، فسيبدو بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_22" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  blanks</span><span class="pun">=</span><span class="pln">blanks</span><span class="pun">[:</span><span class="pln">i</span><span class="pun">]+</span><span class="pln">secretWord</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]+</span><span class="pln">blanks</span><span class="pun">[</span><span class="pln">i</span><span class="pun">+</span><span class="lit">1</span><span class="pun">:]</span></pre>

<p>
	تستخدم هذه الشيفرة في كلتا الحالتين معامل الجمع <code>+</code> لجمع ثلاثة قيم، ولكن في حالة عدم استخدام فراغات، قد يبدو معامل الجمع الموجود ضمن المتغير <code>[:blanks[i+1</code> على أنّه عملية جمع رابعة، إلا أن استخدام الفراغات سيوضح أن معامل الجمع هذا جزء من قيمة الشريحة slice (بنية في بايثون تمكننا من الوصول إلى أجزاء من التسلسلات مثل السلاسل النصية والجداول والقوائم) الموجودة بين القوسين.
</p>

<h4>
	لا تضع مسافات قبل الفواصل وضع مسافة واحدة بعدها
</h4>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_24" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">,</span><span class="pln"> bacon</span><span class="pun">,</span><span class="pln"> ham</span><span class="pun">):</span><span class="pln">
YES</span><span class="pun">:</span><span class="pln">     weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.718</span><span class="pun">]</span></pre>

<p>
	وإلا سينتهي الأمر بشيفرة مجمّعة ذات مقروئية منخفضة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_26" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">,</span><span class="pln">bacon</span><span class="pun">,</span><span class="pln">ham</span><span class="pun">):</span><span class="pln">
NO</span><span class="pun">:</span><span class="pln">      weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42.0</span><span class="pun">,</span><span class="lit">3.1415</span><span class="pun">,</span><span class="lit">2.718</span><span class="pun">]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_29" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln">eggs </span><span class="pun">,</span><span class="pln"> bacon </span><span class="pun">,</span><span class="pln"> ham</span><span class="pun">):</span><span class="pln">
NO</span><span class="pun">:</span><span class="pln">      weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42.0</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.718</span><span class="pun">]</span></pre>

<p>
	يضيف منسّق Black تلقائيًا مسافة بعد كل فاصلة، كما يحذف أي فراغات مُضافة قبلها.
</p>

<h4>
	لا تستخدم أي فراغات قبل أو بعد النقاط
</h4>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_31" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="str">'Hello, world'</span><span class="pun">.</span><span class="pln">upper</span><span class="pun">()</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_33" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="str">'Hello, world'</span><span class="pln"> </span><span class="pun">.</span><span class="pln"> upper</span><span class="pun">()</span></pre>

<p>
	يحذف منسق Black تلقائيًا أي مسافات قبل أو بعد النقاط.
</p>

<h4>
	لا تضع مسافات بعد أسماء الدوال أو التوابع أو حاويات البيانات
</h4>

<p>
	من السهل تمييز أسماء <a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">الدوال</a> والتوابع كونها تُتبع دومًا بقوسين، لذا يجب عدم وضع مسافة بين اسم الدالة أو التابع وقوس البداية، فعادةً ما يتم استدعاء الدوال بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_36" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span></pre>

<p>
	ومع استخدام مسافة قبل قوس البداية، قد يبدو استدعاء الدالة الواحدة على أنه أمران مستقلان، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_38" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span></pre>

<p>
	لذا يحذف منسّق Black أي مسافات بين اسم الدالة أو التابع وقوس بدايتها.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_40" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> spam</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
YES</span><span class="pun">:</span><span class="pln"> spam</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
YES</span><span class="pun">:</span><span class="pln"> pet</span><span class="pun">[</span><span class="str">'name'</span><span class="pun">]</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_42" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  spam </span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln">
NO</span><span class="pun">:</span><span class="pln">  spam    </span><span class="pun">[</span><span class="lit">0</span><span class="pun">:</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
NO</span><span class="pun">:</span><span class="pln">  pet </span><span class="pun">[</span><span class="str">'name'</span><span class="pun">]</span></pre>

<p>
	لذا يحذف منسّق Black أي مسافات كائنة بين اسم المتغير وقوس البداية المعقوف.
</p>

<h4>
	لا تضع مسافات بعد أقواس البداية أو قبل أقواس النهاية بأنواعها
</h4>

<p>
	يجب عدم استخدام مسافات في فصل الأقواس بأنواعها الهلالية () والمعقوصة {} والمعقوفة [] عن محتوياتها، فيجب أن تبدأ المعاملات في عبارة تصريح عن دالة ما أو القيم ضمن قائمة بعد قوس بدايتها وتنتهي قبل قوس نهايتها مباشرةً.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_44" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln">eggs</span><span class="pun">,</span><span class="pln"> bacon</span><span class="pun">,</span><span class="pln"> ham</span><span class="pun">):</span><span class="pln">
YES</span><span class="pun">:</span><span class="pln">     weights </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">42.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.718</span><span class="pun">]</span></pre>

<p>
	إذ يجب عدم إضافة أي مسافات بعد قوس البداية أو قبل قوس النهاية، سواء كانت هذه الأقواس هلالية أم معقوفة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_46" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln"> eggs</span><span class="pun">,</span><span class="pln"> bacon</span><span class="pun">,</span><span class="pln"> ham </span><span class="pun">):</span><span class="pln">
NO</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"> </span><span class="lit">42.0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.1415</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.718</span><span class="pln"> </span><span class="pun">]</span></pre>

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

<h4>
	ضع فراغين قبل تعليقات نهاية السطر
</h4>

<p>
	إن أردت إضافة تعليق إلى نهاية أحد أسطر الشيفرة، فيجب إضافة مسافتين بعد نهاية السطر البرمجي وقبل المحرف <code>#</code> الدال على بداية التعليق، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_48" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span><span class="pln">  </span><span class="com"># Display a greeting.</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_50" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)</span><span class="pln"> </span><span class="com"># Display a greeting.</span><span class="pln">
NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, world!'</span><span class="pun">)#</span><span class="pln"> </span><span class="typ">Display</span><span class="pln"> a greeting</span><span class="pun">.</span></pre>

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

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

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_52" style=""><span class="pln">NO</span><span class="pun">:</span><span class="pln">  </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ExampleClass</span><span class="pun">:</span><span class="pln">
         </span><span class="kwd">def</span><span class="pln"> exampleMethod1</span><span class="pun">():</span><span class="pln">
             </span><span class="kwd">pass</span><span class="pln">
         </span><span class="kwd">def</span><span class="pln"> exampleMethod2</span><span class="pun">():</span><span class="pln">
             </span><span class="kwd">pass</span><span class="pln">
     </span><span class="kwd">def</span><span class="pln"> exampleFunction</span><span class="pun">():</span><span class="pln">
         </span><span class="kwd">pass</span></pre>

<p>
	لتصبح تلقائيًا بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_54" style=""><span class="pln">YES</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ExampleClass</span><span class="pun">:</span><span class="pln">
         </span><span class="kwd">def</span><span class="pln"> exampleMethod1</span><span class="pun">():</span><span class="pln">
             </span><span class="kwd">pass</span><span class="pln">

         </span><span class="kwd">def</span><span class="pln"> exampleMethod2</span><span class="pun">():</span><span class="pln">
             </span><span class="kwd">pass</span><span class="pln">


     </span><span class="kwd">def</span><span class="pln"> exampleFunction</span><span class="pun">():</span><span class="pln">
         </span><span class="kwd">pass</span></pre>

<h3>
	مثال على التباعد الرأسي
</h3>

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

<p>
	لنأخذ على سبيل المثال صنف التحقق من البريد الإلكتروني <code>EmailValidator</code> من الملف validators.py في إطار عمل تطبيق ويب محرك القوالب <a href="https://academy.hsoub.com/programming/python/django/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-django%C2%A0-r353/" rel="">جانغو</a>، مع ملاحظة أنه من غير الضروري الآن فهم آلية عمل هذه الشيفرة، بل سنركّز على كيفية الفصل ما بين توابع الاستدعاء <code>()__call__</code> باستخدام الأسطر الفارغة إلى أربعة مجموعات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_57" style=""><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
    </span><span class="kwd">def</span><span class="pln"> __call__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> value</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"> </span><span class="kwd">not</span><span class="pln"> value </span><span class="kwd">or</span><span class="pln"> </span><span class="str">'@'</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> value</span><span class="pun">:</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">ValidationError</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">message</span><span class="pun">,</span><span class="pln"> code</span><span class="pun">=</span><span class="pln">self</span><span class="pun">.</span><span class="pln">code</span><span class="pun">)</span><span class="pln">

    </span><span class="lit">2</span><span class="pln"> user_part</span><span class="pun">,</span><span class="pln"> domain_part </span><span class="pun">=</span><span class="pln"> value</span><span class="pun">.</span><span class="pln">rsplit</span><span class="pun">(</span><span class="str">'@'</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">3</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">user_regex</span><span class="pun">.</span><span class="pln">match</span><span class="pun">(</span><span class="pln">user_part</span><span class="pun">):</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">ValidationError</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">message</span><span class="pun">,</span><span class="pln"> code</span><span class="pun">=</span><span class="pln">self</span><span class="pun">.</span><span class="pln">code</span><span class="pun">)</span><span class="pln">

    </span><span class="lit">4</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">domain_part </span><span class="kwd">not</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">domain_whitelist </span><span class="kwd">and</span><span class="pln">
                </span><span class="kwd">not</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">validate_domain_part</span><span class="pun">(</span><span class="pln">domain_part</span><span class="pun">)):</span><span class="pln">
            </span><span class="com"># Try for possible IDN domain-part</span><span class="pln">
            </span><span class="kwd">try</span><span class="pun">:</span><span class="pln">
                domain_part </span><span class="pun">=</span><span class="pln"> punycode</span><span class="pun">(</span><span class="pln">domain_part</span><span class="pun">)</span><span class="pln">
            </span><span class="kwd">except</span><span class="pln"> </span><span class="typ">UnicodeError</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">pass</span><span class="pln">
            </span><span class="kwd">else</span><span class="pun">:</span><span class="pln">
                </span><span class="kwd">if</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">validate_domain_part</span><span class="pun">(</span><span class="pln">domain_part</span><span class="pun">):</span><span class="pln">
                    </span><span class="kwd">return</span><span class="pln">
            </span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">ValidationError</span><span class="pun">(</span><span class="pln">self</span><span class="pun">.</span><span class="pln">message</span><span class="pun">,</span><span class="pln"> code</span><span class="pun">=</span><span class="pln">self</span><span class="pun">.</span><span class="pln">code</span><span class="pun">)</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span></pre>

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

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

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

<h4>
	أفضل الممارسات حيال التباعد الرأسي
</h4>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_59" style=""><span class="kwd">print</span><span class="pun">(</span><span class="str">'What is your name?'</span><span class="pun">)</span><span class="pln">
name </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_61" style=""><span class="kwd">print</span><span class="pun">(</span><span class="str">'What is your name?'</span><span class="pun">);</span><span class="pln"> name </span><span class="pun">=</span><span class="pln"> input</span><span class="pun">()</span></pre>

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

<p>
	أمّا بالنسبة للعبارات البرمجية التي تنتهي بنقطتين رأسيتين، كعبارات <code>if</code> و <code>for</code> و <code>while</code> و <code>def</code> أو جمل بناء الأصناف، فمن الممكن كتابتها على سطر واحد، فمثلًا من الممكن كتابة استدعاء الدالة <code>()print</code> في الشيفرة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_63" style=""><span class="kwd">if</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Alice'</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, Alice!'</span><span class="pun">)</span></pre>

<p>
	على نفس السطر مع العبارة الشرطية <code>if</code>، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_65" style=""><span class="kwd">if</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">'Alice'</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello, Alice!'</span><span class="pun">)</span></pre>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_67" style=""><span class="kwd">import</span><span class="pln"> math</span><span class="pun">,</span><span class="pln"> os</span><span class="pun">,</span><span class="pln"> sys</span></pre>

<p>
	ومع ذلك، فإن الدليل PEP 8 يوصي بفصل هذه العبارات، لتتم عملية استيراد كل وحدة في سطر مستقل، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6540_69" style=""><span class="kwd">import</span><span class="pln"> math
</span><span class="kwd">import</span><span class="pln"> os
</span><span class="kwd">import</span><span class="pln"> sys</span></pre>

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

<p>
	كما ينصح الدليل PEP 8 بتجميع عبارات الاستيراد ضمن ثلاث مجموعات، كما يلي:
</p>

<ul>
	<li>
		الوحدات من <a href="https://academy.hsoub.com/programming/python/%D8%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">مكتبة بايثون</a> المعيارية، مثل الوحدة <code>math</code> و <code>os</code> و <code>sys</code>.
	</li>
	<li>
		الوحدات الخارجية، مثل <code>Selenium</code> و <code>Requests</code> و <code>Django</code>.
	</li>
	<li>
		الوحدات الداخلية التي تمثّل جزءًا من البرنامج.
	</li>
</ul>

<p>
	وإجمالًا لا يغير منسق Black من تنسيق الاستيرادات في الشيفرة، نظرًا لكون الإرشادات المتعلقة بالاستيرادات اختيارية.
</p>

<h2>
	الخاتمة
</h2>

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

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

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

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

<p>
	لقد استعرضنا في هذا المقال التنسيقات الأساسية التي يجريها Black، ويمكنك الاطلاع على دليل Black الإرشادي لكامل التنسيقات بزيارة <a href="https://black.readthedocs.io/en/stable/the_black_code_style/index.html" rel="external nofollow">black.readthedocs.io</a>.
</p>

<p>
	ترجمة -وبتصرف- للجزء الأول من الفصل الثالث Code Formatting With Black من كتاب <a href="https://inventwithpython.com/beyond/chapter3.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigarti.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AA%D8%BA%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D9%8A%D8%A6%D8%A9-path-%D9%88%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D9%86%D8%A7%D9%81%D8%B0%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1885/" rel="">متغير البيئة PATH والعمل دون نافذة سطر الأوامر في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">أساسيات البرمجة بلغة بايثون</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%D8%B3%D9%8A%D9%82-%D8%A7%D9%84%D9%86%D8%B5%D9%88%D8%B5-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r409/" 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-%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>
	</li>
</ul>
]]></description><guid isPermaLink="false">1919</guid><pubDate>Sun, 05 Mar 2023 16:08:00 +0000</pubDate></item><item><title>&#x62A;&#x639;&#x631;&#x641; &#x639;&#x644;&#x649; &#x623;&#x647;&#x645; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; &#x627;&#x644;&#x645;&#x62F;&#x645;&#x62C;&#x629; &#x641;&#x64A; &#x644;&#x63A;&#x629; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A3%D9%87%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D9%85%D8%AF%D9%85%D8%AC%D8%A9-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1907/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_02/1633506154_-------.png.14727ba8f84b37aaf2c6aeb7629629e2.png" /></p>
<p>
	تعرفنا في <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1906/" rel="">المقال السابق</a> على مفهوم الدوال وكيف يمكن للمبرمج تعريف دوال مخصصة ولكن لا يحتاج المبرمج إلى تعريف كل الدوال بنفسه من الصفر بل توجد الكثير من الدوال المدمجة بالفعل في اللغة افتراضيًا تسمى Built-in Functions أي دوال مدمَجة، وأفضل الأمثلة عليها هي دالة الطباعة <code>print</code> الموجودة افتراضيًا في بايثون، وسنذكر في هذا الفصل أهم هذه الدوال وأمثلة على استخدامها.
</p>

<h2>
	دوال التعامل مع الأوقات والأزمنة في بايثون
</h2>

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

<p>
	توجد في <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> بعض <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-modules-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-packages-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r329/" rel="">الوحدات Modules</a> التي تُستخدَم عند التعامل مع الأوقات والتواريخ، سنبدأ أولًا بوحدة الوقت التي تُدعى <code>time</code> وهي تحتوي على الكثير من الدوال المفيدة للتعامل مع الوقت وسنذكر بعضًا منها.
</p>

<p>
	<strong>ملاحظة</strong>: يُحسَب في <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> وفي كثير من <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> وقت الثانية الحالية حسب فترة بُعدها بالثواني عن الساعة 12 صباحًا يوم 1 من شهر 1 عام 1970م، وهو نظام متعارف عليه، إذ يُعَدّ ذلك التاريخ نقطة انطلاق ما يُدعى بوقت يونكس Unix أو Unix Epoch.
</p>

<h3>
	دالة time
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_14" style=""><span class="kwd">import</span><span class="pln"> time

</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">time</span><span class="pun">())</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1592952455.39395</span></pre>

<p>
	ستلاحظ في كل مرة يُنفَّذ المثال أعلاه أن العدد يزيد بفرق عدد الثواني بين التنفيذ الثاني والتنفيذ الأول، والجدير بالذكر أنّ الثانية في تلك القاعدة يُطلق عليها بالإنجليزية لقب Tick، وحسب تلك القاعدة فإنه يعبَّر عن التاريخ حسب عدد الثواني، إذ يمثِّل العدد الموجب عدد ثواني المارة على تاريخ 1/1/1970؛ أما العدد السالب، فيُمثِّل عدد الثواني المطلوبة للوصول إلى وقت يونكس أي تاريخ 1 شهر 1 عام 1970م في حال تعاملنا مع تاريخ قديم، ولفهم ما نعنيه يمكن تخيُّل تاريخ وقت يونكس هو نقطة الصفر بحيث تمثِّل القيمة الموجبة ما بعد ذلك التاريخ؛ أما القيمة السالبة، فتمثِّل ما قبل ذلك التاريخ كما في الصورة التالية:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118763" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-020.png.7e6f25c428a97748a0219892fb6c8153.png" rel=""><img alt="دالة time في بايثون" class="ipsImage ipsImage_thumbnailed" data-fileid="118763" data-ratio="20.91" data-unique="89apf9ael" style="width: 550px; height: auto;" width="550" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-020.thumb.png.b6f193b90af1ddb7cac077ebe2e907d8.png"> </a>
</p>

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

<h3>
	دالة localtime
</h3>

<p>
	يمكننا في بايثون معرفة التاريخ الحالي عبر دالة <code>localtime</code> وفي المثال الآتي نوضِّح كيفية استخدامها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_19" style=""><span class="kwd">import</span><span class="pln"> time
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">localtime</span><span class="pun">());</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> time</span><span class="pun">.</span><span class="pln">struct_time</span><span class="pun">(</span><span class="pln">tm_year</span><span class="pun">=</span><span class="lit">2020</span><span class="pun">,</span><span class="pln"> tm_mon</span><span class="pun">=</span><span class="lit">6</span><span class="pun">,</span><span class="pln"> tm_mday</span><span class="pun">=</span><span class="lit">24</span><span class="pun">,</span><span class="pln"> tm_hour</span><span class="pun">=</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> tm_min</span><span class="pun">=</span><span class="lit">23</span><span class="pun">,</span><span class="pln"> tm_sec</span><span class="pun">=</span><span class="lit">55</span><span class="pun">,</span><span class="pln"> tm_wday</span><span class="pun">=</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> tm_yday</span><span class="pun">=</span><span class="lit">176</span><span class="pun">,</span><span class="pln"> tm_isdst</span><span class="pun">=</span><span class="lit">0</span><span class="pun">)</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_21" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">localtime</span><span class="pun">()[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2020</span></pre>

<p>
	ولطباعة الشهر مثلًا يجب طباعة العنصر الثاني كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_24" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">localtime</span><span class="pun">()[</span><span class="lit">1</span><span class="pun">]);</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">6</span></pre>

<p>
	وهكذا.
</p>

<h3>
	دالة asctime
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_26" style=""><span class="kwd">import</span><span class="pln"> time
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">asctime</span><span class="pun">(</span><span class="pln">time</span><span class="pun">.</span><span class="pln">localtime</span><span class="pun">()));</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Wed</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">24</span><span class="pln"> </span><span class="lit">23</span><span class="pun">:</span><span class="lit">41</span><span class="pun">:</span><span class="lit">30</span><span class="pln"> </span><span class="lit">2020</span></pre>

<h3>
	دالة sleep
</h3>

<p>
	توقف الدالة <code>sleep</code> عمل البرنامج لبرهة من الزمن تُحدَّد بعدد من الثواني تُمرَّر على أساس معامِل وحيد في الدالة، ففي المثال التالي سيُطبَع الاسم Adam في بداية تشغيل البرنامج ثم سيتوقف البرنامج عشرة ثوانٍ ثم يطبع الاسم Noah:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_28" style=""><span class="kwd">import</span><span class="pln"> time
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Adam'</span><span class="pun">)</span><span class="pln">
time</span><span class="pun">.</span><span class="pln">sleep</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="pln"> </span><span class="pun">(</span><span class="str">'Noah'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Adam</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Noah</span></pre>

<h2>
	دوال التعامل مع التواريخ في بايثون
</h2>

<p>
	سنتعرف على بعض الدوال البسيطة والمفيدة في التعامل مع التواريخ.
</p>

<h3>
	دالة month
</h3>

<p>
	تطبع التقويم الميلادي لشهر محدد في سنة محددة عبر المعامِلات التي تستقبلها الدالة، فالمعامل الأول المطلوب في الدالة هو العام؛ أما المعامل الثاني فهو رقم الشهر، إذ يمكننا عبر المثال التالي طباعة تقويم شهر 1 من عام 2019م:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_30" style=""><span class="kwd">import</span><span class="pln"> calendar
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">calendar</span><span class="pun">.</span><span class="pln">month</span><span class="pun">(</span><span class="lit">2019</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln">     </span><span class="typ">January</span><span class="pln"> </span><span class="lit">2019</span><span class="pln">
</span><span class="typ">Mo</span><span class="pln"> </span><span class="typ">Tu</span><span class="pln"> </span><span class="typ">We</span><span class="pln"> </span><span class="typ">Th</span><span class="pln"> </span><span class="typ">Fr</span><span class="pln"> </span><span class="typ">Sa</span><span class="pln"> </span><span class="typ">Su</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><span class="pln">  </span><span class="lit">6</span><span class="pln">
 </span><span class="lit">7</span><span class="pln">  </span><span class="lit">8</span><span class="pln">  </span><span class="lit">9</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="lit">11</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="lit">13</span><span class="pln">
</span><span class="lit">14</span><span class="pln"> </span><span class="lit">15</span><span class="pln"> </span><span class="lit">16</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">18</span><span class="pln"> </span><span class="lit">19</span><span class="pln"> </span><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><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span><span class="lit">26</span><span class="pln"> </span><span class="lit">27</span><span class="pln">
</span><span class="lit">28</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="lit">30</span><span class="pln"> </span><span class="lit">31</span></pre>

<h3>
	دالة today
</h3>

<p>
	توجد في بايثون وحدة <code>datetime</code> والتي تحتوي على الكثير من الخصائص والدوال منها الدالة <code>today</code>.
</p>

<p>
	نستطيع استخدام الدالة <code>today</code> لطباعة تاريخ اليوم، ففي المثال الآتي نستورد الصنف <code>date</code> من الوحدة <code>datetime</code> ثم نستخدِم دالة <code>today</code> الموجودة بداخلها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_32" style=""><span class="kwd">from</span><span class="pln"> datetime </span><span class="kwd">import</span><span class="pln"> date

</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">date</span><span class="pun">.</span><span class="pln">today</span><span class="pun">())</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2020</span><span class="pun">-</span><span class="lit">06</span><span class="pun">-</span><span class="lit">25</span></pre>

<h3>
	دالة isleap
</h3>

<p>
	تتحقق هذه الدالة من كون السنة المحدَّدة في معاملها سنةً كبيسةً أم لا، إذ نتحقق في المثال التالي من سنة 2019:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_34" style=""><span class="kwd">import</span><span class="pln"> calendar
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">calendar</span><span class="pun">.</span><span class="pln">isleap</span><span class="pun">(</span><span class="lit">2019</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="kwd">False</span></pre>

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

<h3>
	دالة leapdays
</h3>

<p>
	تحسب هذه الدالة عدد الأيام الكبيسة في نطاق عدد سنوات يُحدَّد عبر تمرير معاملين فيها بحيث يحتوي المعامِل الأول على عام بداية النطاق؛ أما المعامل الثاني فيحتوي على عام نهاية النطاق، فإذا أردنا مثلًا معرفة عدد الأيام الكبيسة منذ عام 1990م حتى عام 2019م، فسيكون كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_36" style=""><span class="kwd">import</span><span class="pln"> calendar

</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">calendar</span><span class="pun">.</span><span class="pln">leapdays</span><span class="pun">(</span><span class="lit">1990</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2019</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">7</span></pre>

<p>
	توجد في كل من الوحدات <code>time</code> و <a href="https://wiki.hsoub.com/Python/calendar" rel="external"><code>calendar</code></a> و <a href="https://wiki.hsoub.com/Python/datetime" rel="external"><code>datetime</code></a> السالف ذكرها الكثير من الدوال والخصائص الأخرى التي لا يتسع الفصل لذكرها، ويمكنك الرجوع إلى <a href="https://wiki.hsoub.com/Python#.D8.A7.D9.84.D9.88.D8.AD.D8.AF.D8.A7.D8.AA_.D8.A7.D9.84.D9.82.D9.8A.D8.A7.D8.B3.D9.8A.D8.A9_.D9.81.D9.8A_.D9.84.D8.BA.D8.A9_.D8.A8.D8.A7.D9.8A.D8.AB.D9.88.D9.86" rel="external">توثيقها في موسوعة حسوب</a> لمزيد من التفاصيل.
</p>

<h2>
	دوال التعامل مع الملفات في بايثون
</h2>

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

<p>
	<strong>ملاحظة</strong>: لا تُستخدَم دوال التعامل مع الملفات المدمجة غالبًا بصورة افتراضية في بايثون في <a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%AE%D8%B7%D9%88%D8%A7%D8%AA-%D8%AA%D9%86%D9%81%D9%8A%D8%B0-%D9%85%D8%B4%D8%B1%D9%88%D8%B9-%D8%B9%D9%86-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A2%D9%84%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%AC%D8%B2%D8%A1-%D8%A7%D9%84%D8%A3%D9%88%D9%84-r1357/" rel="">مشاريع تعلُّم الآلة</a>، وذلك لأن معظم ملفات تلك المشروعات هي ملفات بصيغة CSV أو ما شابه، وهي ملفات من الأفضل قراءة محتواها عبر مكتبات متخصصة لذلك النوع، ولكن مع ذلك فإنه من المُستحسن معرفة بعض تلك الدوال المدمجة وإمكاناتها، إذ أنها قد تكون مفيدةً في بعض البرامج.
</p>

<h3>
	الدالة read
</h3>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_39" style=""><span class="pln">file </span><span class="pun">=</span><span class="pln"> open </span><span class="pun">(</span><span class="str">'file.txt'</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">file</span><span class="pun">.</span><span class="pln">read</span><span class="pun">())</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">The</span><span class="pln"> file content</span></pre>

<p>
	استخدمنا في المثال السابق الدالة <code>open</code> لقراءة الملف دون تمرير معامل ثان لها وهو معامل الوصول بوضع القراءة افتراضيًا، وقد أنشأت بذلك كائنًا يحتوي على الكثير من الدوال، منها الدالة التي تتيح قراء المحتوى النصي وهي الدالة <code>read</code>.
</p>

<h3>
	الدالة write
</h3>

<p>
	كما يمكننا أيضًا كتابة محتوًى في الملف بتغيير رمز وضع الوصول إلى <code>w</code>، ثم استخدام الدالة <code>write</code> لإدخال نص وحفظه في الملف كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_41" style=""><span class="pln">file </span><span class="pun">=</span><span class="pln"> open </span><span class="pun">(</span><span class="str">'file.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'w'</span><span class="pun">)</span><span class="pln">
file</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'New file content'</span><span class="pun">)</span></pre>

<p>
	ستُحذَف جميع محتويات الملف النصي بعد تنفيذ ذلك البرنامج، ويُغيَّر بالمعامل الأول في دالة <code>write</code>، والجدير بالذكر أنّ الرمز <code>w</code> يتيح الكتابة في الملفات فقط ولا يتيح قراءة المحتويات.
</p>

<h3>
	الدالة close
</h3>

<p>
	من الأفضل إغلاق المتغير الذي يحتوي على الملف بعد إنهاء المهمات المُراد تنفيذها على الملفات لكي تُلغى أيّة تعديلات غير منتهية ومن ثم إغلاق الملف، إذ لن يكون التعديل على الملف متاحًا بعد إغلاقه إلا إذا استُخدِمت الدالة <code>open</code> مرةً أخرى لفتح الملف، ويمكن إغلاق الملف باستخدام الدالة <code>close</code> الموجودة في متغير الملف كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_43" style=""><span class="pln">file</span><span class="pun">.</span><span class="pln">close</span><span class="pun">()</span></pre>

<h3>
	الدالتان remove و rename
</h3>

<p>
	توجد دالتان مهمتان هما دالة حذف الملفات <code>remove</code> ودالة إعادة تسمية الملفات <code>rename</code>، لكنهما متاحتان فقط بوجود مكتبة مستقلة للتعامل مع <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">أنظمة التشغيل</a>، وهي مكتبة <code>os</code> المُسماة بذلك اختصارا لكلمة Operating System، إذ يكون المعامل الوحيد للدالة الأولى التي تتيح حذف الملفات هو اسم الملف أو مساره بداخل المجلد الموجود فيه البرنامج؛ أما الدالة الثانية التي تتيح إعادة تسمية الملفات، فستطلب معاملين هما اسم الملف الحالي المُراد تعديله واسم الملف الجديد، إذ سنعيد في المثال التالي تسمية ملف موجود بجوار البرنامج.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_46" style=""><span class="kwd">import</span><span class="pln"> os
os</span><span class="pun">.</span><span class="pln">rename </span><span class="pun">(</span><span class="str">'file.txt'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'file_renamed.txt'</span><span class="pun">)</span></pre>

<p>
	سيتغير بذلك اسم الملف بجوار البرنامج من file.txt إلى file_renamed.txt بدون طباعة أيّ كلمة عند تشغيل البرنامج.
</p>

<p>
	<strong>ملاحظة</strong>: من الضروري دائمًا معاملة صيغة الملف على أساس جزء من الاسم عند التعامل مع الملفات في بايثون وفي معظم لغات البرمجة.
</p>

<p>
	يوضِّح المثال التالي حذف الملف من الحاسوب تمامًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_48" style=""><span class="kwd">import</span><span class="pln"> os
os</span><span class="pun">.</span><span class="pln">remove </span><span class="pun">(</span><span class="str">'file_renamed.txt'</span><span class="pun">)</span></pre>

<h2>
	دوال التعامل مع النصوص في بايثون
</h2>

<p>
	النص أو <a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d8%a7%d9%84%d9%82%d9%88%d8%a7%d8%a6%d9%85-%d9%88%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-%d9%84%d8%ba%d8%a9-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r223/" rel="">السلسلة النصية string في لغة بايثون</a> عبارة عن سلسلة متتالية من الأحرف الموضوعة ضمن علامتي اقتباس مفردتين أو مزدوجتين
</p>

<p>
	ومن أهم الدوال المستخدمة للتعامل مع السلاسل النصية في بايثون نذكر:
</p>

<h3>
	دالة str
</h3>

<p>
	السلسلة النصية كما ذكرنا ما هي إلا سلسلة من الأحرف المتتالية ويمكنك الوصول إلى كل حرف منها باستخدام الدالة str [n] حيث يعبر n هنا عن موضع أو فهرس الحرف الذي تريد الوصول له، علمًا بأن فهرسة السلاسل النصية في بايثون تبدأ بالصفر أي أن فهرس الحرف الأول في السلسلة النصية يساوي صفر.
</p>

<p>
	لنأخذ مثالًا لتوضيح الأمر، سننشئ متغير يعبر عن السلسلة Python String وسنصل للحرفين الأول والثاني من السلسلة من خلال كتابة str[0] و str[1] كما يلي
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_51" style=""><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Python String"</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">])</span><span class="pln"> </span><span class="com"># P</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">str</span><span class="pun">[</span><span class="lit">1</span><span class="pun">])</span><span class="pln"> </span><span class="com"># y</span></pre>

<p>
	ملاحظة: إذا كنت مررت قيمة سالبة للفهرس فإن بايثون تبدأ العد من نهاية السلسلة وتعيد لك الحرف الموافق وتبدأ الفهرسة في هذه الحالة بالقيمة 1- كما هو موضح في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_53" style=""><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Python String"</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">str</span><span class="pun">[-</span><span class="lit">1</span><span class="pun">])</span><span class="pln"> </span><span class="com"># g</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">str</span><span class="pun">[-</span><span class="lit">4</span><span class="pun">])</span><span class="pln"> </span><span class="com"># r</span></pre>

<p>
	ويمكن الحصول على سلسلة فرعية من سلسلة نصية ما من خلال تمرير مجال من القيم للدالة على سبيل المثال للحصول على أول 6 أحرف من السلسلة النصية "Python String" نكتب الكود التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_55" style=""><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Python String"</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">str</span><span class="pun">[</span><span class="lit">0</span><span class="pun">:</span><span class="lit">6</span><span class="pun">])</span><span class="pln"> </span><span class="com">#Python</span></pre>

<p>
	كما تلاحظ من المثال أعلاه ستتضمن السلسلة الفرعية الناتج عن الأحرف من الدليل رقم 0 لغاية الدليل 5 وتستبعد الحرف ذو الدليل 6.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_57" style=""><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Python String"</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">str</span><span class="pun">[:</span><span class="lit">6</span><span class="pun">])</span><span class="pln"> </span><span class="com"># Python</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">str</span><span class="pun">[</span><span class="lit">7</span><span class="pun">:])</span><span class="pln"> </span><span class="com"># String</span></pre>

<h3>
	دالة len
</h3>

<p>
	تستعمل الدالة len للحصول على طول السلسلة النصية أي عدد حروفها، على سبيل المثال الشيفرة التالية تعيد القيمة 13
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_59" style=""><span class="pln">str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Python String"</span><span class="pln">
str_len </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">str</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">str_len</span><span class="pun">)</span></pre>

<h2>
	دوال التعامل مع القوائم والمصفوفات في بايثون
</h2>

<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="">القوائم lists</a> والمصفوفات arrays بنى بيانات في بايثون قادرة على تخزين عناصر متعددة في متغير واحد. والفرق الأساسي بين القوائم والمصفوفات هو أن القائمة تتكون من عناصر تنتمي إلى أنواع بيانات مختلفة في حين تتكون المصفوفة من عناصر تنتمي إلى نفس نوع البيانات.
</p>

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

<h3>
	دالة append
</h3>

<p>
	تضيف الدالة append عنصرًا واحدًا إلى نهاية القائمة، يمكن أن يكون العنصر نفسه قائمة، لاحظ الأمثلة التالية
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_62" style=""><span class="pln">fruits </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'apple'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'banana'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cherry'</span><span class="pun">]</span><span class="pln">
vegetables </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"cabbage"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"tomato"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"cucumber"</span><span class="pun">]</span><span class="pln">
fruits</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="str">"orange"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['apple', 'banana', 'cherry', 'orange']</span><span class="pln">
fruits</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">vegetables</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['apple', 'banana', 'cherry', 'orange', ['cabbage', 'tomato', 'cucumber']]</span></pre>

<h3>
	دالة clear
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_66" style=""><span class="pln">fruits </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"apple"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"banana"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"cherry"</span><span class="pun">]</span><span class="pln">
fruits</span><span class="pun">.</span><span class="pln">clear</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">)</span><span class="pln"> </span><span class="com">#[]</span></pre>

<h3>
	دالة count
</h3>

<p>
	تعيد الدالة count عدد المرات التي ورد فيها عنصر ما في القائمة، على سبيل المثال لإعادة عدد مرات ورود اسم معين في قائمة من الأسماء أو رقم محدد في سلسلة أرقام نكتب الكود التالي
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_64" style=""><span class="pln">names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Ali'</span><span class="pun">,</span><span class="str">'OLA'</span><span class="pun">,</span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="str">'Ali'</span><span class="pun">,</span><span class="str">'Mohammed'</span><span class="pun">,</span><span class="str">'Ali'</span><span class="pun">,]</span><span class="pln">
num</span><span class="pun">=</span><span class="pln">names</span><span class="pun">.</span><span class="pln">count</span><span class="pun">(</span><span class="str">"Ali"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">num</span><span class="pun">)</span><span class="pln"> </span><span class="com">#3</span><span class="pln">
points </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">3</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">9</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">9</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">
x </span><span class="pun">=</span><span class="pln"> points</span><span class="pun">.</span><span class="pln">count</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">x</span><span class="pun">)#</span><span class="lit">2</span></pre>

<h3>
	دالة extend
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_68" style=""><span class="pln">fruits </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'apple'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'banana'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cherry'</span><span class="pun">]</span><span class="pln">
vegetables </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">"cabbage"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"tomato"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"cucumber"</span><span class="pun">]</span><span class="pln">
points </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">4</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">9</span><span class="pun">)</span><span class="pln">
fruits</span><span class="pun">.</span><span class="pln">extend</span><span class="pun">(</span><span class="pln">vegetables</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">fruits</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['apple', 'banana', 'cherry', 'cabbage', 'tomato', 'cucumber']</span></pre>

<h3>
	دالة index
</h3>

<p>
	تعيد الدالة index فهرس العنصر في القائمة كل ما عليك هو تمرير قيمة العنصر الذي تريد البحث عنه في السلسلة وستعيد لك الدالة دليل أو ظهور له ضمن القائمة، وتذكر أن فهرس أول عنصر في القائمة هو 0.
</p>

<p>
	لاحظ المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_70" style=""><span class="pln">names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Myriam '</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Ali'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Mohammed'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="str">'Salah'</span><span class="pun">]</span><span class="pln">
i</span><span class="pun">=</span><span class="pln">names</span><span class="pun">.</span><span class="pln">index</span><span class="pun">(</span><span class="str">'Ahmad'</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"> </span><span class="com">#3</span></pre>

<h3>
	دالة insert
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_72" style=""><span class="pln">students </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Ali'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">90</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Salah'</span><span class="pun">,</span><span class="pln"> </span><span class="lit">80</span><span class="pun">]</span><span class="pln">
students</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">76</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">students</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['Ali', 90, 'Ahmad', 76, 'Salah', 80]</span></pre>

<h3>
	دالة pop
</h3>

<p>
	تحذف الدالة pop عنصر له فهرس محدد من القائمة ويمكن أن تعيد لنا العنصر المحذوف كما في المثال التالي
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_74" style=""><span class="pln">fruits </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'apple'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'banana'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'cherry'</span><span class="pun">]</span><span class="pln">
x </span><span class="pun">=</span><span class="pln"> fruits</span><span class="pun">.</span><span class="pln">pop</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="pln">fruits</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['apple', 'cherry']</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="com">#banana</span></pre>

<h3>
	دالة remove
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_76" style=""><span class="pln">names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Ali'</span><span class="pun">,</span><span class="str">'OLA'</span><span class="pun">,</span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="str">'Ali'</span><span class="pun">,</span><span class="str">'Mohammed'</span><span class="pun">,</span><span class="str">'Ali'</span><span class="pun">,]</span><span class="pln">
names</span><span class="pun">.</span><span class="pln">remove</span><span class="pun">(</span><span class="str">"Ali"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">names</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['OLA', 'Ahmad', 'Ali', 'Mohammed', 'Ali']</span></pre>

<h3>
	دالة reverse
</h3>

<p>
	تعكس الدالة ترتيب عناصر القائمة
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_78" style=""><span class="pln">numbers </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</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"> </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="lit">4</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">8</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> </span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
numbers</span><span class="pun">.</span><span class="pln">reverse</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">numbers</span><span class="pun">)</span><span class="pln">
</span><span class="com">#[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] </span></pre>

<h3>
	دالة sort
</h3>

<p>
	ترتب الدالة sort عناصر القائمة وفق التسلسل الأبجدي وهي تفرز العناصر تصاعديًا بشكل افتراضي كما يمكن تمرير وسيط اختياري reverse وإعطاؤه القيمة True لجعل الدالة تغير طريقة عملها وتفرز عناصر القائمة تنازليًا
</p>

<p>
	على سبيل المثال لترتيب مجموعة من الأسماء أبجديًا نكتب الشيفرة التالية
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_80" style=""><span class="pln">names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'OLA'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Mohammed'</span><span class="pun">]</span><span class="pln">
names</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">()</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">names</span><span class="pun">)</span><span class="pln"> </span><span class="com"># ['Ahmad', 'Mohammed', 'OLA']</span><span class="pln">
names</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">reverse</span><span class="pun">=</span><span class="kwd">True</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">names</span><span class="pun">)</span><span class="pln"> </span><span class="com"># ['OLA', 'Mohammed', 'Ahmad']</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_721_82" style=""><span class="kwd">def</span><span class="pln"> myFunc</span><span class="pun">(</span><span class="pln">e</span><span class="pun">):</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">e</span><span class="pun">)</span><span class="pln">

names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Ahmad'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Ali'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Mohammed'</span><span class="pun">]</span><span class="pln">

names</span><span class="pun">.</span><span class="pln">sort</span><span class="pun">(</span><span class="pln">key</span><span class="pun">=</span><span class="pln">myFunc</span><span class="pun">)</span><span class="pln">

</span><span class="kwd">print</span><span class="pun">(</span><span class="pln">names</span><span class="pun">)</span><span class="pln"> </span><span class="com">#['Ali', 'Ahmad', 'Mohammed']</span></pre>

<p>
	هذه كانت نبذة سريعة عن أهم الدوال الأساسية في الدوال المدمجة في لغة بايثون، ويمكنك التعرف على مزيد من التفاصيل حول الدوال المدمجة في لغة بايثون بالاطلاع على <a href="https://wiki.hsoub.com/Python" rel="external">توثيق لغة بايثون</a> باللغة العربية الذي وفرته لك <a href="https://wiki.hsoub.com/%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9_%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A%D8%A9" rel="external">موسوعة حسوب</a>.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1906/" rel="">مفهوم الدوال Functions في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">تعرف على الدوال (Functions) في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B1%D9%8A%D8%A7%D8%B6%D9%8A%D8%A9-%D8%A7%D9%84%D9%85%D8%B6%D9%85%D9%86%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r731/" 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>
</ul>
]]></description><guid isPermaLink="false">1907</guid><pubDate>Sun, 12 Feb 2023 08:18:49 +0000</pubDate></item><item><title>&#x645;&#x641;&#x647;&#x648;&#x645; &#x627;&#x644;&#x62F;&#x648;&#x627;&#x644; Functions &#x641;&#x64A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D9%81%D9%87%D9%88%D9%85-%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-functions-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1906/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_02/1342296368_---.png.dea6015c7b2cdec52e0869592abcb797.png" /></p>
<p>
	تُعَدّ الدوال Functions في لغات البرمجة كتلًا منظمةً من الشيفرة تؤدي مهامًا محددةً، ويمكن إعادة استخدامها في أيّ مكان في البرنامج، كما توفِّر للمبرمج طريقةً أفضل لتنظيم كتابته للبرامج، بحيث لا يُضطر إلى إعادة كتابة مهمة واحدة أكثر من مرة، وسنتعرف في هذا المقال على مفهوم الدوال وأنواعها وكيفية كتابة دوال مخصصة في لغة بايثون وتنفيذها.
</p>

<h2>
	تعريف دالة function
</h2>

<p>
	تُعرَّف <a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">الدالة في لغة بايثون</a> باستخدام الكلمة المفتاحية <code>def</code> -وهي اختصار كلمة definition أي تعريف- متبوعةً باسم الدالة والتي تخضع لقواعد المعرِّفات في <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> التي ذكرناها سابقًا في مقال <a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">أساسيات البرمجة في لغة بايثون</a>، ويلي اسم الدالة قوسان تُعرَّف معامِلات الدالة بداخلهما -والتي سنشرح أنواعها فيما بعد- ثم يُتبَع ذلك بالنقطتين <code>:</code>، وأسفل ذلك تُكتَب كتلة الشيفرة -أي جسم الدالة- التي ستُنفَّذ عند استدعاء الدالة.
</p>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_10" style=""><span class="kwd">def</span><span class="pln"> function_name</span><span class="pun">(</span><span class="pln"> arguments </span><span class="pun">):</span><span class="pln">
   </span><span class="str">"function's comment"</span><span class="pln">
   function code 
   </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">[</span><span class="pln">expression</span><span class="pun">]</span></pre>

<p>
	يمكننا البدء في تعريف دالة بمثال عن كتابة دالة تحسب مساحة الدوائر لتُستدعى من أجل حساب مساحة أية دائرة باختلاف نصف قطرها، ولكتابة تلك الدالة يجب معرفة قانون حساب مساحة الدائرة وهوπ*r<sup>2</sup> ‎ بحيث تكون π هي قيمة ثابتة تساوي 3.141592654؛ أما r<sup>2</sup> فهي مربع نصف قطر الدائرة، وهي المتغير المطلوب للدالة، إذ تختلف كل دائرة في نصف قطرها، في حين تبقى <code>π</code> ثابتةً لا تتغير، وبناءً على سنطبق العملية ثم نعيد الناتج من الدالة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_12" style=""><span class="kwd">def</span><span class="pln"> circle_area </span><span class="pun">(</span><span class="pln">radius</span><span class="pun">):</span><span class="pln">
    r_squared </span><span class="pun">=</span><span class="pln"> radius </span><span class="pun">**</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
    pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.141592654</span><span class="pln">
    area </span><span class="pun">=</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> r_squared
    </span><span class="kwd">return</span><span class="pln"> area</span></pre>

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

<h2>
	استدعاء دالة
</h2>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_14" style=""><span class="pln">r </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">circle_area</span><span class="pun">(</span><span class="pln">r</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">314.1592654</span></pre>

<h2>
	معاملات الدوال
</h2>

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

<p>
	يمكن تمرير المعاملات المطلوبة في الدوال بنفس ترتيبها في حالة وجود أكثر من معامل، ويمكننا لمزيد من التوضيح لعملية استدعاء الدوال وإسناد قيم المعاملات تخيل وجود دالة تُدعى <code>example</code> ولديها ثلاثة معاملات هي <code>a</code> و <code>b</code> و <code>c</code> كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_16" style=""><span class="kwd">def</span><span class="pln"> example</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">
    </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</span></pre>

<p>
	يمكن إسناد قيمة المعاملات الثلاثة بالترتيب عند استدعاء الدالة كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_18" style=""><span class="pln">example</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>
	ستُسنَد القيمة العددية 1 إلى المعامل a والقيمة العددية 2 إلى المعامل b والقيمة العددية 3 إلى المعامل c، لكن يمكن إسناد تلك القيم بدون استخدام ذلك الترتيب بذكر أسماء المعاملات وهو ما يسمى بالمعاملات المسماة Keyword Arguments كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_20" style=""><span class="pln">example</span><span class="pun">(</span><span class="pln">c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</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></pre>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_22" style=""><span class="pln">r_str </span><span class="pun">=</span><span class="pln"> input </span><span class="pun">(</span><span class="str">'Please enter R value: '</span><span class="pun">)</span><span class="pln">
r </span><span class="pun">=</span><span class="pln"> float</span><span class="pun">(</span><span class="pln">r_str</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">circle_area</span><span class="pun">(</span><span class="pln">radius</span><span class="pun">=</span><span class="pln">r</span><span class="pun">))</span></pre>

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

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

<h3>
	المعاملات الافتراضية
</h3>

<p>
	يمكن إضافة معامِلات لها قيم افتراضية، عندها يكون تمرير قيمة للمعامل غير ضروري أو اختياري عند استدعائه، ويكون ذلك عبر كتابة اسم المعامِل ثم استخدام عامل الإسناد <code>=</code> ثم كتابة القيمة الافتراضية للمعامِل.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_24" 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="lit">1</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> y

</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">multiple</span><span class="pun">(</span><span class="lit">5</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">5</span></pre>

<p>
	نلاحظ أنه لم نمرِّر المعامِل الثاني، وبما أنه يحمل قيمةً افتراضيةً هي العدد 1، فكانت النتيجة في ضرب العدد 5 بالعدد 1.
</p>

<h3>
	المعاملات الديناميكية ‎*args
</h3>

<p>
	من الميزات المفيدة في <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> وجود إمكانية إضافة عدد غير محدَّد من المعامِلات في الدوال عند استدعائها، وتُضاف تلك الميزة عبر إضافة رمز النجمة <code>*</code> عند تعريف الدالة وقبل كتابة اسم المعامِل الذي سيحمل جميل القيم التي ستمرَّر عند استدعاء الدالة مرتبةً حسبما تم تمريره عند الاستدعاء.
</p>

<p>
	في المثال التالي استقبلنا عددًا غير محدود من القيم، ثم استخدمنا <a href="https://academy.hsoub.com/programming/python/%d8%ad%d9%84%d9%82%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1-loops-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r291/" rel="">حلقة التكرار</a> <code>for</code>، من أجل جمع كل القيم وإعادة الناتج من الدالة.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_26" style=""><span class="kwd">def</span><span class="pln"> addition </span><span class="pun">(*</span><span class="pln">args</span><span class="pun">):</span><span class="pln">
    total </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"> args</span><span class="pun">:</span><span class="pln">
        total </span><span class="pun">+=</span><span class="pln"> number
    </span><span class="kwd">return</span><span class="pln"> total
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> addition</span><span class="pun">(</span><span class="lit">5</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">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">14</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">40</span></pre>

<p>
	كما يمكن إضافة عدد محدد من المعاملات في الدالة أولًا، ثم إضافة معامل يمثل بقية المعاملات إن وجدت آخر المعاملات حصرًا ولا نضيفه قبلها، وإليك مثال بتعديل الدالة السابقة مثلًا بحيث تجمع كل المعاملات الإضافية الزائدة عن المعامل <code>x</code> ثم تضرب الناتج فيه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_28" style=""><span class="kwd">def</span><span class="pln"> addition </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">args</span><span class="pun">):</span><span class="pln">
    total </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"> args</span><span class="pun">:</span><span class="pln">
        total </span><span class="pun">+=</span><span class="pln"> number
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> total
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> addition</span><span class="pun">(</span><span class="lit">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">6</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">14</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">80</span></pre>

<p>
	<strong>ملاحظة</strong>: في حالة استخدام ميزة المعاملات الديناميكية في إحدى الدوال، لا يمكن تمرير قيم المعاملات عبر تحديد أسمائها بل يجب تمرير المعاملات حسب ترتيب تعريفها في الدالة.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_30" style=""><span class="kwd">def</span><span class="pln"> addition</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">args</span><span class="pun">):</span><span class="pln">
    total </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"> args</span><span class="pun">:</span><span class="pln">
        total </span><span class="pun">+=</span><span class="pln"> number
    </span><span class="kwd">return</span><span class="pln"> x </span><span class="pun">*</span><span class="pln"> total</span><span class="pun">,</span><span class="pln"> total
result </span><span class="pun">=</span><span class="pln"> addition</span><span class="pun">(</span><span class="lit">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">6</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">14</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"> result</span><span class="pun">[</span><span class="lit">0</span><span class="pun">],</span><span class="pln"> result</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="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">80</span><span class="pln"> </span><span class="lit">40</span></pre>

<h3>
	المعاملات الديناميكية المسماة ‎**kwargs
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_32" style=""><span class="kwd">def</span><span class="pln"> print_name</span><span class="pun">(**</span><span class="pln">kid</span><span class="pun">):</span><span class="pln">
  </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"His last name is "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> kid</span><span class="pun">[</span><span class="str">"lname"</span><span class="pun">])</span><span class="pln">

print_name</span><span class="pun">(</span><span class="pln">fname </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Jamil"</span><span class="pun">,</span><span class="pln"> mname</span><span class="pun">=</span><span class="pln"> </span><span class="str">"Ahmad"</span><span class="pun">,</span><span class="pln"> lname </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Alomar"</span><span class="pun">)</span></pre>

<h2>
	الدوال مجهولة الاسم
</h2>

<p>
	الدوال مجهولة الاسم Anonymous Functions وتُدعى أيضًا دوال لامدا Lambda Functions، وهي دوال لا تُعرَّف بالكلمة المفتاحية <code>def</code> وإنما تستخدم الكلمة المفتاحية <code>lambda</code>، وتُعرَّف بالشكل التالي بحيث توضع معاملات الدالة مكان args والتعليمة الوحيدة في الدالة مكان statement:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_34" style=""><span class="kwd">lambda</span><span class="pln"> args </span><span class="pun">:</span><span class="pln"> statement</span></pre>

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

<ul>
	<li>
		لا تستطيع الدوال المجهولة إعادة أكثر من قيمة واحدة.
	</li>
	<li>
		لا تستطيع الدوال المجهولة احتواء أكثر من تعليمة واحدة.
	</li>
</ul>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_36" style=""><span class="pln">addition </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">lambda</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"> y</span></pre>

<p>
	نلاحظ أنه قد أسنِدت الدالة إلى متغير <code>addition</code>، إذ يكون اسم المتغير هو نفسه اسم الدالة حتى نستطيع استدعاء الدالة عند الحاجة، وبذلك نستطيع استدعاء الدالة مع تمرير المعاملات المطلوبة <code>x</code> و <code>y</code> للحصول على ناتج الدالة بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_38" style=""><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">addition</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="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3</span></pre>

<h2>
	نطاق المتغيرات Variables Scope
</h2>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_40" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> example</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">
example</span><span class="pun">()</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Hello</span></pre>

<p>
	أما المثال التالي فلن يعمل أبدًا، إذ يحاول البرنامج خارج الدالة طباعة متغير معرَّف داخل النطاق المحلي للدالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_42" style=""><span class="kwd">def</span><span class="pln"> example</span><span class="pun">():</span><span class="pln">
    x </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Hello'</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">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">NameError</span><span class="pun">:</span><span class="pln"> name </span><span class="str">'x'</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> defined</span></pre>

<p>
	ولذلك يجب دائمًا مراعاة نطاقات المتغيرات أثناء كتابة البرامج.
</p>

<h2>
	الوحدات Modules
</h2>

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

<p>
	تُنشأ الوحدات بإنشاء ملف بايثون منفصل في المجلد نفسه الذي يحتوي على مشروعك، فإذا كان برنامجك الذي تكتبه حاليًا موجودًا في ملف program.py مثلًا، فبإمكانك بجوار ذلك الملف إنشاء وحدة من خلال إنشاء ملف آخر باسم الوحدة، إذ نستطيع في مثالنا أعلاه تسمية الوحدة باسم calculations.py، بحيث تكون الكلمة calculations هي اسم الوحدة؛ أما py فهي صيغة كل الملفات التي تحتوي على شيفرة بايثون، وبعد ذلك نستطيع استيراد تلك الوحدة من الملف الرئيسي لبرنامجك باستخدام الكلمة المفتاحية <code>import</code> متبوعة باسم الوحدة، وعندئذ يُتاح لك الوصول إلى متغيرات ودوال تلك الوحدة في ملفك.
</p>

<p>
	لنضف الدالة التي كتبناها سابقًا لحساب مساحة الدائرة في تلك الوحدة الجديدة، لكن مع تعديل بسيط وهو أننا سنعرِّف المتغير الذي يحمل قيمة π في نطاق المتغيرات العام في ملف الوحدة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_44" style=""><span class="pln">pi </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.141592654</span><span class="pln">
</span><span class="kwd">def</span><span class="pln"> circle_area </span><span class="pun">(</span><span class="pln">radius</span><span class="pun">):</span><span class="pln">
    r_squared </span><span class="pun">=</span><span class="pln"> radius </span><span class="pun">**</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
    area </span><span class="pun">=</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> r_squared
    </span><span class="kwd">return</span><span class="pln"> area</span></pre>

<p>
	أما في ملف برنامجنا الرئيسي الآن، فسنستطيع البدء في استيراد الوحدة، ثم استخدام دالة حساب مساحة الدائرة والوصول إلى المتغير الذي يحمل قيمة <code>π</code> مباشرةً، إذ نستطيع مثلًا استقبال قيمة نصف القطر من المستخدِم أثناء تشغيل البرنامج، ثم استدعاء الدالة من الوحدة مباشرةً وطباعة النتيجة للمستخدِم كما في المثال الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_46" style=""><span class="kwd">import</span><span class="pln"> calculations
r </span><span class="pun">=</span><span class="pln"> input </span><span class="pun">(</span><span class="str">'Please enter R value: '</span><span class="pun">)</span><span class="pln">
r </span><span class="pun">=</span><span class="pln"> float </span><span class="pun">(</span><span class="pln">r</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">calculations</span><span class="pun">.</span><span class="pln">circle_area</span><span class="pun">(</span><span class="pln">r</span><span class="pun">))</span></pre>

<p>
	كما يمكن الوصول إلى متغيرات الوحدة مثل المتغير pi الذي يحمل قيمة π كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_48" style=""><span class="kwd">import</span><span class="pln"> calculations
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">calculations</span><span class="pun">.</span><span class="pln">pi</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3.141592654</span></pre>

<p>
	من الميزات المفيدة التي تقدمها الوحدات في بايثون أنه بالإمكان استيراد متغير أو دالة معينة من الوحدة، عبر استخدام الكلمة المفتاحية <code>from</code> متبوعةً باسم الوحدة، ثم استخدام أمر الاستيراد <code>import</code> متبوعًا باسم المتغير أو الدالة المُراد استيرادها كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_50" style=""><span class="kwd">from</span><span class="pln"> calculations </span><span class="kwd">import</span><span class="pln"> pi
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pi</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3.141592654</span></pre>

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

<ol>
	<li>
		البحث عن اسم الوحدة في الملفات الموجودة في المجلد نفسه الذي يحتوي على البرنامج.
	</li>
	<li>
		إذا لم يستطع إيجاد الوحدة، فسيبحث في جميع مسارات المجلدات المخزنة في متغير البيئة <code>PYTHONPATH</code>.
	</li>
	<li>
		إذا لم يستطع إيجاد الوحدة، فسيبحث في المسار الرئيسي المثبَّت فيه لغة بايثون، والذي يحتوي عادةً على المكتبات التي ثبِّتت على الحاسوب لتُستخدَم في جميع برامج بايثون.
	</li>
</ol>

<p>
	ومن أهم المعلومات الواجب ذكرها، قبل الانتهاء من الحديث عن الوحدات، أنه يوجد اختلاف بين <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-modules-%D9%88%D8%A7%D9%84%D8%AD%D8%B2%D9%85-packages-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r329/" rel="">الوحدات</a> وبين المكتبات على الرغم من كون طريقة الاستيراد لكلاهما متشابهة، إذ تستورَد المكتبة كاملًا عن طريق الكلمة المفتاحية الخاصة بالاستيراد، ويستورَد جزء من المكتبة بالكلمة المفتاحية <code>from</code>، لكن قد تحتوي المكتبة على العديد من الوحدات والملفات، فغالبًا تكون المكتبة تطبيقًا يحتوي على العديد من الوحدات، التي بدورها تحتوي على تصنيفات ودوال ومتغيرات، وتكون تلك المكتبة في مجلد منفصل.
</p>

<p>
	يتطلب إنشاء مكتبة إنشاء مجلد يحتوي على ملف فارغ باسم <code>init__.py__</code> ليُعرَّف المجلد على أساس مكتبة بايثون، ثم يُنشأ أيّ عدد من الوحدات -أي الملفات- لتُستورَد بعد ذلك من خلال استيراد اسم المكتبة، ولمزيد من التوضيح فإنه يمكن إنشاء مكتبة -أي مجلد- باسم calculations من أجل المثال الذي أوردناه لدالة حساب مساحة الدائرة، ثم ننشئ ملفًا فارغًا باسم <code>init__.py__</code> ثم ننشئ ملفًا باسم circle.py يحتوي على محتوى الوحدة نفسها التي كتبناها للتو وبعد ذلك تكون قد حوِّلت الوحدة calculations إلى مكتبة يمكن استيراد إحدى وحداتها كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_52" style=""><span class="kwd">from</span><span class="pln"> calculations </span><span class="kwd">import</span><span class="pln"> circle
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">circle</span><span class="pun">.</span><span class="pln">pi</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3.141592654</span></pre>

<p>
	نلاحظ أننا استوردنا الوحدة <code>circle</code> من المكتبة ولم نستورِد المكتبة كلها، ونستطيع التفصيل بصورة أكبر من ذلك حتى، إذ نستطيع استيراد المتغير π فقط من داخل الوحدة كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3001_55" style=""><span class="kwd">from</span><span class="pln"> calculations</span><span class="pun">.</span><span class="pln">circle </span><span class="kwd">import</span><span class="pln"> pi
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">pi</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">3.141592654</span></pre>

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

<p>
	للمزيد من التفاصيل حول هذه النقطة، ننصحك بقراءة مقال <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-r1333/" rel="">البرمجة باستخدام الوحدات</a>.
</p>

<h2>
	خاتمة
</h2>

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

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D8%AA%D8%AE%D8%A7%D8%B0-%D8%A7%D9%84%D9%82%D8%B1%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%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%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1892/" rel="">اتخاذ القرار: العبارات الشرطية والحلقات التكرارية في البرمجة</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="">كيفية استخدام args* و kwargs** في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AF%D9%88%D8%A7%D9%84-%D8%A7%D9%84%D8%B1%D9%8A%D8%A7%D8%B6%D9%8A%D8%A9-%D8%A7%D9%84%D9%85%D8%B6%D9%85%D9%86%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-3-r731/" 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%A3%D9%87%D9%85-8-%D9%85%D9%83%D8%AA%D8%A8%D8%A7%D8%AA-%D8%A8%D9%84%D8%BA%D8%A9-%D8%A7%D9%84%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%AA%D8%B3%D8%AA%D8%AE%D8%AF%D9%85-%D9%81%D9%8A-%D8%A7%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D8%A7%D9%84%D8%B5%D8%BA%D9%8A%D8%B1%D8%A9-r654/" rel="">أهم 8 مكتبات بلغة البايثون تستخدم في المشاريع الصغيرة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1906</guid><pubDate>Wed, 15 Feb 2023 16:00:00 +0000</pubDate></item><item><title>&#x627;&#x62A;&#x62E;&#x627;&#x630; &#x627;&#x644;&#x642;&#x631;&#x627;&#x631;: &#x627;&#x644;&#x639;&#x628;&#x627;&#x631;&#x627;&#x62A; &#x627;&#x644;&#x634;&#x631;&#x637;&#x64A;&#x629; &#x648;&#x627;&#x644;&#x62D;&#x644;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631;&#x64A;&#x629; &#x641;&#x64A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D8%AA%D8%AE%D8%A7%D8%B0-%D8%A7%D9%84%D9%82%D8%B1%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D8%A8%D8%A7%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-%D9%88%D8%A7%D9%84%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%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1892/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_02/805399132_-----.png.bc110727c1adc6a168e79a3ac1f2e2de.png" /></p>
<p>
	يُعَدّ اتخاذ القرار أحد المواضيع الأهم في <a href="https://academy.hsoub.com/programming/general/%D9%87%D9%86%D8%AF%D8%B3%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA/" rel="">هندسة البرمجيات</a>، إذ يُستخدَم بصورة دائمة وضرورية في أيّ برنامج، في حين تُستخدَم جمل اتخاذ القرار لطرح سؤال ما، عبر المعامِلات التي تُستخدَم للموازنة التي ذكرناها في المقال السابق <a href="https://academy.hsoub.com/programming/artificial-intelligence/%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%88%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1872/" rel="">أنواع البيانات والعمليات الأساسية في لغة بايثون</a> من هذه السلسلة ومن ثم اتخاذ قرار بتنفيذ أسطر معيّنة بناءً على تحقق شرط من عدمه.
</p>

<h2>
	العبارات الشرطية
</h2>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118376" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-004.png.07a25afa486dc6fecfac1e3d46cd3492.png" rel=""><img alt="العبارات الشرطية في البرمجة" class="ipsImage ipsImage_thumbnailed" data-fileid="118376" data-ratio="139.25" data-unique="4pvy28mf3" style="width: 400px; height: auto;" width="431" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-004.thumb.png.afd6c599a22c3f2dee5943e55584f807.png"> </a>
</p>

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

<p>
	يمكن كتابة الجمل الشرطية في <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> ومحاكاة المخطط السابق عبر تعليمة <code>if</code> بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_11" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</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="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">'X equals five'</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="pln"> </span><span class="pun">(</span><span class="str">"X doesn't equal five"</span><span class="pun">)</span></pre>

<p>
	عرّفنا في المثال السابق متغيرًا يحتوي على القيمة العددية 5، ثم طرحنا سؤالًا في السطر الذي يليه على اللغة وهو: هل المتغير x يساوي العدد 5؟ بالطبع الإجابة نعم، وبناءً على ذلك ستُنفِّذ كتلة الشيفرة المندرِجة تحت هذا الشرط عند تحققه، أي ستُطبع <code>X equals five</code>، وقد استخدمنا في المثال السابق قاعدة <code>if else</code>، وهي ما يوضحها المخطط السابق إذ توجد كتلتان من الشيفرة، بحيث تُنفَّذ إحداهما فقط بناءً على نتيجة الجملة الشرطية.
</p>

<p>
	سنوضح في المخطط الآتي فسنوضح استخدام قاعدة <code>if</code> فقط، بحيث تُنفَّذ كتلة شيفرة عند تحقق الشرط، ولا يُنفَّذ أيّ شيء عند عدم تحققه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118377" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-006.png.abd50699f13bbd38588db081a4d26851.png" rel=""><img alt="استخدام الجمل الشرطية في البرمجة" class="ipsImage ipsImage_thumbnailed" data-fileid="118377" data-ratio="204.00" data-unique="q9pe2ppbm" style="width: 250px; height: auto;" width="250" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-006.thumb.png.2a63540a1bf964a2adc29b60ce964397.png"> </a>
</p>

<p>
	المثال المكافئ للمخطط <a href="https://wiki.hsoub.com/Python" rel="external">بلغة بايثون</a> يُكتب كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_15" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> x </span><span class="pun">&gt;</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="pln"> </span><span class="pun">(</span><span class="str">"X is bigger than 3"</span><span class="pun">)</span></pre>

<p>
	يكون المتغير x في هذه الحالة أكبر من الرقم بالطبع، وبالتالي ستُنفَّذ كتلة الشيفرة المندرجة تحت هذا الشرط، وتُطبَع العبارة X is bigger than 3؛ أما في المثال التالي فسنغيِّر معامِل الموازنة في الجملة الشرطية، وبالتالي فلن تُنفَّذ أيّ كتلة شيفرة لعدم استخدام قاعدة <code>if else</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_17" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> x </span><span class="pun">&lt;=</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="pln"> </span><span class="pun">(</span><span class="str">"X is less than 3 or equals to 3"</span><span class="pun">)</span></pre>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118379" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-008.png.e013d681294bef07f8640776abcb52ef.png" rel=""><img alt="مسار تنفيذ البرنامج" class="ipsImage ipsImage_thumbnailed" data-fileid="118379" data-ratio="187.00" data-unique="xzt1s3qqu" style="width: 300px; height: auto;" width="300" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-008.thumb.png.b61945138a19b7b8bd72eae915b9e11b.png"> </a>
</p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118380" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-010.png.95594258131895a5f28a7e7b816dae9f.png" rel=""><img alt="قواعد تحقق المفسر من الشرط إذا لم يتحقق الشرط السابق له" class="ipsImage ipsImage_thumbnailed" data-fileid="118380" data-ratio="81.25" data-unique="n8w68nbmj" style="width: 480px; height: auto;" width="450" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-010.png.95594258131895a5f28a7e7b816dae9f.png"> </a>
</p>

<p>
	نحاكي في المخطط السابق خريطة تدفق برنامج بسيط يحتوي على ثلاث جمل شرطية، أولها كُتبت باستخدام <code>if</code>، وثانيها وثالثها كُتِب باستخدام <code>elif</code>، كما من الضروري معرفة التالي:
</p>

<ul>
	<li>
		يجب أن تبدأ الجمل الشرطية بجملة <code>if</code> أولًا.
	</li>
	<li>
		لا حدود لجُمل <code>elif</code>، إذ يمكن أن يمتد المخطط السابق إلى عدد غير محدود من الجمل الشرطية الأخرى.
	</li>
	<li>
		يمكن إضافة جملة <code>else</code> مرةً واحدةً فـي الجمل الشرطية، وهي تُستخدَم كآخر حل بعد عدم تحقق جميع الشروط السابقة لها، أي <code>if</code> و <code>elif</code>.
	</li>
</ul>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_22" style=""><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Adam"</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">"Noah"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Noah"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">"Jacob"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Jacob"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">"Adam"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Adam"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">The</span><span class="pln"> name </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Adam</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_24" style=""><span class="pln">name </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Yusuf"</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">"Noah"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Noah"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">"Jacob"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Jacob"</span><span class="pun">)</span><span class="pln">
</span><span class="kwd">elif</span><span class="pln"> name </span><span class="pun">==</span><span class="pln"> </span><span class="str">"Adam"</span><span class="pun">:</span><span class="pln">
    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">"The name is Adam"</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="pln"> </span><span class="pun">(</span><span class="str">"We don't know the name"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">We</span><span class="pln"> don</span><span class="str">'t know the name</span></pre>

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

<h2>
	حلقات التكرار
</h2>

<p>
	تُعَدّ <span ipsnoautolink="true">حلقات التكرار Loops</span> إحدى أهم الميزات المستخدَمة بكثرة في كل <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a>، إذ قد يود المبرمج في كثير من الأحيان تكرار كتلة شيفرة معيّنة لمدة معيّنة قد تكون عددًا معيّنًا من المرات، أو إلى حين تحقق شرط معيّن، وذلك ما توفره لنا <a href="https://academy.hsoub.com/programming/python/%d8%ad%d9%84%d9%82%d8%a7%d8%aa-%d8%a7%d9%84%d8%aa%d9%83%d8%b1%d8%a7%d8%b1-loops-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r291/" rel="">حلقات التكرار في بايثون</a> وفي كثير من <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">اللغات البرمجية</a> الأخرى، كما تُستخدَم استخدامًا واسعًا في كثير من الخوارزميات وبالطبع في معظم البرامج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118381" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-012.png.da1398e24ff92d305d46c296b1ec2bae.png" rel=""><img alt="حلقات التكرار في البرمجة" class="ipsImage ipsImage_thumbnailed" data-fileid="118381" data-ratio="89.00" data-unique="85umhl9b7" style="width: 400px; height: auto;" width="675" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-012.thumb.png.892a914d37c76bf19109ef3f653972af.png"> </a>
</p>

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

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

<h3>
	حلقة While
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_37" style=""><span class="kwd">while</span><span class="pln"> expression</span><span class="pun">:</span><span class="pln">
    statements</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_39" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">9</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">
    x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_41" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">9</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"> x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="str">'Done'</span><span class="pun">)</span></pre>

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

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

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

<h3>
	حلقة For
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_43" style=""><span class="kwd">for</span><span class="pln"> variable </span><span class="kwd">in</span><span class="pln"> sequence</span><span class="pun">:</span><span class="pln">
    statements</span></pre>

<p>
	يحل اسم المتغير الذي يحتوي على قيمة العنصر الحالي أثناء دوران الحلقة محل variable في حين يحل اسم المتغير الذي يحتوي على السلسلة محل sequence والذي قد يكون قائمةً، أو مجموعةًً، أو صفًا؛ أما statements فيحل محلها كتلة الشيفرة المُراد تكرار تنفيذها.
</p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118382" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-014.png.51c66eebeafbd8f1437df28b21b70060.png" rel=""><img alt="حلقة For البرمجية" class="ipsImage ipsImage_thumbnailed" data-fileid="118382" data-ratio="108.00" data-unique="y075rt7zw" style="width: 500px; height: auto;" width="556" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-014.thumb.png.5ddc895cfdeeba5573734c3e88a6f5d1.png"> </a>
</p>

<p>
	ويوضح المثال التالي تنفيذ المخطط <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>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_47" style=""><span class="pln">names </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Adam'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Noah'</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> name </span><span class="kwd">in</span><span class="pln"> names</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">name</span><span class="pun">)</span></pre>

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

<p>
	لاحظ أنه يمكن استخدام النصوص في حلقات التكرار عبر قاعدة <code>for</code>، إذ أنّ كل محرف في النص هو عنصر مستقل بداخل السلسلة النصية، ففي المثال نطبع كل حرف من محارف كلمة Hello بصورة مفرَدة باستخدام حلقة <code>for</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_50" style=""><span class="kwd">for</span><span class="pln"> letter </span><span class="kwd">in</span><span class="pln"> </span><span class="str">'hello'</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">letter</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> h
</span><span class="pun">&gt;&gt;</span><span class="pln"> e
</span><span class="pun">&gt;&gt;</span><span class="pln"> l
</span><span class="pun">&gt;&gt;</span><span class="pln"> l
</span><span class="pun">&gt;&gt;</span><span class="pln"> o</span></pre>

<p>
	يمكن أيضًا إضافة <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%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%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1306/" rel="">حلقات تكرار</a> داخل حلقات أخرى، أو إضافة جمل شرطية داخل حلقات التكرار، أو إضافة جمل شرطية داخل جمل شرطية أخرى إلى ما لا نهاية، فلا يوجد ما يمنع أن تحتوي كتلة الشيفرة الموجودة داخل إحدى القواعد، على قاعدة أخرى وكتل أخرى بأيّ عدد.
</p>

<h3>
	الدالة range
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_53" style=""><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">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</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">number</span><span class="pun">)</span></pre>

<p>
	سيطبع المثال بناءً على ذلك الأرقام من 1 إلى 5 بالتتالي ولاحظ أن العدد الأقصى لا يدخل ضمن المجال.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5520_7" style=""><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">1</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">2</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">number</span><span class="pun">)</span></pre>

<p>
	سيطبع المثال أعلاه الأرقام من 1 و3 و5
</p>

<h3>
	التعليمة else
</h3>

<p>
	يمكن استخدام الكلمة المفتاحية <code>else</code> في حلقتَي <code>While</code> و<code>For</code>، إذ تُكتَب بعد كتلة الشيفرة المُنفَّذة على مستوى تعبير الحلقة نفسه، ثم إدماج كتلة شيفرة تُنفَّذ عند انتهاء تنفيذ الحلقة، فحتى إذا نُفِّذت كتلة الشيفرة الموجودة بداخل الحلقة مرةً أو ثلاث مرات أو أيّ عدد من المرات، أو لم تُنفَّذ على الإطلاق، فستُنفَّذ دائمًا كتلة الشيفرة التابعة للكلمة المفتاحية <code>else</code> في النهاية، كما في الأمثلة الآتية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_55" style=""><span class="kwd">for</span><span class="pln"> number </span><span class="kwd">in</span><span class="pln"> </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">number</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="pln"> </span><span class="pun">(</span><span class="str">'Done'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Done</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_57" style=""><span class="kwd">for</span><span class="pln"> number </span><span class="kwd">in</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">2</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">number</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="pln"> </span><span class="pun">(</span><span class="str">'Done'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Done</span></pre>

<h3>
	التوقف والتخطي في حلقات التكرار
</h3>

<p>
	تُعَدّ الكلمات <code>break</code> و<code>continue</code> و<code>pass</code> من أهم الكلمات المفتاحية الأخرى المُستخدَمة في حلقات التكرار، فكل واحدة منها يمكن استخدامها في حلقة <code>While</code> أو حلقة <code>For</code> على حد سواء.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_59" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Adam'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Noah'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Jacob'</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> name </span><span class="kwd">in</span><span class="pln"> x</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">'Adam'</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">break</span><span class="pln">

    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Adam</span></pre>

<p>
	كما يمكن إيضاح مسار تنفيذ المثال السابق عبر المخطط الآتي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118383" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-016.png.8f9f6b052810bac434acfd902df745f1.png" rel=""><img alt="التوقف والتخطي في حلقات التكرار" class="ipsImage ipsImage_thumbnailed" data-fileid="118383" data-ratio="65.69" data-unique="xmmmikcs5" style="width: 650px; height: auto;" width="65" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-016.png.8f9f6b052810bac434acfd902df745f1.png"> </a>
</p>

<p>
	نلاحظ أنّ قيمة المتغير name ستحمل القيمة Adam في أول دورة، وعندما يُتحقَّق من الجملة الشرطية هل الاسم لا يساوي آدم؟ فستكون الإجابة بالطبع لا، وستُنفَّذ عملية طباعة الاسم؛ أما في الدورة الثانية، فسيحمل المتغير القيمة Noah، وبالتالي سيتحقق الشرط أي يصبح True، وبالتالي ستُنفَّذ كتلة الشيفرة المندرجة تحت الشرط مباشرةً، وتلك الكتلة تحتوي على تعليمة واحدة وهي <code>break</code>، والتي تعني إنهاء الحلقة بجميع دوراتها واستكمال باقي البرنامج.
</p>

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

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="118384" href="https://academy.hsoub.com/uploads/monthly_2023_02/image-018.png.0276a363f9eb87a8ddfb99f71a9e4dc0.png" rel=""><img alt="آلية عمل الكلمة المفتاحية continue  في الحلقات التكرارية" class="ipsImage ipsImage_thumbnailed" data-fileid="118384" data-ratio="69.35" data-unique="do7tnysog" style="width: 750px; height: auto;" width="744" src="https://academy.hsoub.com/uploads/monthly_2023_02/image-018.thumb.png.32712187b6e0340f5d47b7defc0df73b.png"> </a>
</p>

<p>
	نكتب المخطط السابق بلغة بايثون بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_65" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Adam'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Noah'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Jacob'</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> name </span><span class="kwd">in</span><span class="pln"> x</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">'Adam'</span><span class="pun">:</span><span class="pln">
        </span><span class="kwd">continue</span><span class="pln">

    </span><span class="kwd">print</span><span class="pln"> </span><span class="pun">(</span><span class="pln">name</span><span class="pun">)</span><span class="pln">

</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Noah</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="typ">Jacob</span></pre>

<p>
	لدينا قائمةً تحتوي على ثلاثة أسماء، إذ نهدف من البرنامج إلى طباعة أيّ اسم في القائمة غير اسم آدم Adam، فلذلك كتبنا جملةً شرطيةً بداخل حلقة التكرار <code>for</code>، إذ تطرح الجملة الشرطية على المفسر سؤالًا وهو: هل الاسم الحالي يساوي آدم؟ ستكون الإجابة في أول دورة صحيحةً True، ولذلك سينفِّذ المفسر التعليمات المندرجة أسفل الشرط، إذ توجد تعليمة وحيدة مندرجة أسفل هذا الشرط وهي الكلمة المفتاحية <code>continue</code>، والتي تخبر مفسر اللغة كما ذكرنا ببساطة، بعدم استكمال الدورة الحالية والذهاب مباشرةً إلى الدورة التالية، أي العنصر التالي في القائمة وهكذا سيُطبَع الاسمان Noah و Jacob فقط.
</p>

<p>
	يمكن استخدام الكلمتان المفتاحيتان السابق ذكرهما <code>break</code> و<code>continue</code> في حلقات <code>while</code> وحلقات <code>for</code> على حد سواء، وفيما يلي مثال على استخدام <code>continue</code> في حلقة <code>while</code>.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_615_67" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> x </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">10</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">2</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="pln">
        x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
        </span><span class="kwd">continue</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">
    x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span></pre>

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

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/artificial-intelligence/%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%88%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1872/" rel="">أنواع البيانات والعمليات الأساسية في لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%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%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1306/" rel="">الحلقات التكرارية في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%A7%D9%84%D8%B4%D8%B1%D8%B7%D9%8A%D8%A9-r1329/" rel="">مقدمة في البرمجة الشرطية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1892</guid><pubDate>Mon, 13 Feb 2023 16:04:00 +0000</pubDate></item><item><title>&#x645;&#x62A;&#x63A;&#x64A;&#x631; &#x627;&#x644;&#x628;&#x64A;&#x626;&#x629; PATH &#x648;&#x627;&#x644;&#x639;&#x645;&#x644; &#x62F;&#x648;&#x646; &#x646;&#x627;&#x641;&#x630;&#x629; &#x633;&#x637;&#x631; &#x627;&#x644;&#x623;&#x648;&#x627;&#x645;&#x631; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D9%85%D8%AA%D8%BA%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D9%8A%D8%A6%D8%A9-path-%D9%88%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D8%AF%D9%88%D9%86-%D9%86%D8%A7%D9%81%D8%B0%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1885/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/1684297565_---PATH-------.png.12b9a9117a874b6f4581b9e81ea86919.png" /></p>
<p>
	تعرفنا في مقال سابق من هذه السلسة على <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D9%81%D9%8A-%D9%86%D8%A7%D9%81%D8%B0%D8%A9-%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-r1884/" rel="">الأوامر الشائعة في نافذة سطر أوامر بايثون</a>، وفيه عرّفنا مفهوم متغيرات البيئة وكيفية عرضها.
</p>

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

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

<h2>
	ما هو متغير البيئة PATH؟
</h2>

<p>
	عند كتابة أمر ما مثل الأمر <code>python</code> في نظام التشغيل ويندوز أو الأمر <code>python3</code> في نظامي التشغيل ماك أو إس ولينكس، تتحقق نافذة موجه الأوامر من وجود برنامج بذلك الاسم في المجلد الحالي. وإن لم تجده هناك، فستبحث في المجلدات المذكورة في متغير البيئة PATH.
</p>

<p>
	كمثال على ذلك، يوجد البرنامج python.exe على حاسوب يعمل بنظام تشغيل ويندوز في مجلد C:\Users\Al\AppData\Local\Programs\Python\Python38، ولتشغيله علينا إدخال المسار الآتي كاملًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_11" style=""><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Programs\Python\Python38\python</span><span class="pun">.</span><span class="pln">exe</span></pre>

<p>
	أو الانتقال إلى ذلك المجلد ومن ثم إدخال الأمر <code>python.exe</code>.
</p>

<p>
	إلا أن المسار الطويل هذا يتطلب الكثير من الكتابة، لذا من الممكن إضافة هذا المسار إلى متغير البيئة PATH، وبذلك وبمجرد كتابة الأمر <code>python.exe</code> في أي موقع، سيبحث برنامج <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر الأوامر</a> عن برنامج بنفس الاسم في المجلدات الموجودة في PATH، ما يوفر عليك عناء كتابة المسارات الكاملة للملفات كل مرة.
</p>

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

<p>
	من الممكن عرض قيمة المتغير PATH الحالية باستخدام الأمر <code>path</code>، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_7" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">path
C</span><span class="pun">:</span><span class="pln">\Path</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS\system32</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS\System32\Wbem</span><span class="pun">;</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Microsoft\WindowsApps</span></pre>

<p>
	أما في نظامي التشغيل ماك أو إس و<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس</a>، فيتم الفصل بين أسماء المجلدات باستخدام الفاصلة، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_15" style=""><span class="pln">al@ubuntu</span><span class="pun">:~</span><span class="pln">$ echo $PATH
</span><span class="pun">/</span><span class="pln">home</span><span class="pun">/</span><span class="pln">al</span><span class="pun">/.</span><span class="pln">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">games</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">games</span><span class="pun">:/</span><span class="pln">snap</span><span class="pun">/</span><span class="pln">bin</span></pre>

<p>
	إن ترتيب أسماء المجلدات ضروري، فإن كان لدينا ملفان يحملان الاسم someProgram.exe في المجلدين C:\WINDOWS\system32 و C:\WINDOWS فإن إدخال الأمر someProgram.exe سيشغل البرنامج الموجود في المجلد C:\WINDOWS\system32 لأن هذا المجلد يظهر أولًا ضمن متغير البيئة PATH.
</p>

<p>
	إن لم يكن البرنامج أو الأمر الذي أدخلناه موجودًا في دليل العمل الحالي أو أي من المجلدات المخزنة في المتغير PATH، فعندها ستعرض نافذة سطر الأوامر رسالة خطأ مثلاً command not found أو not recognized as an internal or external command بمعنى أن الأمر غير موجود أو أنه أمر خارجي أو غير معرف، وإن كنت متأكدًا من عدم وجود أي خطأ إملائي، فعليك التأكد من وجود المجلد المتضمن للبرنامج المطلوب ضمن متغير البيئة PATH.
</p>

<h2>
	تغيير متغير البيئة PATH الخاص بسطر الأوامر
</h2>

<p>
	من الممكن تغيير متغير البيئة PATH الخاص بنافذة موجه الأوامر ليتضمن المزيد من المجلدات، وتختلف طريقة إضافة مجلدات إلى المتغير PATH بعض الشيء بين أنظمة التشغيل المختلفة، ففي نظام التشغيل ويندوز يمكن تنفيذ الأمر <code>path</code> لإضافة مجلد جديد إلى قيمة المتغير PATH الحالية، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_17" style=""><span class="lit">1</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">path C</span><span class="pun">:</span><span class="pln">\newFolder</span><span class="pun">;%</span><span class="pln">PATH</span><span class="pun">%</span><span class="pln">

</span><span class="lit">2</span><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">path
C</span><span class="pun">:</span><span class="pln">\newFolder</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Path</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS\system32</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS</span><span class="pun">;</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS\System32\Wbem</span><span class="pun">;</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Microsoft\WindowsApps</span></pre>

<p>
	وبذلك يتوسع المسار %PATH% (المشار له في السطر رقم 1) إلى القيمة الجديدة لمتغير البيئة PATH، عبر إضافة اسم المجلد الجديد مع فاصلة منقوطة إلى بداية القيمة الحالية للمتغير PATH، وبتشغيل الأمر <code>path</code> مجددًا، ستلاحظ القيمة الجديدة للمتغير.
</p>

<p>
	أم في في نظامي التشغيل ماك أو إس ولينكس، فيمكن ضبط متغير البيئة PATH بصيغة مشابهة لعبارة الاسناد التقليدية في <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a>، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_19" style=""><span class="lit">1</span><span class="pln"> al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ PATH</span><span class="pun">=/</span><span class="pln">newFolder</span><span class="pun">:</span><span class="pln">$PATH
</span><span class="lit">2</span><span class="pln"> al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ echo $PATH
</span><span class="pun">/</span><span class="pln">newFolder</span><span class="pun">:/</span><span class="pln">home</span><span class="pun">/</span><span class="pln">al</span><span class="pun">/.</span><span class="pln">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">sbin</span><span class="pun">:/</span><span class="pln">bin</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">games</span><span class="pun">:/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">local</span><span class="pun">/</span><span class="pln">games</span><span class="pun">:/</span><span class="pln">snap</span><span class="pun">/</span><span class="pln">bin</span></pre>

<p>
	وبذلك يتوسع المسار %PATH% (المشار له في السطر رقم 1) إلى القيمة الجديدة لمتغير البيئة PATH، عبر إضافة اسم المجلد الجديد مع فاصلة منقوطة إلى بداية القيمة الحالية للمتغير PATH، وبتشغيل الأمر <code>path</code> مجددًا، ستلاحظ القيمة الجديدة للمتغير.
</p>

<p>
	لكن التغييرات في قيمة المتغير PATH الناتجة عن الطريقتين السابقتين تسري فقط على نافذة موجه الأوامر الحالية، وأي برنامج يتم تشغيله عبرها بعد إجراء التغيير، لكن لدى فتح نافذة موجه أوامر جديدة، فلن تكون هذه التغيرات مطبقة عليها، لذا لإضافة المجلدات بطريقة دائمة، يجب تغيير مجموعة متغيرات البيئة الخاصة <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">بنظام التشغيل</a>.
</p>

<h2>
	إضافة المجلدات بطريقة دائمة إلى المتغير PATH في نظام التشغيل ويندوز
</h2>

<p>
	يحتوي نظام التشغيل ويندوز على مجموعتين من متغيرات البيئة: متغيرات البيئة الخاصة بالنظام (المطبقة على جميع المستخدمين)، ومتغيرات البيئة الخاصة بالمستخدم (والتي تتجاوز متغيرات البيئة الخاصة بالنظام وتطبق فقط على المستخدم الحالي).
</p>

<p>
	ولتعديل هذه المتغيرات، نضغط على قائمة ابدأ ثم نكتب في مربع البحث Edit environment variables for your account، فتفتح نافذة متغيرات البيئة كما هو مبين في الشكل التالي أدناه.
</p>

<p>
	نختار المتغير Path من قائمة متغيرات المستخدم (وليس من قائمة متغيرات النظام) ثم نضغط على تحرير Edit ونضيف اسم مجلد جديد في حقل النص الذي يظهر (نضيف فاصلة منقوطة للفصل بين الأسماء) ثم نضغط موافق OK.
</p>

<p>
	ليس من السهل العمل مع هذه الواجهة، لذا إن لم تكن متمرسًا بتغيير متغيرات البيئة في ويندوز ننصحك بتحميل البرنامج المجاني Rapid Environment Editor من الرابط <a href="https://www.rapidee.com/." ipsnoembed="true" rel="external nofollow">https://www.rapidee.com/.</a>
</p>

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

<p>
	يمكننا تعديل متغير PATH الخاص بالنظام بشكل دائم من موجه الأوامر باستخدام الأمر <code>setx</code>، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_23" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">setx </span><span class="pun">/</span><span class="pln">M PATH </span><span class="str">"C:\newFolder;%PATH%"</span></pre>

<p>
	كما يجب تشغيل موجه الأوامر كمسؤول لتنفيذ الأمر setx.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="117737" href="https://academy.hsoub.com/uploads/monthly_2023_01/2-6.png.e6001893c1bd603a6f24ba6bf8d92cef.png" rel=""><img alt="تشغيل موجه الأوامر كمسؤول لتنفيذ الأمر setx" class="ipsImage ipsImage_thumbnailed" data-fileid="117737" data-ratio="109.60" data-unique="e138hr74d" style="width: 500px; height: auto;" width="500" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-6.thumb.png.8e66ff10b7c935238a331e829c1ce132.png"> </a>
</p>

<p style="text-align: center;">
	نافذة متغيرات البيئة في نظام التشغيل ويندوز.
</p>

<h2>
	إضافة مجلدات بطريقة دائمة إلى متغير المسار PATH في ماك أو إس ولينكس
</h2>

<p>
	لإضافة مجلدات إلى متغير البيئة PATH في جميع نوافذ موجهات الأوامر في نظامي التشغيل ماك أو إس ولينكس، لابد من تعديل الملف النصي ‎.bashrc في المجلد الرئيسي بإضافة السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_26" style=""><span class="pln">export PATH</span><span class="pun">=/</span><span class="pln">newFolder</span><span class="pun">:</span><span class="pln">$PATH</span></pre>

<p>
	يعمل هذا السطر على تعديل المتغير PATH لجميع موجهات الأوامر التي ستشغل مستقبلًا.
</p>

<p>
	أما في إصدار ماك أو إس كاتالينا أو الإصدارات الأحدث، فقد تغير برنامج الصدفة الافتراضي من Bash إلى Z Shell، وبالتالي يجب تعديل الملف النصي ‎.‎zshrc في المجلد الرئيسي بدلًا من الملف النصي ‎.bashrc.
</p>

<h2>
	تشغيل برامج بايثون دون استخدام نافذة سطر الأوامر
</h2>

<p>
	جميعنا في الغالب يعلم كيفية تشغيل البرامج باستخدام المشغل المزود به نظام التشغيل، فمثلًا يحتوي نظام ويندوز على قائمة ابدأ، في حين يحتوي نظام ماك أو إس على Finder و Dock، أما نظام أوبنتو لينكس فيحتوي على Dash، إذ تضيف البرامج نفسها إلى هذه المشغلات فور تثبيتها، كما من الممكن تشغيل البرامج من مستكشف الملفات (مثل File Explorer في ويندوز و Finder في ماك أو إس و Files في أبونتو لينكس) وذلك بالنقر المزدوج على أيقونة البرنامج.
</p>

<p>
	إلا أن هذه الطرق لا تنطبق على برامج <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>، فالنقر المزدوج على ملف ذو اللاحقة ‎.py سيفتح برنامج بايثون ضمن محرر النصوص أو بيئة تطوير متكاملة IDE بدلاً من تشغيله، ولو أردت تشغيل بايثون مباشرة، ستفتح الصدفة التفاعلية فحسب.
</p>

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

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

<h2>
	تشغيل برامج بايثون على نظام التشغيل ويندوز
</h2>

<p>
	يمكن تشغيل برامج بايثون في نظام التشغيل ويندوز بعدة طرق، فبدلًا من فتح نافذة موجه الأوامر، من الممكن الضغط على زري WIN+R في لوحة المفاتيح لفتح نافذة المشغل Run، وفيها نكتب py c:\path\to\yourScript.py كما هو مبين في الشكل التالي، حيث أن البرنامج py.exe مثبت في المسار C:\Windows\py.exe الموجود ضمن متغير البيئة PATH، أما اللاحقة exe. فهي اختيارية عند تشغيل البرامج.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="117738" href="https://academy.hsoub.com/uploads/monthly_2023_01/2-7.png.e416af08ea077beddd3c3b082d0c668b.png" rel=""><img alt="تشغيل برامج بايثون على نظام التشغيل ويندوز" class="ipsImage ipsImage_thumbnailed" data-fileid="117738" data-ratio="59.00" data-unique="ayhj1f5fj" style="width: 400px; height: auto;" width="450" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-7.png.e416af08ea077beddd3c3b082d0c668b.png"> </a>
</p>

<p style="text-align: center;">
	نافذة Run في نظام التشغيل ويندوز
</p>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_31" style=""><span class="lit">@py</span><span class="pun">.</span><span class="pln">exe C</span><span class="pun">:</span><span class="pln">\path\to\yourScript</span><span class="pun">.</span><span class="pln">py </span><span class="pun">%*</span><span class="pln">
</span><span class="lit">@pause</span></pre>

<p>
	مع مراعاة استبدال المسار في الشيفرة السابقة بالمسار المطلق للبرنامج لديك، واحفظ الملف باللاحقة bat. (مثلاً yourScript.bat)، إن رمز @ في بداية كل أمر تمنع عرضه في نافذة موجه الأوامر، ويعمل الرمز *%‎ على توجيه أي وسطاء موجه أوامر مدخلة بعد اسم الملف الدفعي إلى شيفرة بايثون، التي تقرأ بدورها الوسطاء من القائمة sys.argv.
</p>

<p>
	وبذلك سيغنيك هذا الملف الدفعي عن كتابة المسار المطلق الكامل لبرنامج بايثون في كل مرة تريد تشغيله فيها، كما أن الأمر pause@ سيضيف عبارة press any key to continue… إلى نهاية الخرج وذلك لمنع النافذة من الإغلاق بسرعة.
</p>

<p>
	وفي هذا الصدد يُنصح بوضع جميع الملفات الدفعية وملفات py. في مجلد واحد موجود مسبقًا في متغير البيئة PATH كالمجلد الرئيسي ‪C:\Users\<username></username>
</p>

<p>
	وبذلك وبعد إعداد الملف الدفعي يمكنك تشغيل شيفرات بايثون من خلال الضغط على WIN+R وإدخال اسم الملف الدفعي (إدخال لاحقة bat. هو أمر اختياري) والضغط على زر ENTER.
</p>

<h2>
	تشغيل برامج بايثون في نظام التشغيل ماك أو إس
</h2>

<p>
	يمكن إنشاء نص برمجي للصدَفَة في نظام التشغيل ماك أو إس لتشغيل شيفرات بايثون بإنشاء ملف نصي ذو لاحقة command.
</p>

<p>
	لذا سننشئ ملفًا باستخدام أحد محررات النصوص (مثل TextEdit) ونكتب ضمنه التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_33" style=""><span class="com">#!/usr/bin/env bash</span><span class="pln">
python3 </span><span class="pun">/</span><span class="pln">path</span><span class="pun">/</span><span class="pln">to</span><span class="pun">/</span><span class="pln">yourScript</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	نحفظ الملف في المجلد الرئيسي، ومن نافذة موجه الأوامر نجعل شيفرة الصدفة السابقة قابلة للتنفيذ بتشغيل الأمر <code>chmod u+x yourScript.command</code>.
</p>

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

<h2>
	تشغيل برامج بايثون في نظام أوبنتو لينكس
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7529_35" style=""><span class="com">#!/usr/bin/env python3</span></pre>

<p>
	يدعى هذا بسطر shebang دلالةً على الرمز <code>#!</code> الذي يبدأ به، مخبرًا نظام أبونتو بأنه عند تشغيل هذا الملف نريد استخدام python3 في ذلك، ومن ثم نضيف سماحية التنفيذ إلى الملف هذا باستخدام الأمر chmod في نافذة موجه الأوامر، بالشكل:
</p>

<pre class="ipsCode">al@al-VirtualBox:~$ chmod u+x yourScript.py
</pre>

<p>
	والآن متى ما أردت تشغيل شيفرتك المكتوبة في ملف بايثون هذا، يمكنك الضغط على مفاتيح CTR+ALT+T لفتح نافذة موجه أوامر جديدة، حيث ستكون هذه النافذة مضبوطة افتراضيًا على المجلد الرئيسي، لذلك يمكنك إدخال الأمر <code>yourScript.py/.</code> بسهولة لتشغيل البرنامج.
</p>

<p>
	إن الرمز <code>/.</code> ضروري كونه يخبر نظام أبونتو بأن الملف yourScript.py موجود ضمن دليل العمل الحالي (وهو نفسه المجلد الرئيسي في هذه الحالة).
</p>

<h2>
	الخلاصة
</h2>

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

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

<p>
	وتختلف قليلًا خطوات إضافة مجلدات جديدة إلى متغير البيئة PATH باختلاف أنظمة التشغيل.
</p>

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

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

<p>
	ترجمة -وبتصرف- للفصل الثاني "إعداد البيئة وواجهة سطر الأوامر" من كتاب <a href="https://inventwithpython.com/beyond/chapter2.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D9%81%D9%8A-%D9%86%D8%A7%D9%81%D8%B0%D8%A9-%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-r1884/" rel="">الأوامر الشائعة في نافذة سطر أوامر بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">ما هو سطر الأوامر ؟</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%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>
	</li>
</ul>
]]></description><guid isPermaLink="false">1885</guid><pubDate>Fri, 10 Feb 2023 16:07:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x648;&#x627;&#x645;&#x631; &#x627;&#x644;&#x634;&#x627;&#x626;&#x639;&#x629; &#x641;&#x64A; &#x646;&#x627;&#x641;&#x630;&#x629; &#x633;&#x637;&#x631; &#x623;&#x648;&#x627;&#x645;&#x631; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%A7%D9%84%D8%B4%D8%A7%D8%A6%D8%B9%D8%A9-%D9%81%D9%8A-%D9%86%D8%A7%D9%81%D8%B0%D8%A9-%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-r1884/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/1312531549_-------.png.a8d6d14cb2b5ec98f7f293461abf7b28.png" /></p>
<p>
	يعتقد الكثير من المبرمجين المبتدئين أن استخدام واجهة سطر الأوامر أمر معقد، ما يجعله حكرًا على المحترفين، وهو اعتقاد مغلوط، إذ لا بدّ من التعامل مع واجهة سطر الأوامر بدءًا من مرحلة إعداد بيئة بايثون، وصولًا إلى تشغيل مرحلة البرامج.
</p>

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

<p>
	كما يقدّم هذا المقال تعريفًا بمفهوم متغيرات البيئة وكيفية عرضها والتعامل معها.
</p>

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

<h3>
	مطابقة أسماء المجلدات والملفات مع محارف البدل
</h3>

<p>
	تتعامل الكثير من الأوامر مع أسماء المجلدات والملفات كوسطاء، كما تتعامل مع الأسماء المتضمنة محارف بدل مثل <code>*</code> و <code>?</code>، ما يسمح لنا بتحديد عدة ملفات مطابقة، حيث يطابق محرف البدل * كافة الملفات الموافقة للمحارف التي تليه، في حين يطابق المحرف ? أي محرف مفرد مكانه، وندعو العبارات التي تستخدم محارف البدل * و? بالأنماط العامة.
</p>

<p>
	تسمح الأنماط العامة بتحديد أنماط للملفات، فعلى سبيل المثال يمكن تنفيذ الأمر <code>dir</code> أو <code>ls</code> لعرض جميع الملفات والمجلدات في دليل العمل الحالي، لكن إن أردنا عرض ملفات <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> فقط، فنستخدم الأمرين بالشكل <code>dir *.py</code> أو <code>ls *.py</code> بغية عرض الملفات التي تنتهي باللاحقة py. فقط.
</p>

<p>
	فمثلًا النمط العام py.* يعني "أي مجموعة من المحارف المتبوعة بـ py.":
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_9" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">dir </span><span class="pun">*.</span><span class="pln">py
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> drive C </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Windows</span><span class="pln">
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="typ">Serial</span><span class="pln"> </span><span class="typ">Number</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> DFF3</span><span class="pun">-</span><span class="lit">8658</span><span class="pln">
 </span><span class="typ">Directory</span><span class="pln"> of C</span><span class="pun">:</span><span class="pln">\Users\Al
</span><span class="lit">03</span><span class="pun">/</span><span class="lit">24</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">10</span><span class="pun">:</span><span class="lit">45</span><span class="pln"> PM             </span><span class="lit">8</span><span class="pun">,</span><span class="lit">399</span><span class="pln"> conwaygameoflife</span><span class="pun">.</span><span class="pln">py
</span><span class="lit">03</span><span class="pun">/</span><span class="lit">24</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">11</span><span class="pun">:</span><span class="lit">00</span><span class="pln"> PM             </span><span class="lit">7</span><span class="pun">,</span><span class="lit">896</span><span class="pln"> test1</span><span class="pun">.</span><span class="pln">py
</span><span class="lit">10</span><span class="pun">/</span><span class="lit">29</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">08</span><span class="pun">:</span><span class="lit">18</span><span class="pln"> PM            </span><span class="lit">21</span><span class="pun">,</span><span class="lit">254</span><span class="pln"> wizcoin</span><span class="pun">.</span><span class="pln">py
               </span><span class="lit">3</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">       </span><span class="lit">37</span><span class="pun">,</span><span class="lit">549</span><span class="pln"> bytes
               </span><span class="lit">0</span><span class="pln"> </span><span class="typ">Dir</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">  </span><span class="lit">506</span><span class="pun">,</span><span class="lit">300</span><span class="pun">,</span><span class="lit">776</span><span class="pun">,</span><span class="lit">448</span><span class="pln"> bytes free</span></pre>

<p>
	إن النمط العام <code>records201?.txt</code> يعني أي ملف يبدأ بالسلسلة records201 متبوعة بأي محرف متبوعًا بالسلسلة txt.، وهذا ما يوافق بالنتيجة كافة الملفات ابتداءً من records2010.txt وصولًا إلى records2019.txt (مع أي ملفات بأسماء من قبيل records201X.txt)، في حين أن النمط العام <code>record20??.txt</code> يوافق أي ملف بأي محرفين مكان ?? مثل records2021.txt أو records20AB.txt.
</p>

<h3>
	تغيير المجلدات باستخدام الأمر cd
</h3>

<p>
	إن تنفيذ الأمر <code>cd</code> متبوعًا باسم المجلد المستهدف يغير دليل العمل الحالي في الصَدَفَة إلى المجلد المطلوب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_11" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">cd </span><span class="typ">Desktop</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users\Al\Desktop</span><span class="pun">&gt;</span></pre>

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

<p>
	وفي حال كون اسم المجلد يتضمن مسافات، فلابد من تضمينه بين علامتي اقتباس مزدوجة.
</p>

<p>
	ولتغيير دليل العمل الحالي ليكون المجلد الرئيسي للمستخدم، نكتب الأمر <code>cd ~</code> وذلك في نظامي التشغيل ماك أو إس و<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس</a>، أما في نظام ويندوز فنكتب الأمر <code>cd %%USERPROFILE</code>.
</p>

<p>
	وإن رغبت بتغيير محرك الأقراص الحالي أيضًا في ويندوز، فلابد بدايةً من إدخال اسم القرص المطلوب كأمرٍ منفصل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_15" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">d</span><span class="pun">:</span><span class="pln">
D</span><span class="pun">:</span><span class="pln">\&gt;cd </span><span class="typ">BackupFiles</span><span class="pln">
D</span><span class="pun">:</span><span class="pln">\BackupFiles</span><span class="pun">&gt;</span></pre>

<p>
	أما لتغيير دليل العمل ليصبح هو المجلد الأب لدليل العمل الحالي، يكفي استخدام <code>..</code> كاسم للمجلد، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_18" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">cd </span><span class="pun">..</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users</span><span class="pun">&gt;</span></pre>

<h2>
	عرض قائمة بمحتويات مجلد باستخدام الأمرين dir و ls
</h2>

<p>
	يعرض الأمر dir الملفات والمجلدات ضمن دليل العمل الحالي وذلك في <a href="https://academy.hsoub.com/apps/operating-systems/%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84/" rel="">نظام التشغيل</a> ويندوز، ويؤدي الأمر ls نفس المهمة في نظامي التشغيل ماك أو إس ولينكس، كما يمكن عرض محتويات مجلد آخر باستخدام الأمر <code>dir</code> أو <code>ls</code> متبوعًا باسم المجلد الآخر.
</p>

<p>
	يعد كل من رمزي الانتقال <code>l-</code> و <code>a-</code> وسيطًا مساعدًا مفيدًا للأمر <code>ls</code>، الذي يعرض افتراضيًا أسماء الملفات والمجلدات الموجودة فقط، أما لعرض قائمة أكثر تفصيلًا تحتوي على أحجام الملفات وسماحياتها وتاريخ آخر تعديل عليها وغيرها من المعلومات، فنستخدم الوسيط <code>l-</code>.
</p>

<p>
	يعامِل كل من نظامي التشغيل ماك أو إس ولينكس الملفات التي تبدأ بنقطة على أنها ملفات إعدادات، فيبقيانها مخفية عن الأوامر العادية، وهنا من الممكن استخدام الوسيط -a ليعرض الأمر <code>ls</code> جميع الملفات بما فيها المخفية، ولعرض قائمة المعلومات الموسعة والملفات المخفية معًا ندمج وسيطي التحويل كما يلي <code>ls -al</code>، وفيما يلي مثال من نافذة موجه الأوامر في نظام ماك او إس أو لينكس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_20" style=""><span class="pln">al@ubuntu</span><span class="pun">:~</span><span class="pln">$ ls
</span><span class="typ">Desktop</span><span class="pln">    </span><span class="typ">Downloads</span><span class="pln">       mu_code  </span><span class="typ">Pictures</span><span class="pln">  snap     </span><span class="typ">Videos</span><span class="pln">
</span><span class="typ">Documents</span><span class="pln">  examples</span><span class="pun">.</span><span class="pln">desktop  </span><span class="typ">Music</span><span class="pln">    </span><span class="typ">Public</span><span class="pln">    </span><span class="typ">Templates</span><span class="pln">
al@ubuntu</span><span class="pun">:~</span><span class="pln">$ ls </span><span class="pun">-</span><span class="pln">al
total </span><span class="lit">112</span><span class="pln">
drwxr</span><span class="pun">-</span><span class="pln">xr</span><span class="pun">-</span><span class="pln">x </span><span class="lit">18</span><span class="pln"> al   al   </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">4</span><span class="pln"> </span><span class="lit">18</span><span class="pun">:</span><span class="lit">47</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
drwxr</span><span class="pun">-</span><span class="pln">xr</span><span class="pun">-</span><span class="pln">x  </span><span class="lit">3</span><span class="pln"> root root </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">18</span><span class="pun">:</span><span class="lit">11</span><span class="pln"> </span><span class="pun">..</span><span class="pln">
</span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-------</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> al   al   </span><span class="lit">5157</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">2</span><span class="pln"> </span><span class="lit">20</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> </span><span class="pun">.</span><span class="pln">bash_history
</span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> al   al    </span><span class="lit">220</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">18</span><span class="pun">:</span><span class="lit">11</span><span class="pln"> </span><span class="pun">.</span><span class="pln">bash_logout
</span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> al   al   </span><span class="lit">3771</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> </span><span class="lit">18</span><span class="pun">:</span><span class="lit">11</span><span class="pln"> </span><span class="pun">.</span><span class="pln">bashrc
drwx</span><span class="pun">------</span><span class="pln"> </span><span class="lit">17</span><span class="pln"> al   al   </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Jul</span><span class="pln"> </span><span class="lit">30</span><span class="pln"> </span><span class="lit">10</span><span class="pun">:</span><span class="lit">16</span><span class="pln"> </span><span class="pun">.</span><span class="pln">cache
drwx</span><span class="pun">------</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> al   al   </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">19</span><span class="pln"> </span><span class="lit">15</span><span class="pun">:</span><span class="lit">04</span><span class="pln"> </span><span class="pun">.</span><span class="pln">config
drwxr</span><span class="pun">-</span><span class="pln">xr</span><span class="pun">-</span><span class="pln">x  </span><span class="lit">2</span><span class="pln"> al   al   </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">4</span><span class="pln"> </span><span class="lit">17</span><span class="pun">:</span><span class="lit">33</span><span class="pln"> </span><span class="typ">Desktop</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span></pre>

<p>
	يعد الأمر <code>dir</code> في نظام ويندوز نظير الأمر <code>ls -al</code>، وفيما يلي مثال من نافذة موجه الأوامر في نظام ويندوز:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_22" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">dir
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> drive C </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Windows</span><span class="pln">
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="typ">Serial</span><span class="pln"> </span><span class="typ">Number</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> DFF3</span><span class="pun">-</span><span class="lit">8658</span><span class="pln">

 </span><span class="typ">Directory</span><span class="pln"> of C</span><span class="pun">:</span><span class="pln">\Users\Al

</span><span class="lit">06</span><span class="pun">/</span><span class="lit">12</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">05</span><span class="pun">:</span><span class="lit">18</span><span class="pln"> PM    </span><span class="pun">&lt;</span><span class="pln">DIR</span><span class="pun">&gt;</span><span class="pln">          </span><span class="pun">.</span><span class="pln">
</span><span class="lit">06</span><span class="pun">/</span><span class="lit">12</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">05</span><span class="pun">:</span><span class="lit">18</span><span class="pln"> PM    </span><span class="pun">&lt;</span><span class="pln">DIR</span><span class="pun">&gt;</span><span class="pln">          </span><span class="pun">..</span><span class="pln">
</span><span class="lit">12</span><span class="pun">/</span><span class="lit">04</span><span class="pun">/</span><span class="lit">2018</span><span class="pln">  </span><span class="lit">07</span><span class="pun">:</span><span class="lit">16</span><span class="pln"> PM    </span><span class="pun">&lt;</span><span class="pln">DIR</span><span class="pun">&gt;</span><span class="pln">          </span><span class="pun">.</span><span class="pln">android
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
</span><span class="lit">08</span><span class="pun">/</span><span class="lit">31</span><span class="pun">/</span><span class="lit">2018</span><span class="pln">  </span><span class="lit">12</span><span class="pun">:</span><span class="lit">47</span><span class="pln"> AM            </span><span class="lit">14</span><span class="pun">,</span><span class="lit">618</span><span class="pln"> projectz</span><span class="pun">.</span><span class="pln">ipynb
</span><span class="lit">10</span><span class="pun">/</span><span class="lit">29</span><span class="pun">/</span><span class="lit">2014</span><span class="pln">  </span><span class="lit">04</span><span class="pun">:</span><span class="lit">34</span><span class="pln"> PM           </span><span class="lit">121</span><span class="pun">,</span><span class="lit">474</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">jpg</span></pre>

<h3>
	عرض محتويات المجلدات الفرعية باستخدام الأمرين dir /s و find
</h3>

<p>
	بتنفيذ الأمر <code>dir /s</code> في نظام التشغيل ويندوز تعرض المجلدات مع ما تحويه من مجلدات فرعية، فعلى سبيل المثال يعرض الأمر التالي جميع المجلدات التي تنتهي باللاحقة py. في المجلد C:\github\ezgmail مع كافة المجلدات الفرعية ضمنه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_24" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\github\ezgmail</span><span class="pun">&gt;</span><span class="pln">dir </span><span class="pun">/</span><span class="pln">s </span><span class="pun">*.</span><span class="pln">py
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> drive C </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Windows</span><span class="pln">
 </span><span class="typ">Volume</span><span class="pln"> </span><span class="typ">Serial</span><span class="pln"> </span><span class="typ">Number</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> DEE0</span><span class="pun">-</span><span class="lit">8982</span><span class="pln">
 </span><span class="typ">Directory</span><span class="pln"> of C</span><span class="pun">:</span><span class="pln">\github\ezgmail
</span><span class="lit">06</span><span class="pun">/</span><span class="lit">17</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">06</span><span class="pun">:</span><span class="lit">58</span><span class="pln"> AM             </span><span class="lit">1</span><span class="pun">,</span><span class="lit">396</span><span class="pln"> setup</span><span class="pun">.</span><span class="pln">py
               </span><span class="lit">1</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">        </span><span class="lit">1</span><span class="pun">,</span><span class="lit">396</span><span class="pln"> bytes
 </span><span class="typ">Directory</span><span class="pln"> of C</span><span class="pun">:</span><span class="pln">\github\ezgmail\docs
</span><span class="lit">12</span><span class="pun">/</span><span class="lit">07</span><span class="pun">/</span><span class="lit">2018</span><span class="pln">  </span><span class="lit">09</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> PM             </span><span class="lit">5</span><span class="pun">,</span><span class="lit">504</span><span class="pln"> conf</span><span class="pun">.</span><span class="pln">py
               </span><span class="lit">1</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">       </span><span class="lit">5</span><span class="pun">,</span><span class="lit">504</span><span class="pln"> bytes
 </span><span class="typ">Directory</span><span class="pln"> of C</span><span class="pun">:</span><span class="pln">\github\ezgmail\src\ezgmail

</span><span class="lit">06</span><span class="pun">/</span><span class="lit">23</span><span class="pun">/</span><span class="lit">2019</span><span class="pln">  </span><span class="lit">07</span><span class="pun">:</span><span class="lit">45</span><span class="pln"> PM            </span><span class="lit">23</span><span class="pun">,</span><span class="lit">565</span><span class="pln"> __init__</span><span class="pun">.</span><span class="pln">py
</span><span class="lit">12</span><span class="pun">/</span><span class="lit">07</span><span class="pun">/</span><span class="lit">2018</span><span class="pln">  </span><span class="lit">09</span><span class="pun">:</span><span class="lit">43</span><span class="pln"> PM                </span><span class="lit">56</span><span class="pln"> __main__</span><span class="pun">.</span><span class="pln">py
               </span><span class="lit">2</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">       </span><span class="lit">23</span><span class="pun">,</span><span class="lit">621</span><span class="pln"> bytes
     </span><span class="typ">Total</span><span class="pln"> </span><span class="typ">Files</span><span class="pln"> </span><span class="typ">Listed</span><span class="pun">:</span><span class="pln">
               </span><span class="lit">4</span><span class="pln"> </span><span class="typ">File</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">       </span><span class="lit">30</span><span class="pun">,</span><span class="lit">521</span><span class="pln"> bytes
               </span><span class="lit">0</span><span class="pln"> </span><span class="typ">Dir</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">  </span><span class="lit">505</span><span class="pun">,</span><span class="lit">407</span><span class="pun">,</span><span class="lit">283</span><span class="pun">,</span><span class="lit">200</span><span class="pln"> bytes free</span></pre>

<p>
	ويؤدي الأمر <code>find . –name</code> في نظامي ماك أو إس ولينكس الوظيفة ذاتها، كالتالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_26" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> find </span><span class="pun">.</span><span class="pln"> </span><span class="pun">-</span><span class="pln">name </span><span class="str">"*.py"</span><span class="pln">
</span><span class="pun">./</span><span class="pln">someSubFolder</span><span class="pun">/</span><span class="pln">eggs</span><span class="pun">.</span><span class="pln">py
</span><span class="pun">./</span><span class="pln">someSubFolder</span><span class="pun">/</span><span class="pln">bacon</span><span class="pun">.</span><span class="pln">py
</span><span class="pun">./</span><span class="pln">spam</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	وجود النقطة (.) يجعل الأمر <code>find</code> يبحث في دليل العمل الحالي، والخيار <code>name-</code> يجعله يبحث عن جميع أسماء المجلدات والملفات، أما الوسيط <code>py.*</code> ذو محرف البدل فيجعل الأمر <code>find</code> يعرض كافة المجلدات والملفات ذات الأسماء التي تتطابق النمط العام <code>py.*</code>، ومن الجدير بالملاحظة أن الأمر <code>find</code> يتطلب كون أي سلسلة تلي الوسيط<code>name-</code> محصورة بين علامتي اقتباس مزدوجتين.
</p>

<h3>
	نسخ الملفات والمجلدات باستخدام الأمرين copy و cp
</h3>

<p>
	لإنشاء نسخة من ملف أو مجلد في مجلد آخر، نكتب الأمر <code>copy [source file or folder] [destination folder]</code> أو <code>cp [source file or folder] [destination folder]</code> ، وفيما يلي مثال من نافذة موجه الأوامر في نظام لينكس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_28" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ ls
hello</span><span class="pun">.</span><span class="pln">py  someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ cp hello</span><span class="pun">.</span><span class="pln">py someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ cd someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder</span><span class="pun">/</span><span class="pln">someSubFolder$ ls
hello</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	<strong>الأسماء المختصرة للأوامر</strong>: عندما بدأت بتعلم نظام التشغيل لينكس، تفاجأت عندما اكتشفت أن الأمر <code>copy</code> الخاص بويندوز يدعى <code>cp</code> في نظام لينكس، إذ أن الاسم "copy" كان أكثر وضوحًا من "cp"، وفكرت حينها، هل يستحق اختصار محرفين جعل الاسم غامضًا؟ ومع الوقت ومع اكتسابي للمزيد من الخبرة في نوافذ <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر الأوامر</a>، وجدتُ أن الجواب هو نعم بكل تأكيد. ففي حين أننا نقرأ الشيفرة المصدرية أكثر مما نكتبها، فإن استخدام أسماء كاملة وطويلة للمتغيرات والدوال مفيد بالفعل، أما في نافذة سطر الأوامر فإننا نكتب الأوامر أكثر بكثير من قراءتها، وبالتالي في هذه الحالة العكس هو الصحيح، بمعنى أن استخدام أسماء مختصرة أو قصيرة للأوامر يجعل من عبء كتابتها أيسر.
</p>

<h3>
	نقل الملفات والمجلدات باستخدام الأمرين move و mv
</h3>

<p>
	في نظام التشغيل ويندوز، يمكننا نقل ملف أو مجلد من مصدره إلى مجلد وجهة جديد من خلال تنفيذ الأمر <code>move [source file or folder] [destination folder]</code>، وبنفس الطريقة يؤدي الأمر <code>mv [source file or folder] [destination folder]</code> نفس الوظيفة في كل من نظامي التشغيل ماك أو إس ولينكس، فيما يلي مثال من نافذة موجه الأوامر في ويندوز:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_30" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ ls
hello</span><span class="pun">.</span><span class="pln">py  someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ mv hello</span><span class="pun">.</span><span class="pln">py someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ ls
someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ cd someSubFolder</span><span class="pun">/</span><span class="pln">
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder</span><span class="pun">/</span><span class="pln">someSubFolder$ ls
hello</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	إذ تم نقل الملف hello.py من مصدره ‎~/someFolder إلى الوجهة الجديدة ‎~/someFolder/someFolder، ولم يعد ظاهرًا في موقعه الأصلي.
</p>

<h3>
	إعادة تسمية الملفات والمجلدات باستخدام الأمرين ren و mv
</h3>

<p>
	بتنفيذ الأمر<code>ren [file or folder] [new name]</code> نعيد تسمية الملف أو المجلد في نظام ويندوز، وبطريقة مشابهة يتم ذلك في نظامي ماك أو إس ولينكس باستخدام الأمر <code>mv [file or folder] [new name]</code>، ومن الجدير بالملاحظة أنه من الممكن استخدام الامر <code>mv</code> في نظامي ماك أو إس ولينكس لإعادة تسمية الملفات ونقلها أيضًا، ففي حال تم وضع اسم ملف موجود مسبقًا في موقع الوسيط الثاني المخصص للاسم الجديد للملف في حالة الرغبة بإعادة تسميته، فعندها ينقل الأمر <code>mv</code> الملف أو المجلد من مصدره إلى ذلك المجلد، أما في حال وضع اسمًا جديدًا لا يطابق أي من أسماء المجلدات الموجودة أصلًا، عندها يعيد الأمر <code>mv</code> تسمية الملف أو المجلد، وفيما يلي مثال من نافذة موجه الأوامر في نظام التشغيل لينكس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_32" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ ls
hello</span><span class="pun">.</span><span class="pln">py  someSubFolder
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ mv hello</span><span class="pun">.</span><span class="pln">py goodbye</span><span class="pun">.</span><span class="pln">py
al@ubuntu</span><span class="pun">:~/</span><span class="pln">someFolder$ ls
goodbye</span><span class="pun">.</span><span class="pln">py  someSubFolder</span></pre>

<p>
	وبذلك تغير اسم الملف hello.py ليصبح goodbye.py.
</p>

<h3>
	حذف الملفات والمجلدات باستخدام الأمرين del و rm
</h3>

<p>
	لحذف ملف أو مجلد في نظام التشغيل ويندوز ننفذ الأمر<code>del [file or folder]</code>، أما في نظامي التشغيل ماك أو إس ولينكس فننفذ الأمر<code>rm [file]</code> (إذ أن rm هو اختصار لكلمة remove).
</p>

<p>
	ولأمري الحذف السابقين اختلافات بسيطة، إذ أن تنفيذ الأمر <code>del</code> في نظام ويندوز على مجلد ما يؤدي إلى حذف كافة ملفاته دون مجلداته الفرعية، كما أن هذا الأمر لن يحذف المجلد المصدري، ولحذفه بكامل محتوياته بالكامل، استخدام أحد الأمرين <code>rd</code> أو <code>rmdir</code> اللذان سنشرحهما في فقرة "حذف الملفات باستخدام الأمرين <code>rd</code> و<code>rmdir</code>" لاحقًا، وبالتالي فإن تنفيذ الأمر <code>del [folder]</code> لن يحذف أي ملفات داخل المجلدات الفرعية لهذا المجلد المصدري، ولحذفها ننفذ الأمر بالشكل <code>del /s /q [folder]</code>، حيث يضمن الوسيط /s تطبيق الأمر <code>del</code> على المجلدات الفرعية، في حين يمثل الوسيط q/ تأكيدًا للعملية، ويوضح الشكل التالي هذا الفرق.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="117735" href="https://academy.hsoub.com/uploads/monthly_2023_01/2-4.png.cb4656bfb386dcbb93abf320fd386265.png" rel=""><img alt="حذف الملفات والمجلدات باستخدام الأمر del" class="ipsImage ipsImage_thumbnailed" data-fileid="117735" data-ratio="81.78" data-unique="2btx16vh2" style="width: 450px; height: auto;" width="500" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-4.png.cb4656bfb386dcbb93abf320fd386265.png"> </a>
</p>

<p>
	القسم الأيسر يبين كيفية حذف الملفات في حال تنفيذ الأمر<code>del delicious</code>، أما القسم الأيمن لحالة تنفيذ الأمر بالشكل <code>del /s /q delicious</code>
</p>

<p>
	من غير الممكن استخدام الأمر <code>rm</code> في نظامي التشغيل ماك أو إس ولينكس لحذف المجلدات وحده، لكن من الممكن استخدامه بالشكل <code>rm -r [folder]</code> لحذف المجلد بجميع محتوياته، وينفذ الأمر <code>rd /s /q [folder]</code> في نظام التشغيل ويندوز المهمة ذاتها، ويوضح الشكل التالي هذه الفكرة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="117736" href="https://academy.hsoub.com/uploads/monthly_2023_01/2-5.png.30eea1cce203884df0dd38d08ca0b773.png" rel=""><img alt="حذف الملفات والمجلدات باستخدام الأمر rm" class="ipsImage ipsImage_thumbnailed" data-fileid="117736" data-ratio="161.60" data-unique="12z1o00of" style="width: 250px; height: auto;" width="200" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-5.png.30eea1cce203884df0dd38d08ca0b773.png"> </a>
</p>

<p>
	يتم حذف المجلد بكامل محتوياته عند تنفيذ الأمر rd /s /q delicious أو rm -r delicious.
</p>

<h3>
	إنشاء المجلدات باستخدام الأمرين md و mkdir
</h3>

<p>
	من الممكن إنشاء مجلد جديد فارغ في نظام التشغيل ويندوز بتنفيذ الأمر <code>md [new folder]</code>، أما في نظامي ماك أو إس ولينكس فيتم ذلك باستخدام الأمر <code>mkdir [folder]</code>، كما يعمل الأمر <code>mkdir</code> أيضًا في نظام ويندوز، إلا ان الأمر <code>md</code> أسهل في الكتابة، وفيما يلي مثال من نافذة موجه الأوامر في لينكس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_39" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> mkdir yourScripts
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> cd yourScripts
</span><span class="lit">1</span><span class="pln"> al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop</span><span class="pun">/</span><span class="pln">yourScripts$ ls
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop</span><span class="pun">/</span><span class="pln">yourScripts$</span></pre>

<p>
	نلاحظ أن الملف الجديد الذي تم إنشاؤه فارغ وبالتالي لا يظهر أي شيء لدى تنفيذ أمر عرض المحتويات <code>ls</code> (السطر المشار له بالرقم 1).
</p>

<h3>
	حذف المجلدات باستخدام الأمرين rd و rmdir
</h3>

<p>
	في نظام ويندوز، وبتنفيذ الأمر <code>rd [source folder]</code> يتم حذف المجلد المصدري، ولإنجاز نفس المهمة في نظامي التشغيل ماك أو إس ولينكس، نستخدم الأمر <code>rmdir [source folder]</code>.
</p>

<p>
	مع ملاحظة أن الأمر <code>rmdir</code> يؤدي أيضًا نفس الوظيفة في نظام ويندوز، إلا أن <code>rd</code> أسهل للكتابة، ولابد من كون المجلد فارغًا لنتمكن من حذفه، وفيما يلي مثال من نافذة موجه الأوامر في نظام التشغيل ويندوز:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_41" style=""><span class="pln">al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> mkdir yourScripts
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> ls
yourScripts
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> rmdir yourScripts
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span><span class="pln"> ls
al@ubuntu</span><span class="pun">:~/</span><span class="typ">Desktop$</span></pre>

<p>
	أنشأنا في المثال السابق مجلدًا فارغًا باسم yourScript، ومن ثم حذفناه.
</p>

<p>
	أما لحذف المجلدات غير الفارغة (مع كل ما تتضمنه من ملفات ومجلدات)، فننفذ الأمر <code>rd /s /q [source folder]</code> في نظام التشغيل ويندوز، أو الأمر <code>rm -rf [source folder]</code> في نظامي التشغيل ماك أو إس ولينكس.
</p>

<h3>
	إيجاد البرامج باستخدام الأمرين where و which
</h3>

<p>
	بتنفيذ الأمر <code>where [program]</code> في نظام التشغيل ويندوز أو الأمر <code>which [program]</code> في نظامي ماك أو إس ولينكس نتبين الموقع المحدد للبرنامج، فعندما ندخل أمرًا في نافذة سطر الأوامر، يبدأ الحاسوب بالبحث عن البرنامج في المجلدات الموجودة في متغير البيئة PATH (رغم أن نظام ويندوز يبحث أولًا في دليل العمل الحالي).
</p>

<p>
	إذ تبين لنا هذه الأوامر أي من برامج بايثون التنفيذية سيتم تشغيلها لدى استخدام الأمر <code>pythin</code> في الصَدَفَة، ففي حال وجود عدة إصدارات من بايثون مثبتة على الجهاز، فسيتضمن بالنتيجة عدة برامج تنفيذية وبنفس الاسم، وستكون أفضلية التشغيل حسب ترتيبها في متغير البيئة PATH، وهنا يأتي دور الأمرين where و when لعرضه، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_44" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">where python
C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Programs\Python\Python38\python</span><span class="pun">.</span><span class="pln">exe</span></pre>

<p>
	يشير اسم المجلد في المثال السابق إلى أن نسخة برنامج بايثون التي تعمل من الصدفة موجودة في المسار الآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_46" style=""><span class="pln"> C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Programs\Python\Python38</span></pre>

<h3>
	تنظيف نافذة موجه الأوامر باستخدام الأمرين cls و clear
</h3>

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

<h2>
	متغيرات البيئة ومتغير المسار PATH
</h2>

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

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

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

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

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

<h2>
	عرض متغيرات البيئة
</h2>

<p>
	من الممكن عرض قائمة بمتغيرات البيئة الخاصة بنافذة موجه الأوامر باستخدام الأمر <code>set</code> (في نظام التشغيل ويندوز) أو الأمر <code>env</code> (في نظامي التشغيل ماك أو إي ولينكس)، كما في المثال:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_49" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">set
ALLUSERSPROFILE</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\ProgramData
APPDATA</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Roaming
</span><span class="typ">CommonProgramFiles</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Program </span><span class="typ">Files</span><span class="pln">\Common </span><span class="typ">Files</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span><span class="pln">
USERPROFILE</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al
VBOX_MSI_INSTALL_PATH</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\Program </span><span class="typ">Files</span><span class="pln">\Oracle\VirtualBox\
windir</span><span class="pun">=</span><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS</span></pre>

<p>
	إن النص على يسار إشارة المساواة (=) هو اسم متغير البيئة والنص على يمينها هو قيمة السلسلة التي يتضمنها، ولكل عملية مجموعتها الخاصة من متغيرات البيئة لذلك يمكن <a href="https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%85%D9%86-%D8%B7%D8%B1%D9%81-%D8%A7%D9%84%D8%B9%D9%85%D9%8A%D9%84-r1471/" rel="">لسطر الأوامر</a> المختلفة أن تمتلك قيمًا مختلفة لمتغيرات البيئة نفسها.
</p>

<p>
	كما من الممكن عرض قيمة متغير بيئة بحد ذاته باستخدام الأمر <code>echo</code>، فمثلًا بتنفيذ الأمر <code>echo %HOMEPATH%</code> في نظام التشغيل ويندوز أو الأمر <code>echo $HOME</code> في نظامي التشغيل ماك أو إس ولينكس، تُعرض قيمة متغيرات البيئة HOMEPATH أو HOME على التوالي، والتي تحتوي على المجلد الرئيسي الحالي للمستخدم، ويبدو الأمر كالتالي في نظام التشغيل ويندوز:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_51" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">echo </span><span class="pun">%</span><span class="pln">HOMEPATH</span><span class="pun">%</span><span class="pln">
\Users\Al</span></pre>

<p>
	أما في نظامي التشغيل ماك أو إس ولينكس، فيبدو بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6041_53" style=""><span class="pln">al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ echo $HOME
</span><span class="pun">/</span><span class="pln">home</span><span class="pun">/</span><span class="pln">al</span></pre>

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

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

<h2>
	الخلاصة
</h2>

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

<p>
	ورغم اختلاف موجه الأوامر وأسماء الأوامر الشائعة باختلاف أنظمة التشغيل، إلا أنها تؤدي بالنتيجة المهام ذاتها.
</p>

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

<p>
	ترجمة -وبتصرف- للفصل الثاني "إعداد البيئة وواجهة سطر الأوامر" من كتاب <a href="https://inventwithpython.com/beyond/chapter2.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A6%D8%A9-%D9%88%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1859/" rel="">إعداد البيئة وواجهة سطر الأوامر في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/%D8%AF%D9%84%D9%8A%D9%84-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%B9%D9%85%D9%84%D9%8A%D8%A9-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D9%85%D9%86-%D8%B7%D8%B1%D9%81-%D8%A7%D9%84%D8%B9%D9%85%D9%8A%D9%84-r1471/" 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/programming/python/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%85%D8%AA%D8%BA%D9%8A%D8%B1%D8%A7%D8%AA-%D9%88%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9%D9%87%D8%A7-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r221/" rel="">تعرف على المتغيرات وكيفية التعامل معها في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1884</guid><pubDate>Mon, 06 Feb 2023 16:08:00 +0000</pubDate></item><item><title>&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x627;&#x644;&#x628;&#x64A;&#x626;&#x629; &#x648;&#x648;&#x627;&#x62C;&#x647;&#x629; &#x633;&#x637;&#x631; &#x627;&#x644;&#x623;&#x648;&#x627;&#x645;&#x631; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%A8%D9%8A%D8%A6%D8%A9-%D9%88%D9%88%D8%A7%D8%AC%D9%87%D8%A9-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1859/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/142484426_-------.png.613d53b5cf580d5cfa8bba83fa44a4ca.png" /></p>
<p>
	مع نهاية <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1858/" rel="">المقال السابق</a> من هذه السلسلة حول كيفية التعامل مع الملفات والمسارات في <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>، يجب أن تكون قد بنيت تصورًا حول نظام الملفات وبالتالي كيفية التعامل مع المسارات في بايثون، الأمر الضروري لمساعدتك في إدارة حاسوبك للمضي في إعداد البيئة البرمجية وفهم واجهة <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر الأوامر</a> والتعامل معها.
</p>

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

<p>
	هناك أنواع كثيرة من الحواسيب <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">بأنظمة تشغيل</a> مختلفة ذات إصدارات متنوعة، وتحتوي هذه الحواسيب أيضًا على إصدارات مختلفة من مفسر أوامر بايثون، وبالتالي لا يوجد عملية إعداد موحدة للجميع.
</p>

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

<h2>
	سطر الأوامر
</h2>

<p>
	تعد نافذة سطر الأوامر Command line برنامجًا معتمدًا على النصوص، يسمح بإدخال الأوامر بغية التفاعل مع نظام التشغيل وتنفيذ البرامج، كما تُعرف هذه النافذة أيضًا باسم واجهة سطر الأوامر command line interface CLI أو موجه الأوامر command prompt أو نافذة موجه الأوامر (الوجهة النهائية للصَدَفة) terminal أو الصدفة shell أو وحدة التحكم console.
</p>

<p>
	بغض النظر عن التسمية، تؤمن نافذة سطر الأوامر بديلًا عن <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D8%AE%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%A8%D9%86%D8%A7%D8%A1-%D8%A7%D9%84%D9%88%D8%A7%D8%AC%D9%87%D8%A7%D8%AA-%D8%A7%D9%84%D8%B1%D8%B3%D9%88%D9%85%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1771/" rel="">واجهة المستخدم الرسومية GUI</a>، التي تتيح للمستخدم التفاعل مع الحاسوب بطريقة بصرية تتعدى حدود الواجهة النصية، إذ تعرض واجهة المستخدم الرسومية معلومات مرئية للمستخدم موجهةً إياه خلال تنفيذه للمهام بطريقة أسهل من تلك التي توفرها نافذة سطر الأوامر.
</p>

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

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

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

<p>
	ويوجد برنامج سطر الأوامر ضمن ملف تنفيذي في الحاسوب، ولهذا السبب عادةً ما ندعوه بالصدفة أو برنامج الصدفة، فبتشغيل برنامج الصدفة تظهر الوجهة النهائية المطلوبة من داخلها terminal وهي نافذة موجه الأوامر:
</p>

<ul>
	<li>
		يقع برنامج الصدفة في نظام تشغيل ويندوز ضمن المسار: C:\Windows\System32\cmd.exe
	</li>
	<li>
		يقع برنامج الصدفة في نظام تشغيل ماك أو إس ضمن المسار ‎/bin/bash.
	</li>
	<li>
		يقع برنامج الصدفة في نظام تشغيل أوبنتو لينكس ضمن المسار ‎/bin/bash.
	</li>
</ul>

<p>
	ابتكر المبرمجون على مدى الأعوام العديد من برامج الصَدَفة <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لنظام التشغيل لينكس</a> مثل Bourne Shell (الذي يقع ضمن ملف تنفيذي يدعى sh)، ومن ثم برنامجًا يدعى Bourne Again Shell (الذي يقع ضمن ملف تنفيذي يدعى <a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%B5%D8%AF%D9%81%D8%A9-%D8%A8%D8%A7%D8%B4-bash-r606/" rel="">Bash</a>).
</p>

<p>
	في حين يستخدم نظام التشغيل لينكس برنامج باش Bash افتراضيًا، أما نظام ماك أو إس فيستخدم شبيه باش وهو برنامج Zsh، أو Z shell في الإصدار كاتالينا والإصدارات الأحدث.
</p>

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

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

<h2>
	فتح نافذة موجه الأوامر
</h2>

<p>
	لفتح نافذة موجه الأوامر نقوم بما يلي:
</p>

<ul>
	<li>
		في نظام التشغيل ويندوز، نضغط على زر ابدأ ونكتب <code>Command Prompt</code> أو <code>cmd</code> ونضغط زر ENTER.
	</li>
	<li>
		في نظام التشغيل ماك أو إس، نضغط على أيقونة Spotlight في الزاوية العلوية اليمنى ونكتب <code>Terminal</code> ثم نضغط زر ENTER.
	</li>
	<li>
		في نظام التشغيل أوبنتو لينكس، نضغط زر WIN لتظهر لنا نافذة Dash، وفيها نكتب <code>Terminal</code> ونضغط زر ENTER، أو مباشرةً من خلال لوحة المفاتيح بالضغط على الاختصار CTRL+ALT+T.
	</li>
</ul>

<p>
	وبشكل مشابه للصدفة التفاعلية التي تعرض نافذة سطر أوامر ذات رمز انتظار الأوامر <code>&lt;&lt;&lt;</code>، فإن نافذة موجه الأوامر terminal تعرض نافذة سطر أوامر خاصة بالصَدَفَة shell prompt حيث يمكنك كتابة الأوامر.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_15" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;هنا</span><span class="pln"> </span><span class="pun">نكتب</span><span class="pln"> </span><span class="pun">الأوامر</span></pre>

<p>
	أما في نظام التشغيل ماك أو إس، فيظهر موجه الأوامر مع رمز انتظار أوامر مكون من اسم الحاسوب متبوعًا بعلامة النقطتين الرأسيتين ثم اسم دليل العمل الحالي، مع التعبير عن المجلد الرئيسي بعلامة (~) يليها اسم المستخدم متبوعًا بإشارة ($)، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_17" style=""><span class="typ">Als</span><span class="pun">-</span><span class="typ">MacBook</span><span class="pun">-</span><span class="typ">Pro</span><span class="pun">:~</span><span class="pln"> al$ </span><span class="pun">هنا</span><span class="pln"> </span><span class="pun">نكتب</span><span class="pln"> </span><span class="pun">الأوامر</span></pre>

<p>
	ويكون رمز انتظار التعليمات في موجه الأوامر الخاص بنظام التشغيل أبونتو لينكس مشابهًا لذلك الموجود في نظام ماك أو إس، باستثناء أن الأول يبدأ باسم المستخدم مع الرمز (@)، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_19" style=""><span class="pln">al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ </span><span class="pun">هنا</span><span class="pln"> </span><span class="pun">نكتب</span><span class="pln"> </span><span class="pun">الأوامر</span></pre>

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

<h2>
	تشغيل البرامج باستخدام نافذة سطر الأوامر
</h2>

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

<ul>
	<li>
		في نظام التشغيل ويندوز نكتب <code>calc.exe</code>.
	</li>
	<li>
		في نظام التشغيل ماك أو إس نكتب <code>open -a Calculator</code> (يُشغّل هذا الأمر في البداية برنامج فتح الملفات والمجلدات open الذي بدوره يشغل برنامج الآلة الحاسبة).
	</li>
	<li>
		في نظام التشغيل لينكس نكتب <code>gnome-calculator</code>.
	</li>
</ul>

<p>
	ومن الجدير بالذكر أن أسماء البرامج والأوامر حساسة لحالة الأحرف فقط في نظام التشغيل لينكس، ما يعني أنه يجب كتابة gnome-calculator حرفيًا في نظام التشغيل لينكس، لكن يمكنك كتابة Calc.exe في نظام التشغيل ويندوز أو OPEN -a Calculator في نظام التشغيل ماك أو إس ولن يؤثر ذلك على النتيجة.
</p>

<p>
	إن إدخال أسماء برنامج الآلة الحاسبة إلى نوافذ سطر الأوامر مشابه تمامًا لتشغيلها من قائمة ابدأ أو Finder أو Dash، إذ تعمل أسماء برنامج الآلة الحاسبة هذه كأوامر، لأن كل من البرامج calc.exe و open و gnom-calculator موجودة في مجلدات مضمنة في متغيرات البيئة الخاصة بالمسارات <code>PATH</code>.
</p>

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

<p>
	إن لم يكن البرنامج موجودًا في مجلد ضمن المتغير PATH، فعندها نحن أمام خياران:
</p>

<ul>
	<li>
		إما أن نستخدم الأمر <code>cd</code> لتغيير دليل العمل الحالي ليصبح هو المجلد الذي يحتوي على ذلك البرنامج، ثم ندخل اسمه، فيمكننا على سبيل المثال إدخال الأمرين التاليين:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_21" style=""><span class="pln">cd C</span><span class="pun">:</span><span class="pln">\Windows\System32
calc</span><span class="pun">.</span><span class="pln">exe</span></pre>

<ul>
	<li>
		أو أن نُدخل المسار الكامل للملف التنفيذي للبرنامج، فعلى سبيل المثال يمكن أن نُدخل الأمر <code>C:\Windows\System32\calc.exe</code> بدلًا من إدخال <code>calc.exe</code>.
	</li>
</ul>

<p>
	إن كان البرنامج في نظام التشغيل ويندوز ينتهي باللاحقة exe. أو bat. فإن كتابة اللاحقة ضمن الأمر هو شيء اختياري، إذ أن كتابة <code>calc</code> وحدها تؤدي نفس النتيجة لدى كتابة <code>calc.exe</code>، في حين لا تمتلك الملفات التنفيذية في نظامي التشغيل ماك أو إس ولينكس على لاحقة تميزها إلا أنها تمتلك مجموعة السماحيات التنفيذية اللازمة.
</p>

<h2>
	استخدام وسطاء نافذة سطر الأوامر
</h2>

<p>
	وسطاء نافذة سطر الأوامر هي عبارة عن أجزاء نصية توضع بعد اسم الأمر، وهي شبيهة بتلك التي نمررها إلى دوال بايثون من حيث أنها تزود الأمر بخيارات محددة أو وجهات إضافية، فعند تنفيذ الأمر <code>cd C:\Users</code> مثلًا، فإن الجزء <code>C:\Users</code> عبارة عن وسيط للأمر <code>cd</code> يبين له المجلد المطلوب تغيير دليل العمل الحالي إليه، أو مثلًا لدى تشغيل شيفرة بايثون من نافذة موجه الأوامر باستخدام الأمر <code>python yourScript.py</code>، فإن الجزء <code>yourScript.py</code> يعد وسيطًا، يبين لبرنامج بايثون الملف المطلوب البحث فيه عن التعليمات المراد تنفيذها.
</p>

<p>
	إن خيارات نافذة سطر الأوامر (والمسماة أيضًا الأعلام flags أو رموز الانتقال switches أو ببساطة الخيارات) هي عبارة عن وسطاء، تتكون عادةً من حرف واحد أو كلمة قصيرة.
</p>

<p>
	تبدأ خيارات سطر الأوامر في نظام التشغيل ويندوز عادة بالخط المائل الأمامي (/)، بينما في كل من نظامي التشغيل ماك أو إس ولينكس فتبدأ بشرطة علوية مفردة (-) أو مزدوجة (--).
</p>

<p>
	وكما تلاحظ فإننا قد استخدمنا الخيار <code>a-</code> لتشغيل الأمر <code>open -a Calculator</code> في نظام التشغيل ماك أو إس، ومن الجدير بالذكر أن خيارات نافذة سطر الأوامر في كلا نظامي التشغيل ماك أو إس ولينكس حساسة لحالة الأحرف، على خلاف نظام التشغيل ويندوز، ومن الممكن الفصل ما بين عدة خيارات في نافذة سطر الأوامر باستخدام المسافات spaces.
</p>

<p>
	تعد أسماء الملفات والمجلدات أيضًا وسطاء شائعة في واجهة سطر الأوامر، وفي حال كون اسم المجلد أو الملف متضمنًا لمسافات، فعندها يجب حصره ضمن علامة اقتباس مزدوجة لتجنب حدوث أخطاء في نافذة سطر الأوامر، على سبيل المثال إن أردنا تغيير دليل العمل إلى مجلد يدعى <code>Vacation Photos</code> من خلال إدخال الأمر <code>cd Vacation Photos</code>، سيظن برنامج سطر الأوامر بأننا قد أدخلنا وسيطين هما <code>Vacation</code> و <code>Photos</code>؛ وعلى هذا الأساس بالذات سوف ندخل الأمر على النحو الموالي:  ‪<code>cd "Vacation Photos"</code>
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_23" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">cd </span><span class="str">"Vacation Photos"</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users\Al\Vacation </span><span class="typ">Photos</span><span class="pun">&gt;</span></pre>

<p>
	كما يعد الوسيط <code>help--</code> شائعًا جدًا للعديد من الأوامر في نظامي ماك أو إس ولينكس، يقابله الوسيط في نظام ويندوز، ويعد هذا الوسيط مسؤولًا عن توفير المعلومات المتعلقة بالأمر المحدد، فمثلًا في حال تشغيل الأمر <code>?/</code> في نظام ويندوز، فستعرض الصَدَفَة معلومات حول الأمر <code>cd</code> متضمنةً وظيفته مع قائمة بكافة الوسطاء التي تعمل معه، بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_25" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">cd </span><span class="pun">/?</span><span class="pln">
</span><span class="typ">Displays</span><span class="pln"> the name of </span><span class="kwd">or</span><span class="pln"> changes the current directory</span><span class="pun">.</span><span class="pln">
CHDIR </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">drive</span><span class="pun">:][</span><span class="pln">path</span><span class="pun">]</span><span class="pln">
CHDIR </span><span class="pun">[..]</span><span class="pln">
CD </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">drive</span><span class="pun">:][</span><span class="pln">path</span><span class="pun">]</span><span class="pln">
CD </span><span class="pun">[..]</span><span class="pln">
  </span><span class="pun">..</span><span class="pln">   </span><span class="typ">Specifies</span><span class="pln"> that you want to change to the parent directory</span><span class="pun">.</span><span class="pln">

</span><span class="typ">Type</span><span class="pln"> CD drive</span><span class="pun">:</span><span class="pln"> to display the current directory </span><span class="kwd">in</span><span class="pln"> the specified drive</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Type</span><span class="pln"> CD without parameters to display the current drive </span><span class="kwd">and</span><span class="pln"> directory</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Use</span><span class="pln"> the </span><span class="pun">/</span><span class="pln">D switch to change current drive </span><span class="kwd">in</span><span class="pln"> addition to changing current
directory </span><span class="kwd">for</span><span class="pln"> a drive</span><span class="pun">.</span><span class="pln">
</span><span class="pun">--</span><span class="pln">snip</span><span class="pun">--</span></pre>

<p>
	تشير معلومات المساعدة هذه إلى أن الأمر <code>cd</code> الخاص بنظام ويندوز يدعى أيضًا <code>chdir</code>. (لا يستخدم معظم الأشخاص الأمر chdir بما أن الأمر <code>cd</code> مختصر ويؤدي نفس الغرض تمامًا)، وتتضمن الأقواس المتوسطة على الوسطاء الإضافية الاختيارية، فعلى سبيل المثال يشير <code>CD [/D] [drive:][path]</code> إلى أنه يمكننا تحديد محرك أقراص أو مسار باستخدام الخيار<code> D/</code>.
</p>

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

<h2>
	تشغيل شفيرة بايثون من نافذة سطر الأوامر باستخدام الأمر c-
</h2>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_27" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">python </span><span class="pun">-</span><span class="pln">c </span><span class="str">"print('Hello, world')"</span><span class="pln">
</span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> world</span></pre>

<p>
	إن رمز الانتقال <code>c-</code> مفيد لرؤية ناتج تنفيذ تعليمة بايثون واحدة دون الحاجة لفتح الصَدَفَة التفاعلية، فمثلًا من الممكن عرض خرج الدالة <code>()help</code> بسرعة والعودة بعدها مباشرةً للمتابعة في سطر الأوامر، بالشكل:
</p>

<pre class="ipsCode" id="ips_uid_2944_7">C:\Users\Al&gt;python -c "help(len)"
Help on built-in function len in module builtins:
len(obj, /)
    Return the number of items in a container.
C:\Users\Al&gt;</pre>

<h2>
	تشغيل برامج بايثون من سطر الأوامر
</h2>

<p>
	إن برامج بايثون عبارة عن ملفات نصية ذات اللاحقة (py.)، وهي ليست ملفات تنفيذية، بل إن مفسرات لغة بايثون تقرأها وتنفذ تعليمات بايثون الموجودة ضمنها.
</p>

<p>
	في حين أن للمفسر ملف تنفيذي وهو <code>python.exe</code> في نظام ويندوز، و python3 في أنظمة ماك أو إس ولينكس (كما أن ملف بايثون الأساسي يتضمن مفسر الإصدار الثاني من بايثون). وبتشغيل الأوامر <code>python yourScript.py</code> أو <code>python3 yourScript.py</code> سيتم تشغيل تعليمات بايثون المحفوظة في الملف المسمى <code>yourScript.py</code>.
</p>

<h2>
	تشغيل البرنامج py.exe
</h2>

<p>
	يثبت بايثون البرنامج py.exe ضمن المجلد C:\Windows وذلك في نظام التشغيل ويندوز، وهو متطابق مع البرنامج python.exe إلا أن الأخير يتميز بامتلاكه وسيطًا إضافيًا يجعله قادرًا على تشغيل أي من إصدارات بايثون المثبة على حاسوبك، ويمكنك تشغيل الأمر <code>py</code> من أي من المجلدين وذلك لكون المجلد <code>C:\Windows</code> مضمنًا في متغير البيئة PATH.
</p>

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

<p>
	وبعد تحديد الإصدار من الممكن تمرير وسطاء سطر الأوامر بنفس الطريقة سواءً باستخدام البرنامج py.exe أو python.exe.
</p>

<p>
	لنشغل الآن الأوامر التالية باستخدام نافذة سطر الأوامر في ويندوز:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_31" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">py </span><span class="pun">-</span><span class="lit">3.6</span><span class="pln"> </span><span class="pun">-</span><span class="pln">c </span><span class="str">"import sys;print(sys.version)"</span><span class="pln">
</span><span class="lit">3.6</span><span class="pun">.</span><span class="lit">6</span><span class="pln"> </span><span class="pun">(</span><span class="pln">v3</span><span class="pun">.</span><span class="lit">6.6</span><span class="pun">:</span><span class="lit">4cf1f54eb7</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Jun</span><span class="pln"> </span><span class="lit">27</span><span class="pln"> </span><span class="lit">2018</span><span class="pun">,</span><span class="pln"> </span><span class="lit">03</span><span class="pun">:</span><span class="lit">37</span><span class="pun">:</span><span class="lit">03</span><span class="pun">)</span><span class="pln"> </span><span class="pun">[</span><span class="pln">MSC v</span><span class="pun">.</span><span class="lit">1900</span><span class="pln"> </span><span class="lit">64</span><span class="pln"> bit </span><span class="pun">(</span><span class="pln">AMD64</span><span class="pun">)]</span><span class="pln">
C</span><span class="pun">:</span><span class="pln">\Users\Al</span><span class="pun">&gt;</span><span class="pln">py </span><span class="pun">-</span><span class="lit">2.7</span><span class="pln">
</span><span class="typ">Python</span><span class="pln"> </span><span class="lit">2.7</span><span class="pun">.</span><span class="lit">14</span><span class="pln"> </span><span class="pun">(</span><span class="pln">v2</span><span class="pun">.</span><span class="lit">7.14</span><span class="pun">:</span><span class="lit">84471935ed</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Sep</span><span class="pln"> </span><span class="lit">16</span><span class="pln"> </span><span class="lit">2017</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">:</span><span class="lit">25</span><span class="pun">:</span><span class="lit">58</span><span class="pun">)</span><span class="pln"> </span><span class="pun">[</span><span class="pln">MSC v</span><span class="pun">.</span><span class="lit">1500</span><span class="pln"> </span><span class="lit">64</span><span class="pln"> bit </span><span class="pun">(</span><span class="pln">AMD64</span><span class="pun">)]</span><span class="pln"> on win32
</span><span class="typ">Type</span><span class="pln"> </span><span class="str">"help"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"copyright"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"credits"</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> </span><span class="str">"license"</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> more information</span><span class="pun">.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span></pre>

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

<h2>
	تشغيل الأوامر من برنامج بايثون
</h2>

<p>
	إن دالة بايثون <code>()subprocess.run</code> الموجودة في الوحدة <code>subprocess</code> قادرة على تشغيل أوامر الصدفة ضمن برامج بايثون، لتعرض خرج هذه الأوامر كسلاسل نصية، فعلى سبيل المثال تشغل الشيفرة التالية الأمر <code>ls -al</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_33" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> subprocess</span><span class="pun">,</span><span class="pln"> locale
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> procObj </span><span class="pun">=</span><span class="pln"> subprocess</span><span class="pun">.</span><span class="pln">run</span><span class="pun">([</span><span class="str">'ls'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'-al'</span><span class="pun">],</span><span class="pln"> stdout</span><span class="pun">=</span><span class="pln">subprocess</span><span class="pun">.</span><span class="pln">PIPE</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> outputStr </span><span class="pun">=</span><span class="pln"> procObj</span><span class="pun">.</span><span class="pln">stdout</span><span class="pun">.</span><span class="pln">decode</span><span class="pun">(</span><span class="pln">locale</span><span class="pun">.</span><span class="pln">getdefaultlocale</span><span class="pun">()[</span><span class="lit">1</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">outputStr</span><span class="pun">)</span><span class="pln">
total </span><span class="lit">8</span><span class="pln">
drwxr</span><span class="pun">-</span><span class="pln">xr</span><span class="pun">-</span><span class="pln">x  </span><span class="lit">2</span><span class="pln"> al al </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">21</span><span class="pun">:</span><span class="lit">37</span><span class="pln"> </span><span class="pun">.</span><span class="pln">
drwxr</span><span class="pun">-</span><span class="pln">xr</span><span class="pun">-</span><span class="pln">x </span><span class="lit">17</span><span class="pln"> al al </span><span class="lit">4096</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">6</span><span class="pln"> </span><span class="lit">21</span><span class="pun">:</span><span class="lit">37</span><span class="pln"> </span><span class="pun">..</span><span class="pln">
</span><span class="pun">-</span><span class="pln">rw</span><span class="pun">-</span><span class="pln">r</span><span class="pun">--</span><span class="pln">r</span><span class="pun">--</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> al al    </span><span class="lit">0</span><span class="pln"> </span><span class="typ">Aug</span><span class="pln">  </span><span class="lit">5</span><span class="pln"> </span><span class="lit">15</span><span class="pun">:</span><span class="lit">59</span><span class="pln"> spam</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	مررنا في الشيفرة السابقة القائمة <code>['ls', '-al']</code> إلى الدالة <code>()subprocess.run</code> (السطر المشار له بالرقم 1)، حيث تحتوي هذه القائمة على الأمر <code>ls</code> متبوعًا بوسطائه، كل منها كسلسلة مستقلة، لأن تمرير السلسلة بالشكل <code>['ls, -al']</code> لن يعمل.
</p>

<p>
	ثم خزّنا خرج الأمر كسلسلة نصية ضمن المتغير <code>outputStr</code> (السطر المشار له بالرقم 2).
</p>

<p>
	وللمزيد من المعلومات حول الدالتين <code>()subprocess.run</code> و <code>()locale.getdefaultlocale</code> القادرتين على جعل شيفرة بايثون تعمل على أي نظام تشغيل، ننصحك بالاطلاع على التوثيقات والمقالات المتوفرة على الإنترنت حولهما.
</p>

<h2>
	تخفيف عبء الكتابة اليدوية باستخدام الإكمال التلقائي
</h2>

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

<p>
	فعلى سبيل المثال عندما نكتب <code>cd c:\u</code> ونضغط على مفتاح Tab في نظام التشغيل ويندوز، فإن هذا الأمر يتحقق من الملفات والمجلدات في المسار <code>\:C</code> التي تبدأ بالحرف u، مكملًا المسار ليصبح <code>c:\Users</code>، كما يصحح حالة الحرف الصغير u ليصبح حرفًا كبيرًا U. (في نظامي التشغيل ماك أو إس ولينكس لا يقوم الاكمال باستخدام زر Tab بتصحيح حالة الحرف من كبير إلى صغير أو بالعكس).
</p>

<p>
	وفي حال وجود عدة ملفات أو مجلدات تبدأ بالحرف U ضمن المجلد <code>\:C</code>، فعندها من الممكن مواصلة الضغط على مفتاح Tab للتنقل فيما بينها وصولًا إلى المطلوب، ولتقليل عدد الخيارات، يمكننا كتابة العبارة <code>cd c:\us</code>، وبالتالي تقل الاحتمالات لتضم فقط الملفات أو المجلدات التي تبدأ بالحرفين us.
</p>

<p>
	والضغط المتكرر هذا على مفتاح Tab يعمل أيضًا في نظامي التشغيل ماك أو إس ولينكس، وفي المثال التالي كتب المستخدم العبارة <code>cd D</code> ثم ضغط مرتين على المفتاح Tab بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3836_35" style=""><span class="pln">al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ cd D
</span><span class="typ">Desktop</span><span class="pun">/</span><span class="pln">   </span><span class="typ">Documents</span><span class="pun">/</span><span class="pln"> </span><span class="typ">Downloads</span><span class="pun">/</span><span class="pln">
al@al</span><span class="pun">-</span><span class="typ">VirtualBox</span><span class="pun">:~</span><span class="pln">$ cd D</span></pre>

<p>
	بالضغط مرتين على مفتاح Tab بعد كتابة الحرف D، ستعرض الصدفة جميع الاحتمالات الممكنة، ومن ثم تعيد كتابة الأمر كما كتبته أنت أصلًا بانتظار قرارك، وهنا يمكنك مثلًا كتابة الحرف e ومن ثم الضغط على المفتاح Tab فتكمل الصدفة الأمر ليصبح <code>/cd Desktop</code>.
</p>

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

<h2>
	عرض الأوامر المخزنة: تاريخ الأوامر
</h2>

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

<p>
	من الممكن عرض تاريخ الأوامر في نظام التشغيل ويندوز بإدخال الأمر <code>doskey /history</code> (إن هذا الاسم الغريب doskey يعود إلى حقبة نظام التشغيل DOS الذي كان يسبق ويندوز)، أما في نظامي ماك أو إس ولينكس، فيمكن عرض تاريخ الأوامر باستخدام الأمر <code>history</code>.
</p>

<h2>
	الخلاصة
</h2>

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

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

<p>
	فرغم اختلاف موجه الأوامر وأسماء الأوامر الشائعة باختلاف أنظمة التشغيل، إلا أنها تؤدي بالنتيجة المهام ذاتها.
</p>

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

<p>
	ترجمة -وبتصرف- للفصل الثاني "إعداد البيئة وواجهة سطر الأوامر" من كتاب <a href="https://inventwithpython.com/beyond/chapter2.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1858/" rel="">التعامل مع الملفات والمسارت في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%ab%d8%a8%d9%8a%d8%aa-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-3-%d9%88%d8%a5%d8%b9%d8%af%d8%a7%d8%af-%d8%a8%d9%8a%d8%a6%d8%aa%d9%87%d8%a7-%d8%a7%d9%84%d8%a8%d8%b1%d9%85%d8%ac%d9%8a%d8%a9-r714/" rel="">تثبيت بايثون 3 وإعداد بيئتها البرمجية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B5%D9%88%D9%84-%D8%B7%D9%84%D8%A8-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-r1857/" rel="">أصول طلب المساعدات البرمجية في بايثون عبر الإنترنت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1859</guid><pubDate>Mon, 30 Jan 2023 16:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x627;&#x644;&#x645;&#x644;&#x641;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x645;&#x633;&#x627;&#x631;&#x627;&#x62A; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B1%D8%A7%D8%AA-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1858/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/1591009416_------.png.9b97332a52d932aebc260fe6f8a16340.png" /></p>
<p>
	بدأنا هذه السلسلة بمقال عن <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%B1%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1856/" rel="">كيفية التعامل مع رسائل الأخطاء في بايثون</a> وسنتابع الحديث في هذا المقال عن كيفية التعامل مع الملفات والمسارات في بايثون. و<a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> هي لغة برمجة عالية المستوى، وتفاعلية وكائنية. وتتمتع بمقروئية عالية، إذ تستخدم كلمات إنجليزية بسيطة، على خلاف اللغات الأخرى التي تستخدم الرموز، كما أنّ قواعدها الإملائية والصياغية بسيطة، ما يجعل تعلمها سهلًا موازنةً <a href="https://academy.hsoub.com/programming/general/%D8%A3%D9%87%D9%85%D9%8A%D8%A9-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D8%A3%D9%87%D9%85-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1854/" rel="">بلغات برمجة أخرى</a>.
</p>

<p>
	ولعلّ الخطوة الأولى قبل الإبحار في <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> هي إعداد البيئة، والتي تعرّف بأنها عملية تنظيم الحاسوب اللازمة لاستخدامه في كتابة الشيفرات البرمجية، الأمر الذي يتضمن تثبيت أي أدوات ضرورية وإعدادها، والتعامل مع أي مشاكل قد تواجهك أثناء عملية الإعداد، ولإنجاز هذه الخطوة لابد من فهمك الجيد لنظام الملفات وكيفية التعامل مع المسارات في بايثون.
</p>

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

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

<h2>
	نظام الملفات
</h2>

<p>
	إن نظام الملفات هو الوسيلة التي يعتمدها <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">نظام التشغيل</a> لتنظيم البيانات وتخزينها واستعادتها، إذ يضم الملف خاصيتين رئيسيتين: اسم الملف (وهو عبارة عن كلمة واحدة عادةً) ومساره.
</p>

<p>
	لنفرض مثلًا وجود ملف على حاسوب محمول ذو نظام التشغيل ويندوز 10 يدعى project.docx ضمن المسار C:\Users\Al\Documents، يحدد المسار موقع الملف في الحاسوب، أما الجزء الذي يلي اسم الملف بعد النقطة فهو لاحقة الملف التي تبين نوعه.
</p>

<p>
	فيشير مثلًا اسم الملف project.docx إلى أن هذا الملف مستند لبرنامج معالج النصوص Word أما Users و Al و Documents فهي اسماء مجلدات، والتي يمكن أن تحتوي على ملفات ومجلدات أخرى.
</p>

<p>
	في مثالنا السابق يوجد الملف project.docx ضمن مجلد المستندات Documents الذي يوجد في المجلد Al الموجود بدوره ضمن مجلد المستخدمين Users، ويبين الشكل التالي ترتيب هذه المجلدات.
</p>

<p style="text-align: center;">
	<img alt="ملف ضمن تسلسل هرمي للمجلدات" class="ipsImage ipsImage_thumbnailed" data-fileid="116183" data-ratio="98.00" data-unique="h8vhcgnnh" style="width: 250px; height: auto;" width="250" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-1.png.7a6a968f115934c87dfe6d57d5e63a28.png">
</p>

<p style="text-align: center;">
	ملف ضمن تسلسل هرمي للمجلدات
</p>

<p>
	إذ يمثل الجزء \:C من مسار الملف المجلد الأساسي الذي يحتوي على جميع المجلدات الأخرى.
</p>

<p>
	يعطى المجلد الأساسي في نظام التشغيل ويندوز Windows الاسم \:C، ويسمى أيضًا القرص :C، بينما في أنظمة التشغيل ماك أو إس Mac os و<a href="https://academy.hsoub.com/devops/linux/%D9%85%D8%A7-%D9%87%D9%88-%D9%86%D8%B8%D8%A7%D9%85-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%8A%D9%86%D9%83%D8%B3%D8%9F-r451/" rel="">لينكس Linux</a> فيشار إليه بالشكل /.
</p>

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

<p>
	هناك نماذج أخرى مثل محركات الأقراص DVD ومحركات الأقراص القابلة للإزالة USB flash drive والتي ستظهر بشكل مختلف في أنظمة التشغيل المختلفة، ففي نظام التشغيل ويندوز تظهر كمجلد أساسي جديد يحمل رمز حرف معين مثلاً \:D أو \:E، بينما في نظام ماك أو إس فتظهر كمجلد جديد ضمن المجلد Volumes/، وفي نظام التشغيل لينكس تظهر كمجلد جديد ضمن المجلد ‪/mnt ("mount")
</p>

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

<h2>
	المسارات في بايثون
</h2>

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

<p>
	من الممكن استيراد مكتبة pathlib من خلال تنفيذ الأمر <code>from pathlib import Path</code>، ولأن صنف المسار <code>Path</code> هو أكثر الأصناف استخدامًا في وحدة pathlib، فمن المسموح كتابة <code>Path</code> وحدها بدلًا من كتابة <code>pathlib.Path</code>.
</p>

<p>
	وبإمكاننا أن نمرر إلى الدالة <code>()Path</code> سلسة نصية هي عبارة عن اسم المجلد أو اسم الملف، وذلك بغية إنشاء كائن مسار Path لاسم هذا المجلد أو الملف.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_13" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> pathlib </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Path</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">(</span><span class="str">'spam'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'bacon'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'eggs'</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'spam/bacon/eggs'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">(</span><span class="str">'spam'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">(</span><span class="str">'bacon/eggs'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'spam/bacon/eggs'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">(</span><span class="str">'spam'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">(</span><span class="str">'bacon'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'eggs'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'spam/bacon/eggs'</span><span class="pun">)</span></pre>

<p>
	ونلاحظ بأنه كوننا ننفذ الشيفرة السابقة على حاسوب يعمل بنظام تشغيل ويندوز، فإن الدالة <code>()Path</code> تعيد كائن مسار ويندوز <code>windowspath</code>، في حين ستتم إعادة الكائن <code>PosixPath</code> في حال استخدام أحد نظامي التشغيل ماك أو إس أو لينكس. (تعد POSIX مجموعة معايير لأنظمة التشغيل الشبيهة بنظام يونيكس ولن نتطرق لها في دراستنا).
</p>

<p>
	ومن الممكن تمرير كائن المسار إلى أي دالة تتطلب اسم ملف في المكتبة المعيارية لبايثون. فعلى سبيل المثال يعد استدعاء الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_15" style=""><span class="pln">open</span><span class="pun">(</span><span class="typ">Path</span><span class="pun">(</span><span class="str">'C:\\'</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'Users'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'Al'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'Desktop'</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="str">'spam.py'</span><span class="pun">)</span></pre>

<p>
	مكافئًا لاستدعاء الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_17" style=""><span class="pln">open</span><span class="pun">(</span><span class="pln">r</span><span class="str">'C:\Users\Al\Desktop\spam.py'</span><span class="pun">)</span></pre>

<h2>
	المجلد الرئيسي
</h2>

<p>
	ما من مستخدم إلا ولديه مجلد رئيسي يخزن فيه ملفاته على الحاسوب، ومن الممكن الحصول على كائن مسار لهذا المجلد الرئيسي باستدعاء التابع <code>()path.home</code> بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_19" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">home</span><span class="pun">()</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'C:/Users/Al'</span><span class="pun">)</span></pre>

<p>
	وتوجد المجلدات الرئيسية في مكان محدد بناءً على نوع نظام التشغيل:
</p>

<ul>
	<li>
		توجد المجلدات الرئيسية في نظام التشغيل ويندوز ضمن C:\Users.
	</li>
	<li>
		توجد المجلدات الرئيسية في نظام التشغيل ماك أو إس ضمن Users/.
	</li>
	<li>
		توجد المجلدات الرئيسية في نظام التشغيل لينكس ضمن home/.
	</li>
</ul>

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

<h2>
	مجلد العمل الحالي
</h2>

<p>
	لكل برنامج يعمل على الحاسوب مجلد عمل حالي (cwd) توجد فيه جميع أسماء الملفات والمسارات التي لا تبدأ بالمجلد الأساسي.
</p>

<p>
	وعلى الرغم من أن كلمة "مجلد folder" هي الاسم الحديث للدليل Directory، يعد cwd (أو ما يعرف بدليل العمل الحالي) هو المصطلح المعياري وليس "مجلد العمل الحالي".
</p>

<p>
	يمكننا الحصول على دليل العمل في هيئة كائن مسار باستخدام الدالة <code>()Path.cwd</code> وتغييره باستخدام الدالة <code>()os.chdir</code>، ولإنجاز ذلك سنكتب الشيفرة التالية في الصدفة التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_21" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> pathlib </span><span class="kwd">import</span><span class="pln"> </span><span class="typ">Path</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> os
</span><span class="lit">1</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">cwd</span><span class="pun">()</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'C:/Users/Al/AppData/Local/Programs/Python/Python38'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">chdir</span><span class="pun">(</span><span class="str">'C:\\Windows\\System32'</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Path</span><span class="pun">.</span><span class="pln">cwd</span><span class="pun">()</span><span class="pln">
</span><span class="typ">WindowsPath</span><span class="pun">(</span><span class="str">'C:/Windows/System32'</span><span class="pun">)</span></pre>

<p>
	اعتبرنا في الشيفرة السابقة أن مسار دليل العمل هو<span><span>:</span></span>
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1951_8" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Programs\Python\Python381</span></pre>

<p>
	وبالتالي سيكون مسار الملف project.docx كالآتي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1951_10" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\Users\Al\AppData\Local\Programs\Python\Python381\project</span><span class="pun">.</span><span class="pln">docx</span></pre>

<p>
	وعندما نغير دليل العمل ليصبح C:\Windows\System32 سيصبح مسار الملف project.docx بالشكل C:\Windows\System32\project.docx، وسيظهر بايثون رسالة خطأ إن غيرنا المجلد إلى مجلد غير موجود:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3598_23" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> os</span><span class="pun">.</span><span class="pln">chdir</span><span class="pun">(</span><span class="str">'C:/ThisFolderDoesNotExist'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">FileNotFoundError</span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="typ">WinError</span><span class="pln"> </span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="typ">The</span><span class="pln"> system cannot find the file specified</span><span class="pun">:</span><span class="pln">
</span><span class="str">'C:/ThisFolderDoesNotExist'</span></pre>

<p>
	ويعد استخدام الدالة <code>()os.getcwd</code> من الوحدة os هو الطريقة الأقدم للحصول على مسار دليل العمل في هيئة سلسلة نصية.
</p>

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

<p>
	يوجد طريقتان لتحديد مسار ملف:
</p>

<ul>
	<li>
		المسار المطلق وهو الذي يبدأ دائمًا بالمجلد الأساسي.
	</li>
	<li>
		المسار النسبي والذي يشير عادةً إلى دليل العمل الخاص بالبرنامج.
	</li>
</ul>

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

<p>
	ويبين الشكل التالي مثالًا لبعض المجلدات والملفات، فعندما يكون دليل العمل بالشكل C:\bacon تكون المسارات النسبية للمجلدات والملفات الأخرى كما هو مبين في الشكل أدناه. أما وجود الرمز في بداية المسار النسبي فهو أمر اختياري، فعلى سبيل المثال يشير كل من spam.txt. و spam.txt إلى الملف ذاته.
</p>

<p style="text-align: center;">
	<img alt="المسارات النسبية للملفات والمجلدات في دليل العمل C:\bacon" class="ipsImage ipsImage_thumbnailed" data-fileid="116184" data-ratio="52.18" data-unique="0ybw1rt4c" style="width: 550px; height: auto;" width="550" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-2.png.6afc5abd428838815c2bf6036a2a0834.png">
</p>

<p style="text-align: center;">
	المسارات النسبية للملفات والمجلدات في دليل العمل C:\bacon
</p>

<h2>
	البرامج والعمليات
</h2>

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

<p style="text-align: center;">
	<img alt="تشغيل برنامج الآلة حاسبة عدة مرات على شكل عدة عمليات منفصلة" class="ipsImage ipsImage_thumbnailed" data-fileid="116185" data-ratio="57.83" data-unique="kbbgzyw5h" style="width: 600px; height: auto;" width="600" src="https://academy.hsoub.com/uploads/monthly_2023_01/2-3.png.0e4502b99449269125c1c7d6aa31419c.png">
</p>

<p style="text-align: center;">
	تشغيل برنامج الآلة حاسبة عدة مرات على شكل عدة عمليات منفصلة
</p>

<p>
	إذ تبقى العمليات منفصلة عن بعضها حتى التابعة منها لنفس البرنامج، فمثلًا إن شغلنا عدة نسخ من برنامج بايثون في نفس الوقت ضمن عمليات مستقلة، فيمكن أن يكون لكل منها قيم متغيرات خاصة بها ومختلفة، فلكل عملية دليل العمل ومتغيرات البيئة الخاصة بها وذلك حتى بالنسبة للعمليات التابعة لنفس البرنامج، وعمومًا تُشغّل نوافذ <a href="https://academy.hsoub.com/devops/servers/%D9%85%D8%A7-%D9%87%D9%88-%D8%B3%D8%B7%D8%B1-%D8%A7%D9%84%D8%A3%D9%88%D8%A7%D9%85%D8%B1-%D8%9F-r353/" rel="">سطر الأوامر</a> عملية واحدة في كل مرة (ومن الممكن أيضًا فتح عدة نوافذ أوامر في نفس الوقت).
</p>

<p>
	ولكل نظام تشغيل طريقته لعرض قائمة العمليات قيد التنفيذ، ففي نظام ويندوز من الممكن تشغيل تطبيق مدير المهام عبر الضغط على مفاتيح CTRL+SHIFT+ESC، أما في نظام ماك أو إس فيمكن الوصول إليها من قائمة التطبيقات Application ومنها نختار الخدمات Utilities ومن ثم مراقب الأداء Activity Monitor، أما في نظام أبونتو لينكس يمكننا الضغط على مفاتيح CTRL+ALT+DEL معًا لتشغيل تطبيق يدعى أيضًا بمدير المهام، ويمكن لمدير المهام أيضًا إنهاء عملية ما قيد التشغيل إن لم تكن تستجيب.
</p>

<h2>
	الخلاصة
</h2>

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

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

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

<p>
	ترجمة -وبتصرف- للفصل الثاني "إعداد البيئة وواجهة سطر الأوامر" من كتاب <a href="https://inventwithpython.com/beyond/chapter2.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B5%D9%88%D9%84-%D8%B7%D9%84%D8%A8-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-r1857/" rel="">أصول طلب المساعدات البرمجية في بايثون عبر الإنترنت</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%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-r306/" rel="">التعامل مع الملفات النصية في بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D9%85%D9%84%D9%81%D8%A7%D8%AA-%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-r484/" rel="">كيفية التعامل مع الملفات النصية في بايثون 3</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%d8%a7%d9%84%d8%aa%d8%b9%d8%a7%d9%85%d9%84-%d9%85%d8%b9-%d8%a7%d9%84%d8%b5%d9%81%d9%88%d9%81%d8%8c-%d8%a7%d9%84%d9%85%d8%ac%d9%85%d9%88%d8%b9%d8%a7%d8%aa-%d9%88%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-r226/" rel="">التعامل مع الصفوف، المجموعات والقواميس في بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1858</guid><pubDate>Mon, 23 Jan 2023 16:06:00 +0000</pubDate></item><item><title>&#x623;&#x635;&#x648;&#x644; &#x637;&#x644;&#x628; &#x627;&#x644;&#x645;&#x633;&#x627;&#x639;&#x62F;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x629; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x639;&#x628;&#x631; &#x627;&#x644;&#x625;&#x646;&#x62A;&#x631;&#x646;&#x62A;</title><link>https://academy.hsoub.com/programming/python/%D8%A3%D8%B5%D9%88%D9%84-%D8%B7%D9%84%D8%A8-%D8%A7%D9%84%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%B9%D8%A8%D8%B1-%D8%A7%D9%84%D8%A5%D9%86%D8%AA%D8%B1%D9%86%D8%AA-r1857/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/231753786_--------.png.a6baf39fc364ec899ef190a21dab688d.png" /></p>
<p>
	تعرفنا في <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%B1%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1856/" rel="">المقال السابق</a> على كيفية التعامل مع رسائل الأخطاء في <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">بايثون</a> وعلى الطرق المساعدة في فهم فحواها وإيجاد مسببات ظهورها، وذلك من خلال الاستعانة بمتتبع الأخطاء لتحديد مصدر الخطأ أو باستخدام منقح صياغة لتلافي وقوع أخطاء ما أمكن، أو اللجوء إلى الإنترنت بحثًا عن تفسير لمضمون رسالة الخطأ. ولكن ماذا لو فشلت هذه المحاولات، أو إن لم تجد في بحر الإنترنت سؤالًا مشابهًا لسؤالك، في هذه الحالة لابد من طرح سؤالك في أحد المنتديات أو ربما عبر إحدى المجموعات البريدية.
</p>

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

<h2>
	كيفية طلب المساعدة البرمجية
</h2>

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

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

<p>
	وفي حال سدت كل السبل في طريقك واستنفذتَ خياراتك بحيث لم يتبقَ أمامك سوى خيار طرح السؤال على جمهور المبرمجين، فتجنب الأخطاء الشائعة التالية:
</p>

<ul>
	<li>
		إضاعة الوقت بالسؤال عما إذا كان من المقبول طرح سؤالك بدلًا من طرحه مباشرةً.
	</li>
	<li>
		أن يكون سؤالك ضمنيًا وغير مباشر.
	</li>
	<li>
		طرح السؤال في الموقع الإلكتروني أو المنتدى غير المناسب.
	</li>
	<li>
		أن يكون عنوان السؤال غير محدد من قبيل "لدي مشكلة" أو "أرجو المساعدة".
	</li>
	<li>
		أن تذكر كون برنامجك لا يعمل دون توضيح الطريقة التي تريدها أن يعمل بها.
	</li>
	<li>
		عدم تضمين رسالة الخطأ كاملةً.
	</li>
	<li>
		عدم مشاركة الشيفرة.
	</li>
	<li>
		مشاركة شيفرة رديئة التنسيق.
	</li>
	<li>
		عدم ذكر الخطوات التي قد جربتَها أصلًا.
	</li>
	<li>
		عدم ذكر معلومات نوع <a href="https://academy.hsoub.com/files/24-%D8%A3%D9%86%D8%B8%D9%85%D8%A9-%D8%A7%D9%84%D8%AA%D8%B4%D8%BA%D9%8A%D9%84-%D9%84%D9%84%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D9%86/" rel="">نظام التشغيل</a> وإصداره.
	</li>
	<li>
		طلب كتابة برنامج كامل.
	</li>
</ul>

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

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

<h2>
	قلل من النقاشات غير المجدية بتقديم كافة المعلومات اللازمة مقدما
</h2>

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

<h3>
	اطرح سؤالك على هيئة سؤال فعلي
</h3>

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

<h3>
	اطرح سؤالك في المكان المناسب
</h3>

<p>
	غالبًا سيكون من غير المجدي طرح سؤال حول بايثون في منتدى مخصص <a href="https://academy.hsoub.com/programming/javascript/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D8%A8%D8%AA-r1689/" rel="">لجافاسكربت</a>، أو سؤال حول <a href="https://wiki.hsoub.com/Algorithms" rel="external">الخوارزميات</a> في قائمة بريدية مخصصة لأمن الشبكات، فغالبًا ما تتضمن المنتديات والقوائم البريدية على مستندات تتضمن الأسئلة الشائعة FAQ أو صفحات وصف لطبيعتها والتي تبين المواضيع المناسبة للنقاش فيها. فعلى سبيل المثال تتمحور القائمة البريدية python-dev حول الميزات التصميمية <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> ولا تمثل قائمة بريدية عامة للمساعدة حول بايثون بصورة عامة. وستوجهك صفحة <a href="https://www.python.org/about/help/" rel="external nofollow">المساعدة</a>  إلى المكان المناسب وفق طبيعة سؤالك حول <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a>.
</p>

<h3>
	لخص سؤالك في العنوان
</h3>

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

<h3>
	وضح الهدف المرجو من شيفرتك
</h3>

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

<h3>
	ضمّن رسالة الخطأ كاملة
</h3>

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

<h3>
	شارك شيفرتك كاملة
</h3>

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

<p>
	إذ يرمز الحرف M إلى Minimal بمعنى أن تكون الشيفرة أقصر ما يمكن مع بقائها تسبب المشكلة التي تواجهك، أما الحرف C فيرمز إلى Complete بمعنى أن تكون الشيفرة كاملة ومتضمنة كل ما يلزم لظهور المشكلة، والحرف R فيرمز إلى Reproducible بمعنى أن الشيفرة ستسبب نفس المشكلة التي تصفها عند كل تنفيذ، أما إن كان برنامجك مضمنًا في ملف واحد، فسيكون من السهل إرفاقه بسؤالك بعد التأكد من تنسيقه بطريقة صحيحة.
</p>

<h3>
	اجعل شيفرتك مقروءة ومفهومة باستخدام التنسيق الملائم
</h3>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5614_14" style=""><span class="kwd">def</span><span class="pln"> knuts</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">):</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> isinstance</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> int</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> value </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">raise</span><span class="pln"> </span><span class="typ">WizCoinException</span><span class="pun">(</span><span class="str">'knuts attr must be a positive int'</span><span class="pun">)</span><span class="pln">
self</span><span class="pun">.</span><span class="pln">_knuts </span><span class="pun">=</span><span class="pln"> value</span></pre>

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

<p>
	وللتأكد من الحفاظ على صحة تنسيق الشيفرة الخاصة ببرنامجك، انسخها إلى أحد مواقع مشاركة الشيفرات مثل <a href="https://pastebin.com/" ipsnoembed="false" rel="external nofollow">https://pastebin.com/</a> أو <a href="https://gist.github.com/" ipsnoembed="false" rel="external nofollow">https://gist.github.com/</a> والتي تخزن شيفرتك على هيئة رابط مختصَر وعام، فمثلًا إن أرفقت الشيفرة مع سؤالك على هيئة رابط مثل <a href="https://pastebin.com/XeU3yusC" ipsnoembed="false" rel="external nofollow">https://pastebin.com/XeU3yusC</a> سيكون أيسر وأسهل من إرفاقها كملف مرفق.
</p>

<p>
	وإذا كنت في صدد نشر شيفرة برنامجك في أحد المواقع الإلكترونية مثل <a href="https://stackoverflow.com/" rel="external nofollow">stackoverflow</a> أو <a href="https://academy.hsoub.com/questions/c3-programming/" rel="">قسم الأسئلة في أكاديمية حسوب</a> أو <a href="https://reddit.com/r/learnpython/" rel="external nofollow">reddit</a>، فتأكد من استخدامك لأدوات التنسيق التي توفرها الصناديق النصية فيها، فمثلًا باستخدامك لمسافة بادئة مكونة من أربعة مسافات سيضمن بالنتيجة استخدام نمط خط ذو تباعد مفرد للشيفرة بالغالب وهو الأسهل للقراءة، كما يمكنك تضمين الشيفرة ما بين علامات اقتباس مائلة (`) لتنسيقها بنمط خط ذو تباعد مفرد.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5614_21" style=""><span class="kwd">def</span><span class="pln"> knuts</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> value</span><span class="pun">):</span><span class="kwd">if</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> isinstance</span><span class="pun">(</span><span class="pln">value</span><span class="pun">,</span><span class="pln"> int</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> value </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">0</span><span class="pun">:</span><span class="kwd">raise</span><span class="pln"> </span><span class="typ">WizCoinException</span><span class="pun">(</span><span class="str">'knuts attr must be a positive int'</span><span class="pun">)</span><span class="pln"> self</span><span class="pun">.</span><span class="pln">_knuts </span><span class="pun">=</span><span class="pln"> value</span></pre>

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

<h3>
	اذكر في سؤالك جميع المحاولات التي أجريتها
</h3>

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

<p>
	كما أن تقديمك لهذه المعلومات يوضح أنك تطلب المساعدة فقط، ولست اتكاليًا تنتظر من يكتب لك شيفرة لبرنامجك عوضًا عنك. فالخبر السيئ أن الكثير من طلاب <a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">علوم الحاسوب</a> اعتادوا أن يطلبوا من الأشخاص على الإنترنت حل واجباتهم، أو من المستقلين أن يعدّو لهم تطبيقات سريعة مجانًا، متناسين أن منتديات المساعدة البرمجية لم تعد أصلًا لهذا الغرض.
</p>

<h3>
	وصف الإعدادات التي تستخدمها
</h3>

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

<ul>
	<li>
		نوع نظام التشغيل وإصداره، كأن تذكر أنه الإصدار الاحترافي من ويندوز 10 أو إصدار كاتالينا (الخامس عشر) من ماك أو إس.
	</li>
	<li>
		إصدار بايثون المستخدم في تنفيذ برنامجك، كأن تذكر بأن الإصدار 3.7 من بايثون أو الإصدار 3.6.6 منها.
	</li>
	<li>
		أي وحدات خارجية تستخدمها في برنامجك مع ذكر إصدار كل منها، كأن تذكر أنك تستخدم الإصدار 2.1.1 من وحدة <a href="https://academy.hsoub.com/programming/python/django/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A5%D8%B7%D8%A7%D8%B1-%D8%A7%D9%84%D8%B9%D9%85%D9%84-django%C2%A0-r353/" rel="">جانغو</a>.
	</li>
</ul>

<p>
	ولمعرفة إصدارات الوحدات الخارجية المستوردة في برنامجك، يمكنك تشغيل الأمر <code>pip list</code>، كما يمكنك التأكد من رقم إصدار كل منها باستخدام سمة الإصدار <code>__version__</code>، كما في المثال التالي المكتوب ضمن صَدفة بايثون التفاعلية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5614_25" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> django
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> django</span><span class="pun">.</span><span class="pln">__version__
</span><span class="str">'2.1.1'</span></pre>

<p>
	ورغم كون هذه المعلومات ليست بذلك القدر من الأهمية، إلا أن ذكرها سيقلل من الوقت الضائع في النقاشات (الصد والرد)، لذا من المحبذ عرضها من البداية.
</p>

<h3>
	أمثلة على أسئلة متكاملة
</h3>

<p>
	نبين فيما يلي مثالًا على سؤال مطروح بطريقة صحيحة وفقًا للإرشادات والنصائح الواردة في هذا المقال:
</p>

<p>
	<strong>محرك الويب سيلينيوم: كيف أجد كافّة سمات العنصر؟</strong> لدى استخدامي لوحدة سيلينيوم في بايثون، فبإمكاني الحصول على قيمة أي سمة من سمات كائن عنصر الويب باستخدام التابع <code>()get_attribute</code> بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_5614_27" style=""><span class="pln">get_attribute</span><span class="pun">():</span><span class="pln">
foo </span><span class="pun">=</span><span class="pln"> elem</span><span class="pun">.</span><span class="pln">get_attribute</span><span class="pun">(</span><span class="str">'href'</span><span class="pun">)</span></pre>

<p>
	وفي حال عدم وجود اسم السمة <code>href</code>، ستكون القيمة المعادة لا شيء <code>None</code>.
</p>

<p>
	سؤالي هو: كيف أحصل على قائمة بكافة سمات كل عنصر؟ فيبدو أنه لا يوجد توابع لجلب السمات من قبيل <code>get_attributes()</code> أو <code>()get_attribute_names</code>.
</p>

<p>
	علمًا أني أستخدم الإصدار 2.44.0 من وحدة سيلينيوم في بايثون.
</p>

<p>
	لقد ورد <a href="https://academy.hsoub.com/questions/21590-%D8%AE%D8%B7%D8%A3%C2%A0charmap-codec-cant-encode-characters-%D9%81%D9%8A-%D9%85%D9%83%D8%AA%D8%A8%D8%A9-beautifull-soup-%D9%81%D9%8A%C2%A0-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/#comment-64123" rel="">هذا السؤال</a> في قسم الأسئلة في أكاديمية حسوب، وفيه نلاحظ بأن العنوان قد لخص مضمون السؤال كاملًا في جملة واحدة، إذ ذُكرت المشكلة وهي التي تتحدث عن صيغة الخطأ الذي يظهر أثناء التنفيذ، وبذلك إذا قرأ شخص ما هذا العنوان مستقبلًا في نتائج البحث، فسيتضح له مباشرةً فيما إذا كان ذو صلة بسؤاله أم لا.
</p>

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

<h2>
	الخلاصة
</h2>

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

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

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

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

<p>
	ترجمة -وبتصرف- للفصل الأول "التعامل مع الأخطاء وطلب المساعدة" من كتاب <a href="http://inventwithpython.com/beyond/chapter1.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%B1%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1856/" rel="">التعامل مع رسائل الأخطاء في بايثون</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%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>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r1342/" rel="">كيفية التعامل مع الأخطاء البرمجية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1857</guid><pubDate>Mon, 16 Jan 2023 16:09:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x639;&#x627;&#x645;&#x644; &#x645;&#x639; &#x631;&#x633;&#x627;&#x626;&#x644; &#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x641;&#x64A; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646;</title><link>https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%B1%D8%B3%D8%A7%D8%A6%D9%84-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1856/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2023_01/1471421868_------.png.cfbea4acabd0027acffc495590f00fa2.png" /></p>
<p>
	تعد <a href="https://academy.hsoub.com/learn/python-application-development/" rel="">بايثون Python</a> إحدى أشهر <a href="https://ana.hsoub.com/app/todo/34e76931-936e-4ba5-bc65-089f54f628bf" rel="external">لغات البرمجة</a> وأكثرها استخدامًا، وهي خيار ممتاز ليبدأ به المبرمجون المبتدئون، إذ يمكن استخدامها في معظم المجالات، بدءًا من ألعاب الفيديو، وحتى تحليل البيانات والتعلم الآلي.
</p>

<p>
	<a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> هي لغة برمجة عالية المستوى، وتفاعلية وكائنية. وتتمتع بمقروئية عالية، إذ تستخدم كلمات إنجليزية بسيطة، على خلاف اللغات الأخرى التي تستخدم الرموز، كما أنّ قواعدها الإملائية والصياغية بسيطة، ما يجعل تعلمها سهلًا موازنةً بلغات برمجة أخرى.
</p>

<p>
	وفي بدايات تعلّمك <a href="https://academy.hsoub.com/programming/python/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r211/" rel="">لغة بايثون</a> ، وكما هو الحال في رحلة تعلّم أي لغة برمجة، قد تواجهك بعض العقبات ورسائل الأخطاء غير المفهومة، وفي هذه المرحلة من الشائع الشعور بالفشل لدى اضطرارك لاستشارة مواقع الإنترنت عدة مرات في اليوم. لكن حتى أمهر مطوري البرمجيات يبحثون في الإنترنت ويراجعون التوثيقات لإيجاد إجابات حول أسئلتهم البرمجية.
</p>

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

<h2>
	كيفية فهم رسائل الأخطاء في بايثون
</h2>

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

<h3>
	فحص متتبع الأخطاء
</h3>

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_11" style=""><span class="lit">1.</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> a</span><span class="pun">():</span><span class="pln">
</span><span class="lit">2.</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Start of a()'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pln">    </span><span class="lit">3.</span><span class="pln">     b</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call b().</span><span class="pln">
</span><span class="lit">4.</span><span class="pln">
</span><span class="lit">5.</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> b</span><span class="pun">():</span><span class="pln">
</span><span class="lit">6.</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Start of b()'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln">    </span><span class="lit">7.</span><span class="pln">     c</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call c().</span><span class="pln">
</span><span class="lit">8.</span><span class="pln">
</span><span class="lit">9.</span><span class="pln"> </span><span class="kwd">def</span><span class="pln"> c</span><span class="pun">():</span><span class="pln">
</span><span class="lit">10.</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'Start of c()'</span><span class="pun">)</span><span class="pln">
</span><span class="lit">3</span><span class="pln">    </span><span class="lit">11.</span><span class="pln">     </span><span class="lit">42</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># This will cause a zero divide error.</span><span class="pln">
</span><span class="lit">12.</span><span class="pln">
</span><span class="lit">13.</span><span class="pln"> a</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call a().</span></pre>

<p>
	في البرنامج السابق، تستدعي الدالة <code>()a</code> الدالة <code>()b</code>، التي تستدعي بدورها الدالة <code>()c</code> المتضمنة للتعبير الرياضي 42/0 المسبب لخطأ القسمة على صفر، فعند تشغيل هذا البرنامج، سيبدو الخرج بالشكل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_21" style=""><span class="typ">Start</span><span class="pln"> of a</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Start</span><span class="pln"> of b</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Start</span><span class="pln"> of c</span><span class="pun">()</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">13</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
    a</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call a().</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> a
    b</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call b().</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> b
    c</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call c().</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> c
    </span><span class="lit">42</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># This will cause a zero divide error.</span><span class="pln">
</span><span class="typ">ZeroDivisionError</span><span class="pun">:</span><span class="pln"> division by zero</span></pre>

<p>
	لنتفحص الآن تقرير متتبع الأخطاء سطرًا بسطر، والذي يبدأ من السطر:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_19" style=""><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span></pre>

<p>
	وتهدف هذه الرسالة إلى إبلاغك بأن ما يتلوها هو تقرير متتبّع الأخطاء، وتشير العبارة <code>most recent call last</code> والتي تعني أن الاستدعاء الأخير سيظهر في نهاية التقرير إلى كون استدعاءات التوابع ستظهر في التقرير بنفس ترتيب ورودها في الشيفرة، بدءًا من استدعاء أول دالة وانتهاءً بآخرها.
</p>

<p>
	أما السطر التالي فيظهر تقرير تتبّع استدعاء أول دالة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_17" style=""><span class="pln"> </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">13</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
    a</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call a().</span></pre>

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

<p>
	ويُظهر متتبّع الأخطاء ملخصًا على هيئة إطار لكل إطار قد انتهى دوره بإعادة قيمة دالته، ونلاحظ من التقرير أعلاه أن استدعاء هذه الدالة قد تم في السطر ذو الرقم 13 من الملف abcTraceback.py، ويشير الوسم <code>&lt;module&gt;</code> إلى كون هذا السطر مصرح عنه ضمن المجال العام، ليظهر بعدها السطر 13 نفسه مسبوقًا بمسافتين بادئتين.
</p>

<p>
	وتظهر الأسطر الأربعة التالية ملخصات الأطر التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_24" style=""><span class="pln">  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> a
    b</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call b().</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> b
    c</span><span class="pun">()</span><span class="pln">  </span><span class="com"># Call c().</span></pre>

<p>
	ومنه نستنج أنه قد تم استدعاء الدالة <code>()b</code> في السطر الثالث ضمن الدالة <code>()a</code>، ما أدى بدوره إلى استدعاء الدالة <code>()c</code> في السطر 7 ضمن الدالة <code>()b</code>. ومن الجدير بالملاحظة أن تقرير التتبع لا يُظهر استدعاء الدالة <code>()print</code> الذي تم في كل من الأسطر 2 و 6 و 10 من الشيفرة رغم تشغيلها حتى قبل استدعاء <a href="https://academy.hsoub.com/programming/python/%d8%aa%d8%b9%d8%b1%d9%81-%d8%b9%d9%84%d9%89-%d8%a7%d9%84%d8%af%d9%88%d8%a7%d9%84-functions-%d9%81%d9%8a-%d8%a8%d8%a7%d9%8a%d8%ab%d9%88%d9%86-r292/" rel="">الدوال</a> آنفة الذكر، والسبب في ذلك هو أن التقرير يشمل فقط الأسطر الحاوية على استدعاءات التوابع المسببة للاستثناء.
</p>

<p>
	وآخر إطار من ملخص تقرير تتبع الأخطاء يظهر رقم السطر المتضمن للاستثناء الذي لم يتم التعامل معه متبوعًا باسمه ورسالة الخطأ الخاصة به:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_27" style=""><span class="pln"> </span><span class="typ">File</span><span class="pln"> </span><span class="str">"abcTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> c
    </span><span class="lit">42</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">0</span><span class="pln">  </span><span class="com"># This will cause a zero divide error.</span><span class="pln">
</span><span class="typ">ZeroDivisionError</span><span class="pun">:</span><span class="pln"> division by zero</span></pre>

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

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

<p>
	والآن دعونا ننتقل إلى حالة أصعب قليلًا. لذا، اكتب الشيفرة التالية ضمن محرر النصوص واحفظ الملف باسم zeroDivideTraceback.py:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_29" style=""><span class="kwd">def</span><span class="pln"> spam</span><span class="pun">(</span><span class="pln">number1</span><span class="pun">,</span><span class="pln"> number2</span><span class="pun">):</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> number1 </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">number2 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln">

spam</span><span class="pun">(</span><span class="lit">101</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span></pre>

<p>
	ولدى تشغيل هذا البرنامج، سيبدو الخرج كالتالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_32" style=""><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"zeroDivideTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
    spam</span><span class="pun">(</span><span class="lit">101</span><span class="pun">,</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"zeroDivideTraceback.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> spam
    </span><span class="kwd">return</span><span class="pln"> number1 </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="pln">number2 </span><span class="pun">-</span><span class="pln"> </span><span class="lit">42</span><span class="pun">)</span><span class="pln">
</span><span class="typ">ZeroDivisionError</span><span class="pun">:</span><span class="pln"> division by zero</span></pre>

<p>
	إن رسالة الخطأ هي نفسها كما في المثال السابق، إلا أن خطأ القسمة على صفر في السطر البرمجي <code>return number1 / (number2 - 42)</code> غير واضح تمامًا، ولكن من الممكن استنتاج وجود عملية قسمة من وجود المعامل <code>/</code>، وبأن التعبير <code>(number2-42)</code> يساوي الصفر، وهذا ما يمكننا من استنتاج أن الدالة <code>spam()</code> ستعطي خطأ في حال كان الوسيط الثاني number2 المُمرر لها مساويًا للعدد 42.
</p>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_34" style=""><span class="kwd">print</span><span class="pun">(</span><span class="str">'Hello.'</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you?'</span><span class="pun">)</span></pre>

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_36" style=""><span class="pln"> </span><span class="typ">File</span><span class="pln"> </span><span class="str">"example.py"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">2</span><span class="pln">
    </span><span class="kwd">print</span><span class="pun">(</span><span class="str">'How are you?'</span><span class="pun">)</span><span class="pln">
        </span><span class="pun">^</span><span class="pln">
</span><span class="typ">SyntaxError</span><span class="pun">:</span><span class="pln"> invalid syntax</span></pre>

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

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

<h3>
	البحث حول رسائل الخطأ
</h3>

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

<p>
	ويبين الشكل التالي نتائج البحث عن الجملة <code>python "ZeroDivisionError: division by zero"</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="">Python</a> يؤدي إلى تضييق نطاق البحث أكثر.
</p>

<p style="text-align: center;">
	<img alt="البحث حول رسائل الخطأ في بايثون" class="ipsImage ipsImage_thumbnailed" data-fileid="116181" data-ratio="68.36" data-unique="tp848f9cb" style="width: 550px; height: auto;" width="550" src="https://academy.hsoub.com/uploads/monthly_2023_01/1-1.png.f8e17fbba65dc8c28ce56959f5c0c19b.png">
</p>

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

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

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

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_8823_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln">employeRecord</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> </span><span class="typ">NameError</span><span class="pun">:</span><span class="pln"> name </span><span class="str">'employeRecord'</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> defined
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="lit">42</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="str">'hello'</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> </span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> unsupported operand type</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">-:</span><span class="pln"> </span><span class="str">'int'</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> </span><span class="str">'str'</span></pre>

<p>
	يوجد في هذا المثال خطأ كتابي في اسم المتغير employeRecord ما سبب حدوث الخطأ 1، وبما أن المعرف employeRecord خاص بشيفرتك، وذلك في رسالة الخطأ NameError: name 'employeRecord' is not defined والتي تعني حدوث خطأ في الاسم بسبب كون اسم المتغير employeRecord غير معرف.
</p>

<p>
	أما في السطر الأخير فمن الواضح أن الأجزاء <code>int</code> و <code>str</code> من رسالة الخطأ 2 تعود للقيم 42 و <code>hello</code> على التوالي، ففي هذه الحالة من الأفضل اقتصار البحث على العبارة python "TypeError: unsupported operand type(s)" for والتي تعني خطأ في نمط البيانات ناتج عن كون أحد المعاملات ذو نمط غير مدعوم، وذلك بدلًا من تضمين البحث بأجزاء من الرسالة تخص شيفرتك على وجه التحديد، وإذا فشل هذا البحث المختصر في الوصول إلى نتائج مفيدة، فجرب كتابة رسالة الخطأ كاملةً.
</p>

<h3>
	تجنب حدوث الأخطاء باستخدام منقحات الصياغة
</h3>

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

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

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

<p style="text-align: center;">
	<img alt="تجنب حدوث الأخطاء باستخدام منقحات الصياغة" class="ipsImage ipsImage_thumbnailed" data-fileid="116182" data-ratio="101.25" data-unique="t6qcvfyn9" style="width: 400px; height: auto;" width="400" src="https://academy.hsoub.com/uploads/monthly_2023_01/1-2.png.b3853184850d71578c4eb50280f6b5c3.png">
</p>

<p>
	منقّح صياغة يشير إلى متغير غير مصرح عنه وذلك في محرر النصوص MU (الشكل الأعلى) وفي المحرر PyCharm (الشكل الأوسط) وفي المحرر Sublime (الشكل الأسفل).
</p>

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

<p>
	وقد لا يأتي محرر النصوص أو البيئة البرمجية المتكاملة التي تستخدمها مع منقّح صياغة أصلًا، ولكن إن كانت تدعم الإضافات، فمن شبه المؤكد وجود منقّح صياغة كإضافة، وغالبًا ما تستخدم هذه الإضافات وحدة تنقيح صياغة تدعى Pyflakes أو وحدات أخرى تؤدي هذا الغرض. وبإمكانك تثبيت الوحدة Pyflakes من الرابط <a href="https://pypi.org/project/pyflakes/" ipsnoembed="false" rel="external nofollow">https://pypi.org/project/pyflakes/</a> أو باستخدام أمر تثبيت الحزم <code>pip</code> بكتابة الأمر <code>pip install --user pyflakes</code>، الأمر الذي يستحق العناء لإنجازه.
</p>

<p>
	<strong>ملاحظة</strong>: يمكنك في نظام ويندوز تشغيل كل من الأمرين <code>pip</code> و <code>python</code>، ولكن في حال استخدامك لأنظمة ماك أو إس أو لينكس فتكون أسماء هذين الأمرين بهذا الشكل فقط من أجل الإصدار الثاني من بايثون، أما للإصدار الثالث فيصبحان بالشكل <code>pip3</code> و <code>python3</code>، انتبه لهذا الموضوع كلما صادفت أحد الأمرين <code>pip</code> أو <code>python</code> في سياق المقال.
</p>

<p>
	تأتي <a href="https://academy.hsoub.com/programming/workflow/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D9%85%D8%AA%D9%83%D8%A7%D9%85%D9%84%D8%A9-ide-r1513/" rel="">بيئة التطوير المتكاملة الخاصة ببايثون IDLE</a> بدون منقّح صياغة وبدون القابلية لتثبيته فيها.
</p>

<h2>
	الخلاصة
</h2>

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

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

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

<p>
	وتذكر أن <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%AA%D8%B9%D9%84%D9%85%D9%87%D8%A7%D8%9F-r1279/" rel="">البرمجة</a> مجال واسع جدًا، ولا يمكن لأحد أن يحيط بجميع تفاصيله، لذا لا تشعر بالإحباط إن اضطررت للبحث باستمرار عن إجابات لأسئلتك، فحتى مطورو البرمجيات المتمرسون يبحثون في الإنترنت عن التوثيقات والحلول يوميًا، وبدلًا من تضييع وقتك بالإحساس بالإحباط ركز على اكتساب مهارة إيجاد الحلول، وهي خطوة مهمة في طريقك لتصبح خبير بايثون.
</p>

<p>
	ترجمة -وبتصرف- للفصل الأول "التعامل مع الأخطاء وطلب المساعدة" من كتاب <a href="http://inventwithpython.com/beyond/chapter1.html" rel="external nofollow">Beyond the Basic Stuff with Python</a> لصاحبه Al Sweigart.
</p>

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

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81%D9%8A%D8%A9-%D8%A7%D9%84%D8%AA%D8%B9%D8%A7%D9%85%D9%84-%D9%85%D8%B9-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-r1342/" rel="">كيفية التعامل مع الأخطاء البرمجية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A7%D8%AA-%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-r1815/" rel="">أساسيات البرمجة بلغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A8%D9%8A%D8%A6%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84-%D9%84%D9%84%D9%85%D8%B4%D8%A7%D8%B1%D9%8A%D8%B9-%D9%85%D8%B9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r1751/" 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">1856</guid><pubDate>Mon, 09 Jan 2023 16:05:00 +0000</pubDate></item></channel></rss>
