Uploaded by Muntazer Hazem

870f1ad5-e611-4d1b-96c3-3fb0db6b30f4 code-in-python-3-ar-v1.0.0

advertisement
‫البرمجة بلغة بايثون‬
‫تعلم البرمجة وكتابة البرامج وتنقيحها بلغة بايثون‬
‫تأليف‬
‫ليزا تاغليفيري‬
‫ترجمة‬
‫محمد بغات‬
‫عبد اللطيف ايمش‬
‫تحرير‬
‫جميل بيلوني‬
‫تصميم الغالف‬
‫فرج الشامي‬
‫أكاديمية حسوب © النسخة األولى ‪2020‬‬
‫صنف ‪ -‬غير‬
‫هذا العمل‬
‫الم َّ‬
‫َّ‬
‫مرخص بموجب رخصة المشاع اإلبداعي‪ :‬نَ سب ُ‬
‫تجاري ‪ -‬الترخيص بالمثل ‪ 4.0‬دولي‬
‫عن الناشر‬
‫ُأ‬
‫نتج هذا الكتاب برعاية شركة حسوب وأكاديمية حسوب‪.‬‬
‫أكاديمية حسوب‬
‫تهدف أكاديمي ة حس وب إلى توف ير مق االت ودروس‬
‫عالي‬
‫ة الج‬
‫ودة ح‬
‫ول مج‬
‫االت مُ ختلف‬
‫ة وبلغة‬
‫عربية فصيحة‪.‬‬
‫تق دم أكاديمي ة حس وب دورات ش املة بج ودة عالي ة‬
‫عن تعلم البرمج ة بأح دث تقنياته ا تعتم د على التط بيق‬
‫العملي‪ ،‬مما يؤهل الطالب لدخول سوق العمل بثقة‪.‬‬
‫تتكامل األكاديمية م ع موس وعة حس وب‪ ،‬ال تي ت وفر‬
‫ً‬
‫عربيا شاماًل مدعمً ا باألمثلة للغات البرمجة‪.‬‬
‫توثيقا‬
‫ً‬
‫ب اب المُ س اهمة في األكاديمي ة مفت وح لك ل من ي رى‬
‫في نفس ه الق درة على توف ير مق االت أو كتب أو مس ارات‬
‫عالية الجودة‪.‬‬
‫‪Academy.hsoub.com‬‬
‫شركة حسوب‬
‫ته دف حس وب لتط وير ال ويب الع ربي وخ دمات اإلن ترنت‬
‫عن طري ق توف ير حل ول عملي ة وس هلة االس تخدام لتح ديات‬
‫مختلفة تواجه المستخدمين في العالم العربي‪.‬‬
‫تش جع حس وب الش باب الع ربي لل دخول إلى س وق العم ل‬
‫عن بع د بتوفيره ا منص ات عربي ة للعم ل عن بع د‪ ،‬مس تقل‬
‫ً‬
‫افة إلى موق ع بعي د‪ ،‬وكم ا أنه ا ت وفر خ دمات‬
‫وخمس ات؛ إض‬
‫للنقاش ات الهادف ة في حس وب ‪ I/O‬وخدم ة رف ع الص ور ع بر‬
‫موقع صور‪.‬‬
‫يعمل في حسوب فريق شاب وش غوف من مختل ف ال دول‬
‫العربي ة‪ .‬ويمكن معرف ة المزي د عن ش ركة حس وب والخ دمات‬
‫التي تقدمها بزيارة موقعها‪.‬‬
‫‪Hsoub.com‬‬
‫▲‬
‫جدول المحتويات‬
‫تقديم ‪15..............................................‬‬
‫‪ .1‬كيفية استخدام هذا الكتاب‪17..................................‬‬
‫‪ .2‬ماذا بعد هذا الكتاب‪18...........................................‬‬
‫مدخل تعريفي إلى لغة بايثون‪20...............‬‬
‫‪ .1‬تاريخ بايثون‪22....................................................‬‬
‫‪ .2‬مميزات لغة بايثون‪22............................................‬‬
‫‪ .3‬أين ُتستخ َدم بايثون؟‪23.........................................‬‬
‫‪ .4‬لماذا بايثون وليس غيرها؟‪24...................................‬‬
‫‪ .5‬خالصة الفصل‪27..................................................‬‬
‫تثبيت بايثون وإعداد بيئة العمل‪28..............‬‬
‫‪ .1‬ويندوز ‪30...........................................................‬‬
‫‪ .2‬أوبنتو‪41.............................................................‬‬
‫‪ .3‬دبيان ‪47.............................................................‬‬
‫‪54..........................................................CentOS .4‬‬
‫‪60...........................................................macOS .5‬‬
‫سطر أوامر بايثون التفاعلي‪70...................‬‬
‫‪ .1‬فتح سطر األوامر التفاعلي‪71...................................‬‬
‫‪ .2‬العمل في سطر أوامر بايثون التفاعلي‪73.....................‬‬
‫‪ .3‬تع ُّدد األسطر ‪74....................................................‬‬
‫‪ .4‬استيراد الوحدات‪75..............................................‬‬
‫‪ .5‬الخروج من سطر أوامر بايثون التفاعلي‪77 ..................‬‬
‫‪ .6‬االطالع على التاريخ ‪78..........................................‬‬
‫‪ .7‬خالصة الفصل‪79..................................................‬‬
‫التعليقات واستخداماتها ‪80......................‬‬
‫‪ .1‬صياغة التعليقات‪81...............................................‬‬
‫‪ .2‬التعليقات الكتلية‪83...............................................‬‬
‫‪ .3‬التعليقات السطرية‪84............................................‬‬
‫‪ .4‬تعليق جزء من الشيفرة بدواعي االختبار والتنقيح‪85 .....‬‬
‫‪ .5‬خالصة الفصل‪87..................................................‬‬
‫المتغيرات واستخداماتها‪88.......................‬‬
‫‪ .1‬فهم المتغيرات‪89..................................................‬‬
‫‪ .2‬قواعد تسمية المتغيرات‪93......................................‬‬
‫‪ .3‬تغيير قيم المتغيرات‪95..........................................‬‬
‫‪ .4‬اإلسناد المتعدد (‪96..................)Multiple Assignment‬‬
‫‪ .5‬المتغيرات العامة والمحلية‪97...................................‬‬
‫‪ .6‬خالصة الفصل‪102................................................‬‬
‫أنواع البيانات والتحويل بينها‪103................‬‬
‫‪ .1‬خلفية عامة‪104....................................................‬‬
‫‪ .2‬األعداد‪105..........................................................‬‬
‫‪ .3‬القيم المنطقية‪107................................................‬‬
‫‪ .4‬السالسل النصية‪109..............................................‬‬
‫‪ .5‬القوائم (‪110................................................)Lists‬‬
‫‪ .6‬الصفوف (‪111...........................................)Tuples‬‬
‫‪ .7‬القواميس ( ‪112..................................)Dictionaries‬‬
‫‪ .8‬التحويل بين أنواع البيانات‪113................................‬‬
‫‪ .9‬خالصة الفصل‪125................................................‬‬
‫السالسل النصية والتعامل معها‪127...........‬‬
‫‪ .1‬إنشاء وطباعة السالسل النصية‪128...........................‬‬
‫‪ .2‬آلية فهرسة السالسل النصية‪129...............................‬‬
‫‪ .3‬تقسيم السالسل النصية‪131.....................................‬‬
‫‪ .4‬جمع السالسل النصية‪135........................................‬‬
‫‪ .5‬تكرار السالسل النصية‪136......................................‬‬
‫‪ .6‬تخزين السالسل النصية في متغيرات‪136 ...................‬‬
‫‪ .7‬دوال السالسل النصية‪137.......................................‬‬
‫‪ .8‬دوال اإلحصاء ‪143................................................‬‬
‫‪ .9‬خالصة الفصل‪146................................................‬‬
‫مدخل إلى تنسيق النصوص‪147.................‬‬
‫‪ .1‬الصياغة المختزلة‪148............................................‬‬
‫‪ .2‬عالمات االقتباس‪148.............................................‬‬
‫‪ .3‬كتابة النص على أكثر من سطر‪149............................‬‬
‫‪ .4‬تهريب المحارف‪150..............................................‬‬
‫‪ .5‬السالسل النصية الخام‪152......................................‬‬
‫‪ .6‬استخدام المُ ِّ‬
‫نسقات ‪153..........................................‬‬
‫‪ .7‬تحديد نوع القيمة‪161............................................‬‬
‫‪ .8‬إضافة حواشي‪163................................................‬‬
‫‪ .9‬استخدام المتغيرات‪165..........................................‬‬
‫‪ .10‬خالصة الفصل‪166...............................................‬‬
‫العمليات الحسابية ‪167.............................‬‬
‫‪ .1‬العامالت‪168........................................................‬‬
‫‪ .2‬الجمع والطرح‪170.................................................‬‬
‫‪ .3‬العمليات الحسابية األحادية‪171................................‬‬
‫‪ .4‬الضرب والقسمة ‪172..............................................‬‬
‫‪ .5‬عامل باقي القسمة (‪174.............................)Modulo‬‬
‫‪ .6‬القوة (‪174................................................)Power‬‬
‫‪ .7‬أسبقية العمليات الحسابية‪175.................................‬‬
‫‪ .8‬عامل اإلسناد (‪176 ................)Assignment Operators‬‬
‫‪ .9‬إجراء العمليات الرياضية عبر الدوال‪178.....................‬‬
‫‪ .10‬خالصة الفصل‪186...............................................‬‬
‫العمليات المنطقية (البوليانية)‪187.............‬‬
‫‪ .1‬عامل الموازنة‪188.................................................‬‬
‫‪ .2‬العامالت المنطقية‪191............................................‬‬
‫‪ .3‬جداول الحقيقة (‪194..........................)Truth Tables‬‬
‫‪ .4‬استعمال المنطق للتحكم في مسار البرنامج‪196 ............‬‬
‫‪ .5‬خالصة الفصل‪197................................................‬‬
‫النوع ‪ :List‬مدخل إلى القوائم‪198...............‬‬
‫‪ .1‬فهرسة القوائم ( ‪200..........................)Indexing Lists‬‬
‫‪ .2‬تعديل عناصر القائمة‪202........................................‬‬
‫‪ .3‬تقطيع القوائم (‪202..............................)Slicing Lists‬‬
‫‪ .4‬تعديل القوائم بالعوامل‪205.....................................‬‬
‫‪ .5‬إزالة عنصر من قائمة‪207........................................‬‬
‫‪ .6‬بناء قوائم من قوائم أخرى موجودة‪208 .....................‬‬
‫‪ .7‬استخدام توابع القوائم‪209......................................‬‬
‫‪ .8‬فهم كيفية استعمال ‪217............List Comprehensions‬‬
‫‪ .9‬خالصة الفصل‪223................................................‬‬
‫النوع ‪ :Tuple‬فهم الصفوف‪225..................‬‬
‫‪ .1‬فهرسة الصفوف‪227..............................................‬‬
‫‪ .2‬تقطيع قيم صف‪229..............................................‬‬
‫‪ .3‬إضافة بنى صف إلى بعضها‪231................................‬‬
‫‪ .4‬دوال التعامل مع الصفوف‪233..................................‬‬
‫‪ .5‬كيف تختلف بنى الصفوف عن القوائم‪235...................‬‬
‫‪ .6‬خالصة الفصل‪236................................................‬‬
‫النوع ‪ :Dictionary‬فهم القواميس‪237..........‬‬
‫‪ .1‬الوصول إلى عناصر قاموس‪239...............................‬‬
‫‪ .2‬تعديل القواميس‪243.............................................‬‬
‫‪ .3‬حذف عناصر من القاموس‪247.................................‬‬
‫‪ .4‬خالصة الفصل‪249................................................‬‬
‫التعليمات الشرطية ‪250............................‬‬
‫‪ .1‬التعليمة ‪251......................................................if‬‬
‫‪ .2‬التعليمة ‪253..................................................else‬‬
‫‪ .3‬التعليمة ‪254................................................else if‬‬
‫‪ .4‬تعليمات ‪ if‬المتشعبة‪257.........................................‬‬
‫‪ .5‬خالصة الفصل‪262................................................‬‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‪263.....‬‬
‫‪ .1‬حلقة التكرار ‪264...........................................while‬‬
‫‪ .2‬حلقة التكرار ‪272..............................................for‬‬
‫‪ .3‬التحكم بحلقات التكرار‪282......................................‬‬
‫‪ .4‬خالصة الفصل‪287................................................‬‬
‫الدوال‪ :‬تعريفها واستعمالها‪288...............‬‬
‫‪ .1‬تعريف دالة ‪289....................................................‬‬
‫‪ .2‬المعامالت‪ :‬تمرير بيانات للدوال‪291...........................‬‬
‫‪ .3‬الوسائط المسمَّ اة ‪293.............................................‬‬
‫‪ .4‬القيم االفتراضية للوسائط‪295..................................‬‬
‫‪ .5‬إعادة قيمة‪296.....................................................‬‬
‫ً‬
‫ً‬
‫رئيسية‪299.............................‬‬
‫دالة‬
‫‪ .6‬استخدام )(‪main‬‬
‫‪ .7‬استخدام ‪ *args‬و ‪305...............................**kwargs‬‬
‫‪ .8‬ترتيب الوسائط‪310...............................................‬‬
‫‪ .9‬استخدام ‪ *args‬و ‪311...............................**kwargs‬‬
‫‪ .10‬خالصة الفصل‪313...............................................‬‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‪314..............‬‬
‫‪ .1‬تثبيت الوحدات‪316..............................................‬‬
‫‪ .2‬استيراد الوحدات‪317.............................................‬‬
‫‪ .3‬استيراد عناصر مح َّددة‪320......................................‬‬
‫‪ .4‬األسماء المستعارة في الوحدات‪321 ..........................‬‬
‫مخصصة واستيرادها‪322......................‬‬
‫َّ‬
‫‪ .5‬كتابة وحدات‬
‫‪ .6‬الوصول إلى الوحدات من مجلد آخر‪326.....................‬‬
‫‪ .7‬خالصة الفصل‪329................................................‬‬
‫بناء األصناف واستنساخ الكائنات‪330...........‬‬
‫‪ .1‬األصناف‪331........................................................‬‬
‫‪ .2‬الكائنات‪332........................................................‬‬
‫‪ .3‬الباني (‪334........................................)Constructor‬‬
‫‪ .4‬العمل مع عدة كائنات‪337........................................‬‬
‫‪ .5‬فهم متغيرات األصناف والنسخ‪338 ...........................‬‬
‫‪ .6‬العمل مع متغيرات الصنف والنسخة معً ا‪343.................‬‬
‫‪ .7‬خالصة الفصل‪344................................................‬‬
‫مفهوم الوراثة في البرمجة‪346.................‬‬
‫‪ .1‬ما هي الوراثة؟‪347................................................‬‬
‫‪ .2‬األصناف األساسية‪348...........................................‬‬
‫‪ .3‬األصناف الفرعية ‪350.............................................‬‬
‫‪ .4‬إعادة تعريف توابع الصنف األساسي‪353 .....................‬‬
‫‪ .5‬الدالة )(‪ super‬وفائدتها في الوراثة‪355.......................‬‬
‫ِّ‬
‫‪ .6‬الوراثة المُ‬
‫تعددة (‪358...............)Multiple Inheritance‬‬
‫‪ .7‬خالصة الفصل‪360................................................‬‬
‫التعددية الشكلية وتطبيقاتها‪361.............‬‬
‫‪ .1‬ما هي التعددية الشكلية (‪)Polymorphism‬؟‪362 ...........‬‬
‫‪ .2‬إنشاء أصناف متعددة األشكال‪363............................‬‬
‫‪ .3‬التعددية الشكلية في توابع األصناف‪365.....................‬‬
‫‪ .4‬التعددية الشكلية في الدوال‪366...............................‬‬
‫‪ .5‬خالصة الفصل‪368................................................‬‬
‫ِّ‬
‫منقح بايثون‪369 ..‬‬
‫تنقيح الشيفرات‪ :‬استخدام‬
‫تفاعليا‪370...............................‬‬
‫‪ .1‬تشغيل منقح بايثون‬
‫ً‬
‫‪ .2‬استخدام المنقح للتنقل ضمن البرنامج‪372 ..................‬‬
‫‪ .3‬نقاط التوقف‪376..................................................‬‬
‫‪ .4‬دمج ‪ pdb‬مع البرامج‪379........................................‬‬
‫‪ .5‬تعديل تسلسل تنفيذ البرنامج ‪380.............................‬‬
‫‪ .6‬جدول بأوامر ‪ pdb‬الشائعة‪384.................................‬‬
‫‪ .7‬الوحدة ‪ :code‬تنقيح الشيفرات من سطر األوامر ‪385 .....‬‬
‫‪ .8‬الوحدة ‪ :Logging‬التنقيح بالتسجيل وتتبع األحداث‪390 .‬‬
‫‪ .9‬خالصة الفصل‪403................................................‬‬
‫إصدارات بايثون‪ :‬اإلصدار ‪ 3‬مقابل ‪404........2‬‬
‫‪ .1‬بايثون ‪405........................................................2‬‬
‫‪ .2‬بايثون ‪405........................................................3‬‬
‫‪ .3‬بايثون ‪406.....................................................2.7‬‬
‫‪ .4‬االختالفات األساسية بين اإلصدارات‪407....................‬‬
‫‪ .5‬نقاط أخرى يجب أخذها بالحسبان‪410 .......................‬‬
‫‪ .6‬ترحيل شيفرة بايثون ‪ 2‬إلى بايثون ‪411....................3‬‬
‫‪ .7‬تعرف على االختالفات بين بايثون ‪ 2‬و بايثون ‪413 ......3‬‬
‫‪ .8‬تحديث الشيفرة‪417..............................................‬‬
‫‪ .9‬التكامل المستمر (‪418...........)Continuous Integration‬‬
‫‪ .10‬خالصة الفصل‪419...............................................‬‬
‫ت‬
‫تقديم‬
‫‪14‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تقديم‬
‫س طع نجم لغ ة البرمج ة ب ايثون في اآلون ة األخ يرة ح تى ب دأت ت زاحم أق وى لغ ات البرمج ة‬
‫في الص دارة وذاك لمزاي ا ه ذه اللغ ة ال تي ال تنحص ر أوله ا س هولة كتاب ة وق راءة ش يفراتها ح تى‬
‫أضحت الخيار األول بين يدي المؤسسات األكاديمية والتدريبية لتدريسها للطالب الجدد الراغ بين‬
‫في الدخول إلى مجال علوم الحاسوب والبرمجة‪ .‬أضف إلى ذلك أن بايثون ً‬
‫لغة متع َّددة األغ راض‬
‫واالس تخدامات‪ ،‬ل ذا فهي دومً ا الخي ار األول في ش تى مج االت عل وم الحاس وب الص اعدة مث ل‬
‫ال ذكاء الص نعي وتعلم اآلل ة وعل وم البيان ات وغيره ا‪ ،‬كم ا َّ‬
‫أنه ا مطلوب ة بش دة في س وق العم ل‬
‫وتعتمدها كبرى الشركات التقنية‪.‬‬
‫جاء هذا الكتاب المترجم عن كتاب «‪ »How to code in Python‬لصاحبته ل يزا ت اغليفيري‬
‫(‪ )Lisa Tagliaferri‬ليش رح المف اهيم البرمجي ة األساس ية بلغ ة ب ايثون‪ ،‬ونأم ل أن يك ون إض ً‬
‫افة‬
‫ً‬
‫ً‬
‫منطلق ا لل دخول إلى ع الم البرمج ة من‬
‫العربية وأن يفيد القارئ العربي في أن يك ون‬
‫نافعة للمكتبة‬
‫َّ‬
‫أوسع أبوابه‪.‬‬
‫هذا الكتاب مرخص بموجب رخصة المش اع اإلب داعي ‪« Creative Commons‬نس ب المُ ص نَّف ‪-‬‬
‫غير تجاري ‪ -‬الترخيص بالمثل ‪»4.0‬‬
‫( ‪)Attribution-NonCommercial-ShareAlike 4.0 - CC BY-NC-SA 4.0‬‬
‫ً‬
‫مفتوحا‪.‬‬
‫تعليميا‬
‫وهو متاح الستخدامه مصدرًا‬
‫ًّ‬
‫نظ رًا لكون ه مت وفرُ ا على هيئ ة كت اب إلك تروني‪ ،‬فبإمكان ك اس تخدام كت اب «البرمج ة بلغ ة‬
‫ً‬
‫واء في‬
‫ً‬
‫مفتوح ا‪ ،‬وبالت الي يمكن اس تخدامه في أي فص ل دراس ي س‬
‫تعليمي ا‬
‫ب ايثون» مرجعً ا‬
‫ً‬
‫المدرسة أو الجامعة‪ ،‬كما يمكن توفير هذا الكتاب اإللكتروني للعامة في المكتبات‪.‬‬
‫‪15‬‬
‫|‬
‫▲‬
‫تقديم‬
‫البرمجة بلغة بايثون‬
‫كيفية‬
‫يمكن استخدام هذا الكتاب اإللكتروني بع دة طرائ ق‪ ،‬وس وف نوض ح في ه ذا التق ديم‬
‫َّ‬
‫التعام ل م ع الكت اب‪ ،‬وكي ف يمكن للمعلمين والطالب اس تخدام الكت اب في فص ولهم الدراس ية‪،‬‬
‫وكي ف يمكن ألمن اء المكتب ات العام ة والجامعي ة توف ير ه ذا الكت اب اإللك تروني ليك ون مرجعً ا‬
‫ً‬
‫ً‬
‫الحق ا‪،‬‬
‫توجيه ا ح ول م ا يجب أن يتعلم ه‬
‫تعليميا‪ .‬أخ يرًا‪ ،‬بالنس بة للق ارئ ال ذي أنهى الكت اب ويري د‬
‫ًّ‬
‫فقد أضفنا بعض المراجع اإلضافية في آخر هذا القسم‪.‬‬
‫‪ .1‬كيفية استخدام هذا الكتاب‬
‫ومنطقية‪ .‬ورغم َّ‬
‫ِّ‬
‫ترتيب ا يناس ب المط ور المبت دئ‪،‬‬
‫أنه ُم رتب‬
‫صمم هذا الكت اب بطريق ة سلس ة‬
‫َّ‬
‫ً‬
‫إال َّ‬
‫أنه ليس علي ك التقي د ب الترتيب‪ :‬اب دأ حيث ش ئت‪ ،‬وأق رأه ب الترتيب ال ذي يناس ب احتياجات ك‪.‬‬
‫بعد إنهاء الكتاب‪ ،‬يمكنك استخدامه مرجعً ا‪.‬‬
‫إذا ق رأت الكت اب ب الترتيب‪ ،‬فس تبدأ رحلت ك في ب ايثون من مقدم ة عام ة ح ول اللغ ة لمن ال‬
‫يعرفه ا‪ ،‬بع د ذل ك‪ ،‬س تتعلم إع داد بيئ ة برمج ة على الجه از المحلي أو على الخ ادم‪ ،‬وس تبدأ تعلم‬
‫البني ة العام ة لش يفرة ب ايثون‪ ،‬وص ياغتها‪ ،‬وأن واع البيان ات فيه ا‪ .‬في ثنِيِّ ات الطري ق‪ ،‬س تتعلم‬
‫أساس يات المنط ق الحس ابي في ب ايثون‪ ،‬وهي مه ارات مفي دة ح تى في لغ ات البرمج ة األخ رى‪.‬‬
‫سنركز في بداية الكتاب على كتاب ة الس كربتات في ب ايثون‪ ،‬ثم س ِّ‬
‫نقدم بالت دريج مف اهيم البرمج ة‬
‫الكائني ة لمس اعدتك على كتاب ة ش يفرات أك ثر مرون ة وتعقي ًدا‪ ،‬م ع تجنب التك رار‪ .‬وفي نهاي ة‬
‫الكت اب‪ ،‬س تتعلم كيفي ة تنقيح ش يفرة ب ايثون‪ ،‬وس نختم بفص ل عن االختالف ات الرئيس ية بين‬
‫بايثون ‪ 3‬واإلصدارات السابقة وكيفية ترحيل شيفرة بايثون من اإلصدار بايثون ‪ 2‬إلى بايثون ‪.3‬‬
‫ا‪ .‬استخدام الكتاب في الفصل الدراسي‬
‫طالب ا‪ ،‬فيمكن ك إطالع معلم ك أو أس تاذك أو قس م الحوس بة على ه ذا الكت اب‬
‫إذا كنت‬
‫ً‬
‫‪16‬‬
‫|‬
‫▲‬
‫تقديم‬
‫البرمجة بلغة بايثون‬
‫اإللك تروني المج اني‪ .‬ق د يوج د في مدرس تك أو جامعت ك مس تودعً ا أو مكتب ًة مفتوح ًة للمراج ع‬
‫ً‬
‫أيض ا مش اركة ه ذا‬
‫التعليمي ة وال تي يمكن ك فيه ا إتاح ة ه ذا الكت اب للطالب أو المعلمين‪ .‬يمكن ك‬
‫الكت اب اإللك تروني م ع األندي ة والمجموع ات ال تي تنتمي إليه ا وال تي ق د تك ون مهتم ة بتعلم‬
‫البرمج ة بلغ ة ب ايثون‪ .‬وإض افة إلى األندي ة وال برامج الخاص ة بعل وم الحاس وب‪ ،‬يمكن أن يس تفيد‬
‫ً‬
‫أيض ا من هذا الكتاب األشخاص الذين يدرسون علم البيانات واإلحصاء والعلوم اإلنسانية الرقمية‪.‬‬
‫ُدرس أو تش رف على ورش ات برمجي ة ِّ‬
‫إذا كنت معلمً ا ت ِّ‬
‫تعلم فيه ا ب ايثون‪ ،‬فيمكن ك اس تخدام‬
‫ً‬
‫مجان ا م ع طالب ك‪ .‬يمكن ك اتب اع ت رتيب فص ول الكت اب‪ ،‬أو يمكن ك‬
‫ه ذا الكت اب التعليمي المفت وح‬
‫ً‬
‫انتقاء الفصول التي تناس ب المُ ق رَّ ر ال ذي ُت ِّ‬
‫أيض ا تكمي ل‬
‫درس ه وف ق ال ترتيب المناس ب ل ك‪ .‬يمكن ك‬
‫ً‬
‫أيض ا‬
‫هذا الكتاب الرقمي ب الكثير من ال دروس والمق االت من أكاديمي ة حس وب أو غيره ا‪ ،‬ويمكن ك‬
‫استخدام موسوعة حسوب مرجعً ا للغة بايثون (وغيرها من اللغات)‪.‬‬
‫ب‪ .‬إضافة الكتاب إلى مكتبتك‬
‫إذا كنت أمين مكتب ة‪ ،‬فيمكن ك إض افة كت اب «البرمج ة بلغ ة ب ايثون» إلى فه رس مكتبت ك‪.‬‬
‫أن تعلم بعض مب ادئ البرمج ة يمكن أن يك ون‬
‫أن ليس ك ل الن اس مهتمين بالبرمج ة‪ ،‬إال َّ‬
‫ص حيح َّ‬
‫الرقمية‪.‬‬
‫األمية‬
‫مفي ًدا في الحياة المهنية‪ ،‬ويساعد على تخفيض‬
‫َّ‬
‫َّ‬
‫‪ .2‬ماذا بعد هذا الكتاب‬
‫عند االنتهاء من هذا الكتاب‪ ،‬يمكن ك االطالع على العدي د من المق االت العملي ة في أكاديمي ة‬
‫حسوب‪ .‬أثناء ذلك‪ ،‬يمكنك التنقل بين توثيق بايثون في موسوعة حسوب وفصول هذا الكتاب‪.‬‬
‫ألي شخص ملم بالبرمجة أن يس اهم في المش اريع مفتوح ة المص در‪ .‬ال برامج مفتوح ة‬
‫يمكن ِّ‬
‫المصدر هي برامج متاحة لالس تخدام وإع ادة التوزي ع والتع ديل دون قي ود‪ .‬تس اعد المس اهمة في‬
‫‪17‬‬
‫|‬
‫▲‬
‫تقديم‬
‫البرمجة بلغة بايثون‬
‫المش اريع مفتوح ة المص در على تحس ين ال برامج‪ ،‬ع بر ض مان تمثيله ا لقاع دة عريض ة من‬
‫المس تخدمين‪ .‬عن دما يس اهم المس تخدمون في المش اريع مفتوح ة المص در‪ ،‬س واء ع بر كتاب ة‬
‫الش يفرة‪ ،‬أو التوثي ق‪ ،‬أو ص يانة المجل دات‪ ،‬ف إنهم ي وفرون قيم ة مض افة للمش روع‪ ،‬ومجتم ع‬
‫المطورين على العموم‪.‬‬
‫للحص ول على مراج ع إض افية عن ب ايثون‪ ،‬أو للمش اركة في نقاش ات م ع اآلخ رين‪ ،‬يمكن ك‬
‫االطالع على المقاالت واألسئلة والدروس عن بايثون في األكاديمية‪.‬‬
‫إذا كنت مهتمً ا بتعلم تطوير تطبيقات الويب أو تطبيقات الجوال‪ ،‬أو تعلم لغ ات مح َّددة مث ل‬
‫روبي وجافاس كربت‪ ،‬ف اطلع على قس م ال دورات في األكاديمي ة‪ ،‬كم ا يمكن ك تص فح موس وعة‬
‫حسوب ألجل قراءة توثيقات عدد كبير من لغات البرمجة باللغة العربية‪.‬‬
‫جميل بيلوني‬
‫‪ - 01‬يوليو ‪2020 -‬‬
‫‪18‬‬
‫|‬
‫▲‬
‫‪1‬‬
‫مدخل تعريفي إلى‬
‫لغة بايثون‬
‫‪19‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫البرمجة بلغة بايثون‬
‫ب ايثون لغ ٌة س هلة الق راءة للغاي ة ومتنوع ة ومتع ددة االس تخدامات‪ ،‬واس مها مس توحى من‬
‫مجموع ة كوميدي ة بريطاني ة باس م « ‪ ،»Monty Python‬وك ان أح د األه داف األساس ية لفري ق‬
‫ً‬
‫مرحة وسهلة االستخدام‪ ،‬وإع دادها بس ٌ‬
‫يط‪ ،‬وطريق ة كتابته ا مباش رة‬
‫تطوير بايثون هو جعل اللغة‬
‫وتعطي ك تقري رًا مباش رًا عن د ح دوث أخط اء‪ ،‬وهي خي ارٌ ممت ٌ‬
‫از للمبت دئين والواف دين الج دد على‬
‫البرمج ة‪ .‬لغ ة ب ايثون هي لغ ة متع ِّددة االس تعماالت‪ ،‬وت دعم مختل ف أنم اط البرمج ة مث ل كتاب ة‬
‫كائنية التوج ه (‪ ،)object-oriented‬وهي مناس ٌ‬
‫بة لألغ راض العام ة‪،‬‬
‫الس كربتات والبرمج ة‬
‫َّ‬
‫واستعمالها يتزايد في سوق العمل إذ تعتم دها منظم ٌ‬
‫ات مث ل « ‪( »United Space Alliance‬ش ركة‬
‫في مجال إرسال مركبات فضائية وتتعاقد معها ناسا) و « ‪( »Industrial Light & Magic‬أستوديو‬
‫للت أثيرات الس ينمائية وللرس وم المتحرك ة)‪ ،‬وت ِّ‬
‫درات كث يرةٍ لمن يري د تعلم لغ ة‬
‫ٍ‬
‫وفر ب ايثون ق‬
‫برمجة جديدة‪.‬‬
‫طورَ ت اللغة في نهاية الثمانينات من القرن الماضي‪ُ ،‬‬
‫ِّ‬
‫ط ِّورَ ت‬
‫ون ِشرَ ت أوّ ل مرة في ع ام ‪ُ ،1991‬‬
‫ٌ‬
‫نشط للغاية في المجتمع‪ .‬وتع ُّد بايثون على َّ‬
‫أنها‬
‫بايثون من قِ بل ‪ ،Guido van Rossum‬وهو عضوٌ‬
‫ب‬
‫ٌ‬
‫ديل عن لغ‬
‫ة ‪ ،ABC‬وأوّ ل إص دار منه ا ك ان يتض من التعام‬
‫ل م ع االس‬
‫تثناءات‬
‫(‪ )exception handling‬وال دوال واألص ناف (‪ )classes‬م ع إمكاني ة الوراث ة فيه ا‪ .‬وع دما ُأ ِ‬
‫نش ئ‬
‫منت دى محادث ة في ‪ Usenet‬باس م ‪ comp.lang.python‬في ‪ ،1994‬فب دأت قاع دة مس تخدمي‬
‫بايثون بالنمو‪ ،‬مما ّ‬
‫وخصوصا لتطوير‬
‫ً‬
‫مهد الطريق لها لتصبح واحدة من أكثر لغات البرمجة شيوعً ا‬
‫البرمجيات مفتوحة المصدر‪.‬‬
‫‪20‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫البرمجة بلغة بايثون‬
‫‪ .1‬تاريخ بايثون‬
‫ظهرت لغة بايثون في أواخر الثمانينيات على يد غيدو فان روسوم (‪،)Guido van Rossum‬‬
‫وق د عُ َّدت خليف ًة للغ ة ‪ .ABC‬كم ا اس تفادت ب ايثون من الكث ير من اللغ ات الس ابقة له ا‪ ،‬مث ل‬
‫‪ Modula-3‬و ‪ C‬و ‪ C++‬و ‪ Algol-68‬و ‪ ،SmallTalk‬وغيرها من اللغات‪.‬‬
‫ُن ِش ر اإلص دار ‪ 2.0‬من لغ ة ب ايثون ع ام ‪ ،2000‬وق د ق َّدم العدي د من الم يزات الجدي دة‪ ،‬مث ل‬
‫الفهمية (‪ ،)List Comprehensions‬ونظ ام كنس المُ همالت (‪ .)garbage collection‬وظه ر‬
‫القوائم‬
‫َّ‬
‫شكل طف ً‬
‫في عام ‪ 2008‬اإلصدار بايثون ‪ ،3.0‬والذي َّ‬
‫ً‬
‫بي د َّ‬
‫متوافق ا تمامً ا م ع‬
‫أنه لم يكن‬
‫رة في اللغ ة‪ْ ،‬‬
‫اإلص دارات الس ابقة‪ ،‬ل ذلك ق رر فري ق التط وير االس تمرار في دعم إص دار أخ ير من سلس لة ب ايثون‬
‫‪ ،2.x‬وهو بايثون ‪ 2.7‬حتى عام ‪.2020‬‬
‫‪ .2‬مميزات لغة بايثون‬
‫تتميز بايثون بعدة أمور عن غيرها من لغات البرمجة‪ ،‬منها‪:‬‬
‫•‬
‫ُّ‬
‫المفتاحية‪،‬‬
‫التعلم‪ :‬يس هل تعلم لغ ة ب ايثون‪ ،‬إذ تت ألف من ع دد قلي ل من الكلم ات‬
‫س))هولة‬
‫َّ‬
‫•‬
‫المقروئية‪ :‬شيفرة لغة بايثون واضحة ومنظمة وسهلة القراءة‪.‬‬
‫•‬
‫سهلة الصيانة‪ :‬شيفرة بايثون سهلة الصيانة إلى حد بعيد‪.‬‬
‫•‬
‫مكتب ))ة قياس ))ية واس)))عة‪ :‬تحت وي مكتب ة ب ايثون القياس ية على ع دد كب ير من الح زم‬
‫وتتميز بصياغة بسيطة وواضحة‪.‬‬
‫المحمولة التي تتوافق مع أنظمة يونكس وويندوز وماك‪.‬‬
‫•‬
‫إمكانية تنفي ذ الش يفرات‬
‫الوض))ع التف))اعلي‪ :‬ت دعم ب ايثون الوض ع التف اعلي‪ ،‬مم ا ي تيح‬
‫َّ‬
‫ً‬
‫مباشرة على سطر األوامر وتنقيحها‪.‬‬
‫‪21‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫•‬
‫البرمجة بلغة بايثون‬
‫متع) ِّ‬
‫)ددة المنص))ات‪ :‬يمكن تش غيل لغ ة ب ايثون على طي ف واس ع من المنص ات واألجه زة‪،‬‬
‫مع االحتفاظ بنفس الواجهة على جميع تلك المنصات‪.‬‬
‫•‬
‫التوس) )عية‪ :‬من أهم مم يزات ب ايثون‪ ،‬ه و توفره ا على ع دد هائ ل من الوح دات‪ ،‬ال تي‬
‫ُّ‬
‫يمكنها توسيع قدرات اللغ ة في ك ل مج االت التط وير‪ ،‬مث ل تحلي ل البيان ات والرس وميات‬
‫ثنائي ة وثالثي ة األبع اد‪ ،‬وتط وير األلع اب‪ ،‬واألنظم ة المدمج ة‪ ،‬والبحث العلمي‪ ،‬وتط وير‬
‫المواقع وغيرها من المجاالت‪.‬‬
‫•‬
‫ِّ‬
‫توفر بايثون واجهات لجميع قواعد البيانات األساسية‪.‬‬
‫قواعد البيانات‪:‬‬
‫•‬
‫الرسومية‪.‬‬
‫الرسوميات‪ :‬تدعم بايثون التطبيقات‬
‫َّ‬
‫•‬
‫َّ‬
‫والمعقدة‪.‬‬
‫دعم البرامج الكبيرة‪ :‬بايثون مناسبة للبرامج الكبيرة‬
‫ستخدم بايثون؟‬
‫‪ .3‬أين ُت‬
‫َ‬
‫ُتس تخ َدم لغ ة ب ايثون في ك ل المج االت‪ ،‬فهي لغ ة برمج ة متع ِّددة األغ راض‪ ،‬ومن مج االت‬
‫اس تخدامها‪ :‬تحلي ل البيان ات‪ ،‬والروبوت ات‪ ،‬وتعلم اآلل ة‪ ،‬وتطبيق ات ‪ ،REST‬وتط وير المواق ع‬
‫واأللع اب‪ ،‬والرس وم ثالثي ة األبع اد‪ ،‬واألتمت ة وبرمج ة األنظم ة المدمج ة‪ ،‬والكث ير من المج االت‬
‫األخرى التي ال يسعنا حصرها هنا‪.‬‬
‫تس تخدم الكث ير من المواق ع والش ركات العمالق ة لغ ة ب ايثون‪ ،‬ومنه ا ‪ Spotify‬و ‪Google‬‬
‫و‪ ،Amazon‬إض افة إلى ‪ Facebook‬ال تي تس تخدم ب ايثون لمعالج ة الص ور‪ .‬وفي ك ل ي وم تتح ول‬
‫ش ركات جدي دة إلى اس تخدام ب ايثون‪ ،‬مث ل ‪ Instagram‬ال تي ق ررت م ؤخ ًرا اس تخدامها وفض لتها‬
‫ً‬
‫والبحثية‪ ،‬مث ل وكال ة الفض اء‬
‫العلمية‬
‫أيض ا من قب ل بعض الجه ات‬
‫على ‪ُ .PHP‬تس تخ َدم ب ايثون‬
‫َّ‬
‫َّ‬
‫األمريكية ناسا‪ ،‬والتي لها مستودع خاص بالمشاريع المُ طورة ببايثون‪.‬‬
‫‪22‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫البرمجة بلغة بايثون‬
‫‪ .4‬لماذا بايثون وليس غيرها؟‬
‫تحدي د أفض ل لغ ة برمج ة للتعلم ق د يك ون مهم ًة ص ً‬
‫عبة‪ .‬ل و س ألت ع َّدة أش خاص عن لغ ة‬
‫البرمج ة ال تي يجب تعلمه ا‪ ،‬فستحص ل على ع دة إجاب ات‪ ،‬ويكفي أن ت دخل على جوج ل وتكتب‬
‫ً‬
‫مختلفة‪ ،‬وجدااًل ال ينتهي حول هذا الموضوع‪.‬‬
‫آراء‬
‫ً‬
‫أفضل لغة برمجة‪ ،‬وستجد‬
‫ال أريد أن أبدأ حرب لغات البرمجة هنا‪ ،‬ولكني سأحاول تقديم بعض الحجج لتبرير لماذا أرى‬
‫وأن تعلم لغ ة ب ايثون مث الي للمبت دئين ال ذين يري دون دخ ول ع الم‬
‫أن ب ايثون هي لغ ة المس تقبل‪،‬‬
‫َّ‬
‫َّ‬
‫البرمجة وعلوم الحاسوب‪.‬‬
‫ا‪ .‬الشعبية‬
‫بحس ب اس تطالع موق ع ‪ ،stackoverflow‬ب ايثون هي لغ ة البرمج ة العامَّ ة األس رع نم وً ا‪ ،‬كم ا‬
‫تمكنت سنة ‪ 2019‬من التفوق على جاف ا ِبع ِّدها أك ثر لغ ة برمج ة متع ددة األغ راض اس تخدامً ا‪ ،‬كم ا‬
‫أنه ا راب ع أك ثر لغ ة تكنولوجي ا برمج ة اس تخدامً ا وراء ‪ JavaScript‬و ‪ CSS/HTML‬و ‪ ،SQL‬كم ا َّ‬
‫َّ‬
‫أنه ا‬
‫ثاني أكثر لغة برمجة محبوبة من قبل المبرمجين‪.‬‬
‫ب ايثون ليس ت لغ ة قويَّ ة وفعال ة وحس ب‪ ،‬كم ا ي دل على ذل ك حقيق ة َّ‬
‫أنه ا أك ثر لغ ة برمج ة‬
‫متع ِّددة األغ راض اس تخدامً ا‪ ،‬ب ل هي ف وق ذل ك محبوب ة من قب ل الم برمجين‪ ،‬وه ذا مؤش ر على‬
‫ً‬
‫مشرقا‪َّ ،‬‬
‫ألنها األسرع نموً ا‪ ،‬فهل ال ي زال ل ديك‬
‫فإن مستقبلها يبدو‬
‫سهولتها‪ ،‬ثم فوق كل ذلك جميعً ا‪،‬‬
‫َّ‬
‫شك في أن تعلم لغة بايثون هو خيار مثالي لك؟!‬
‫المخططان البيانيان التاليان يوضحان شعبية لغة بايثون لدى المبرمجين‪:‬‬
‫‪23‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل تعريفي إلى لغة بايثون‬
‫•‬
‫أكثر لغات البرمجة شعبية (المصدر‪)https://insights.stackoverflow.com/survey/2019 :‬‬
‫•‬
‫در‪:‬‬
‫أك‬
‫ثر لغ‬
‫ات البرمج‬
‫ة المحبوب‬
‫ةل‬
‫دى الم‬
‫برمجين (المص‬
‫‪)https://insights.stackoverflow.com/survey/2019‬‬
‫‪24‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫البرمجة بلغة بايثون‬
‫ب‪ .‬طلب سوق العمل‬
‫يس تخدم ب ايثون بعض أك بر الش ركات في مج ال التكنولوجي ا‪ ،‬مث ل ‪ Uber‬و ‪PayPal‬‬
‫و ‪ Google‬و ‪ Facebook‬و ‪ Instagram‬و ‪ Netflix‬و ‪ Dropbox‬و ‪ .Reddit‬إض‬
‫ً‬
‫افة إلى ه‬
‫ذا‪،‬‬
‫ُتس تخ َدم ب ايثون بكثاف ة في مج ال ال ذكاء االص طناعي والتعلم اآللي وتحلي ل البيان ات وأنظم ة‬
‫المراقبة وغير ذلك‪.‬‬
‫يق در موق ع ‪ ،stackoverflow‬ال دخل الس نوي لمط وري ب ايثون المح ترفين بح والي ‪ 63‬أل ف‬
‫طلبا كبيرًا على لغة بايثون في سوق العمل‪.‬‬
‫أن هناك‬
‫دوالر‪ ،‬وهو مبلغ كبير‪ ،‬ويدل على َّ‬
‫ً‬
‫ج‪ .‬الدعم‬
‫تقريب ا‪ .‬و ِبع ِّدها اللغ ة‬
‫نظ ًرا لشعبيتها الكبيرة‪ ،‬تتمتع بايثون بدعم جيد على جميع المس تويات‬
‫ً‬
‫المفض لة للمبت دئين‪ ،‬فهن اك قن اطير من المراج ع والم واد وال دورات التعليمي ة ال تي تش رح مف اهيم‬
‫األساسية‪ ،‬إضافة إلى صياغة اللغة وتطبيقاتها‪.‬‬
‫البرمجة‬
‫َّ‬
‫س واء كنت هاويً ا‪ ،‬وتحب تعلم البرمج ة هواي ًة‪ ،‬أو ألج ل اس تخدامها في مج ال عمل ك‪ ،‬مث ل‬
‫الطبيعية وغ ير ذل ك‪ ،‬أو كنت تري د أن تعم ل عماًل مس تقاًل ‪ ،‬أو‬
‫تحلي ل البيان ات ومعالج ة اللغ ات‬
‫َّ‬
‫تدخل سوق العمل وتحق ق دخاًل من البرمج ة‪ ،‬ففي جمي ع ه ذه الح االت‪ ،‬س يكون تعلم لغ ة ب ايثون‬
‫مثاليا لك‪.‬‬
‫خيا ًرا‬
‫ً‬
‫‪25‬‬
‫|‬
‫▲‬
‫مدخل تعريفي إلى لغة بايثون‬
‫البرمجة بلغة بايثون‬
‫‪ .5‬خالصة الفصل‬
‫وكائنية‪ ،‬وواح دة‬
‫بايثون هي لغة برمجة عالية المستوى‪ ،‬ومُ ترجمَ ة (‪ )interpreted‬وتفاعلية‬
‫َّ‬
‫دءا من ألع اب‬
‫من أشهر لغات البرمجة وأكثره ا اس تخدامً ا‪ ،‬ويمكن اس تخدامها في ك ل المج االت‪ ،‬ب ً‬
‫ُّ‬
‫والتعلم اآللي‪.‬‬
‫الفيديو ومعالجة اللغات‪ ،‬وحتى تحليل البيانات‬
‫أضف إلى ذلك أنها تتمتع بمقروئي ة عالي ة‪ ،‬إذ تس تخدم كلم ات إنجليزي ة بس يطة‪ ،‬على خالف‬
‫ياغية‬
‫اإلمالئية والص‬
‫أن قواع دها‬
‫َّ‬
‫َّ‬
‫اللغ ات األخ رى ال تي تس تخدم الرم وز والكلم ات المختص رة‪ ،‬كم ا َّ‬
‫بسيطة‪ ،‬ما يجعل تعلمها سهاًل‬
‫ً‬
‫موازنة مع لغ ات برمجي ة أخ رى‪ .‬وه ذا ه و الس بب الرئيس ي العتم اد‬
‫الجامعات ومختلف دورات البرمج ة التدريبي ة تدريس ها في البداي ة لمن يري د ال دخول إلى مج ال‬
‫خصوصا‪.‬‬
‫ً‬
‫علوم الحاسوب عمومً ا والبرمجة‬
‫‪26‬‬
‫|‬
‫▲‬
‫‪2‬‬
‫تثبيت بايثون‬
‫وإعداد بيئة العمل‬
‫‪27‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫بع د أن أخ ذت فك رة عام ة عن لغ ة البرمج ة ب ايثون وتع رفت على تاريخه ا وإص داراتها ‪ -‬في‬
‫الفصل السابق ‪ -‬سيرشدك هذا الفصل إلى كيفي ة تث بيت ب ايثون على نظ ام تش غيلك وإع داد البيئ ة‬
‫البرمجية الالزمة لكتابة البرامج وتنفيذها خالل رحلتك التعليمية هذه‪.‬‬
‫األم ور ال تي سنس لط الض وء عليه ا هي‪ :‬تث بيت ب ايثون ‪ 3‬ثم إع داد بيئته ا البرمجي ة ال تي‬
‫ِّ‬
‫َّ‬
‫تمكن ك من إنش اء مس احة معزول ة في حاس وبك مخصص ة لمش اريع‬
‫وهمية‬
‫تتمثل بإع داد بيئ ة‬
‫َّ‬
‫أن ك ل مش روع تعم ل علي ه يمل ك مجموع ة من االعتمادي ات (‪)dependencies‬‬
‫ب ايثون‪ ،‬مم ا يع ني َّ‬
‫ؤثر على غيره ا من المش اريع‪ .‬ي ِّ‬
‫وال تي لن ت ِّ‬
‫وفر لن ا ذل ك تحكمً ا أك بر بمش اريع ب ايثون وإمكاني ة‬
‫دارات مختلف ةٍ من حزمه ا وه ذا مهمٌ عن دما تتعام ل م ع الح زم الخارجي ة‪ .‬سننش ئ‬
‫ٍ‬
‫التعامل م ع إص‬
‫ً‬
‫ً‬
‫بسيطا يعرض العبارة "!‪( "Hello World‬أهاًل بالعالم!) الشهيرة‪ ،‬وبهذا س نتحقق من‬
‫برنامجا‬
‫بعدئذٍ‬
‫عمل البيئة عماًل‬
‫ً‬
‫ً‬
‫مألوفة لديك مم ا‬
‫صحيحا‪ ،‬وستصبح آنذاك طريقة إنشاء برامج بايثون وتنفيذها‬
‫ِّ‬
‫يمهد الطريق لكتابة وتنفيذ مشاريع بايثون الالحقة‪.‬‬
‫اخ تر مم ا يلي القس م الخ اص بنظ ام تش غيل حاس وبك (حاولن ا ش مل أش هر أنظم ة التش غيل‪،‬‬
‫لينكس وويندوز وماك) وانتقل إليه التباع الخطوات الالزمة لتنفيذ ما سبق‪.‬‬
‫•‬
‫ويندوز‬
‫•‬
‫لينكس‬
‫•‬
‫◦‬
‫أوبنتو‬
‫◦‬
‫دبيان‬
‫◦‬
‫سينتوس‬
‫ماك‬
‫‪28‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫‪ .1‬ويندوز‬
‫ً‬
‫سي ِ‬
‫خطوة بخطوة إلى كيفية تثبيت بايثون ‪ 3‬في ويندوز ‪ ،10‬وتثبيت بيئة‬
‫رش ُدك هذا القسم‬
‫ُ‬
‫برمجة خاصة بها عبر سطر األوامر‪.‬‬
‫ا‪ .‬المتطلبات المسبقة‬
‫يجب أن تمل ك جه ً‬
‫ازا علي ه نظ ام وين دوز ‪ 10‬متص ل بالش بكة م ع ص الحيات م دير‬
‫(‪.)administrative access‬‬
‫ب‪ .‬فتح وإعداد ‪PowerShell‬‬
‫سنجري معظم أطوار التثبيت واإلعدادات عبر سطر األوامر‪ ،‬والذي ه و طريق ٌة غ يرُ رس وميةٍ‬
‫نص ا وتعطي ه للحاس وب لينف ذه‪،‬‬
‫للتعام ل م ع الحاس وب‪ ،‬فب داًل من الض غط على األزرار‪ ،‬س تكتب ًّ‬
‫ً‬
‫ً‬
‫أيضا‪ .‬يمكن أن يساعدك سطر األوامر على تعديل أو أتمتة مختلف المه ام‬
‫نصيا‬
‫ناتجا‬
‫ظهر لك‬
‫ُ‬
‫ً‬
‫وسي ِ‬
‫ٌ‬
‫ٌ‬
‫أساسية لمطوري البرمجيات‪.‬‬
‫أداة‬
‫يوميا‪ ،‬وهو‬
‫التي تنجزها على الحاسوب‬
‫ً‬
‫‪ PowerShell‬هي برن امج من ميكروس وفت ي وفر واجه ة س طر األوام ر‪ .‬يمكن إج راء المه ام‬
‫اإلدارية عبر تنفي ذ األص ناف ‪ ،cmdlets‬وال تي ُت َ‬
‫نط ق "‪ ،"command-lets‬وهي أص ناف متخصص ة‬
‫من اإلط ار ‪ .NET‬يمكنه ا تنفي ذ العملي ات‪ُ .‬جعِ لت ‪ PowerShell‬مفتوح ة المص در من ذ أغس طس‬
‫‪ ،2016‬وصارت متوفرة اآلن عبر ويندوز وأنظمة يونكس (بما في ذلك ماك ولينكس)‪.‬‬
‫س تعثر على ‪ PowerShell‬ب النقر األيمن على أيقون ة ‪ Start‬في ال ركن األيس ر الس فلي من‬
‫الشاش ة‪ .‬عن دما تنبث ق القائم ة‪ ،‬انق ر على " ‪ ،"Search‬ثم اكتب "‪ "PowerShell‬في ش ريط البحث‪.‬‬
‫عند تقديم خيارات لك‪ ،‬انقر بالزر األيمن على تطبيق سطح المكتب "‪."Windows PowerShell‬‬
‫‪29‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫اختر "‪ ."Run as Administrator‬عندما يظهر مربع حوار يسألك‪:‬‬
‫?‪Do you want to allow this app to make changes to your PC‬‬
‫انقر على "‪ ."Yes‬بمجرد إتمام ذلك‪ ،‬سترى واجهة نصية تبدو كما يلي‪:‬‬
‫يمكننا تبديل مجلد النظام عن طريق كتابة األمر التالي‪:‬‬
‫~ ‪cd‬‬
‫بعد ذلك سننتقل إلى المجلد ‪.PS C:\Users\Sammy‬‬
‫لمتابع ة عملي ة التث بيت‪ ،‬س نع ّد بعض األذون ات من خالل ‪ .PowerShell‬تم إع داد‬
‫ً‬
‫أمانا بشكل افتراضي‪.‬‬
‫‪ PowerShell‬لتعمل في الوضع األكثر‬
‫‪30‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫هناك عدة مستويات لألذونات‪ ،‬والتي يمكنك إعدادها بوصفك مدي ًرا (‪:)administrator‬‬
‫•‬
‫‪ :Restricted‬يمث ل سياس ة التنفي ذ االفتراض ية‪ ،‬وبم وجب ه ذا الوض ع‪ ،‬لن تتمكن من‬
‫تنفي‬
‫ذ الس‬
‫كربتات‪ ،‬وس‬
‫تعمل ‪ PowerShell‬بوص‬
‫فها ص‬
‫ً‬
‫دفة تفاعلي‬
‫ًة (أي‬
‫‪ )interactive shell‬وحسب‪.‬‬
‫•‬
‫ِّ‬
‫سيمكنك من تنفيذ جميع السكربتات وملفات اإلعداد المُ َّ‬
‫وقع ة من قب ل جه ة‬
‫‪:AllSigned‬‬
‫موثوق ة‪ ،‬مم ا يع ني أن ه من المحتم ل أن ُتع ِّرض جه ازك لخط ر تنفي ذ س كربتات ض ارة إن‬
‫َّ‬
‫موقعة من جهة غير موثوقة‪.‬‬
‫كانت‬
‫•‬
‫ِّ‬
‫تمكنك من تنفي ذ الس كربتات وملف ات اإلع داد المُ َّ‬
‫نزل ة من الش بكة‪،‬‬
‫‪ :RemoteSigned‬س‬
‫والمُ َّ‬
‫وقعة من جه ة موثوق ة‪ ،‬مم ا يع ني احتم ال أن تع ِّرض جه ازك لخط ر تنفي ذ س كربتات‬
‫ضارة إن كانت تلك السكربتات الموثوقة ضارة‪.‬‬
‫•‬
‫‪ :Unrestricted‬تس مح بتنفي ذ جمي ع الس كربتات وملف ات اإلع داد المُ َّ‬
‫نزل ة من الش بكة‬
‫نز ٌ‬
‫بمجرد تأكي د َّ‬
‫أن المل ف ُم َّ‬
‫ل من الش بكة‪ .‬في ه ذه الحال ة‪ ،‬التوقيع ات الرقمي ة‬
‫أنك ت درك ّ‬
‫غير الزمة‪ ،‬مما يعني أ َن ه من المحتمل تعريض جهازك لخطر تنفيذ سكربتات غير موثوق ة‬
‫منزلة من الشبكة قد تكون ضارة‪.‬‬
‫سنس تخدم سياس ة التنفي ذ ‪ RemoteSigned‬لتع يين اإلذن للمس تخدم الح الي‪ ،‬وهك ذا‬
‫سنسمح لبرنامج ‪ PowerShell‬بقب ول الس كربتات المُ َّ‬
‫نزل ة ال تي نث ق به ا‪ ،‬ودون خفض ك ل دفاعاتن ا‬
‫وجعل األذونات َّ‬
‫هشة كما هو الحال مع سياسة التنفيذ ‪ .Unrestricted‬سنكتب في ‪:PowerShell‬‬
‫‪Set-ExecutionPolicy -Scope CurrentUser‬‬
‫س تطالبك ‪ PowerShell‬بتحدي د سياس ة التنفي ذ‪ ،‬وبم ا َّ‬
‫أنن ا نري د اس تخدام‬
‫‪ ،RemoteSigned‬فسنكتب‪:‬‬
‫‪RemoteSigned‬‬
‫‪31‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫بمجرد الضغط على ال زر اإلدخ ال (‪ُ ،)enter‬‬
‫ستس أل عم ا إن كنت نري د تغي ير سياس ة التنفي ذ‪.‬‬
‫اكتب الح رف ‪ y‬الختي ار "نعم"‪ ،‬واعتم اد التغي يرات‪ .‬يمكنن ا التحق ق من نج اح العملي ة عن طري ق‬
‫طلب األذونات الحالية في الجهاز عبر كتابة‪:‬‬
‫‪Get-ExecutionPolicy -List‬‬
‫ستحصل على مخرجات مشابهة لما يلي‪:‬‬
‫‪Scope ExecutionPolicy‬‬
‫‪----- --------------‬‬‫‪Undefined‬‬
‫‪MachinePolicy‬‬
‫‪Undefined‬‬
‫‪UserPolicy‬‬
‫‪Undefined‬‬
‫‪Process‬‬
‫‪RemoteSigned‬‬
‫‪CurrentUser‬‬
‫‪Undefined‬‬
‫‪LocalMachine‬‬
‫أن المس تخدم الح الي يمكن ه تنفي ذ الس كربتات الموثوق ة ال تي ِّ‬
‫نُزلت من الش بكة‪.‬‬
‫ه ذا يؤك د َّ‬
‫يمكننا اآلن تنزيل الملفات التي سنحتاج إليها إلعداد بيئة برمجة بايثون‪.‬‬
‫ج‪ .‬تثبيت ‪Chocolatey‬‬
‫م دير الح زم (‪ )package manager‬ه و مجموع ة من أدوات البرمجي ات ال تي تعم ل على‬
‫أتمت ة عملي ات التث بيت‪ ،‬بم ا في ذل ك التث بيت األولي لل برامج‪ ،‬وترقيته ا‪ ،‬وإع دادها‪ ،‬وإزالته ا‬
‫عند الحاجة‪.‬‬
‫تحف ظ ه ذه األدوات التثبيت ات في موق ع مرك زي‪ ،‬ويمكنه ا ص يانة جمي ع ح زم ال برامج على‬
‫النظام وفق تنسيقات (‪ )formats‬معروفة‪.‬‬
‫يع د ‪ Chocolatey‬م دير ح زم مفت وح المص در يعم ل من س طر األوام ر‪ ،‬ص ِّمم لنظ ام وين دوز‪،‬‬
‫‪32‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
.‫ ويمكنه مس اعدتك على تث بيت التطبيق ات واألدوات بس رعة‬،‫ الخاص بلينكس‬apt-get ‫وتحاكي‬
.‫سنستخدمه لتنزيل ما نحتاج إليه لبيئتنا التطويرية‬
.‫أن التغييرات التي سيجريها على الجهاز مقبولة‬
َّ ‫ دعنا نقرؤه للتأكد من‬،‫قبل تثبيت السكربت‬
‫ سننش ئ‬.‫ في ناف ذة الطرفي ة‬Chocolatey ‫ لتنزي ل وع رض الس كربت‬.NET ‫سنستخدم إط ار العم ل‬
‫ في‬$ ‫ (يمكن ك تس ميته كم ا تري د طالم ا ستس تخدم المح رف‬$script ‫ يُ س مى‬WebClient ‫كائ ًن ا‬
:Internet Explorer ‫ والذي يشارك إعدادات االتصال بالشبكة مع المتصفح‬،)‫البداية‬
$script = New-Object Net.WebClient
‫دعن ا نلقي نظ رة على الخي ارات المتاح ة لن ا من خالل توص يل الك ائن إلى الص نف‬
:WebClient ‫ إلعادة جميع األعضاء (الخاصيات والتوابع) الخاصة بكائن‬Get-Member
$script | Get-Member
:‫سنحصل على المخرجات التالية‬
. . .
DownloadFileAsync
Method
void DownloadFileAsync(uri
address, string fileName), void DownloadFileAsync(ur...
DownloadFileTaskAsync
Method
System.Threading.Tasks.Task
DownloadFileTaskAsync(string address, string fileNa...
DownloadString
Method
string DownloadString(string
address), string DownloadString(uri address) # ‫هذا التابع‬
DownloadStringAsync
Method
void DownloadStringAsync(uri
address), void DownloadStringAsync(uri address, Sy...
DownloadStringTaskAsync
Method
System.Threading.Tasks.Task[string]
DownloadStringTaskAsync(string address), Sy…
. . .
▲
|
33
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫عن د النظ ر إلى المخرج ات‪ ،‬يمكنن ا تحدي د الت ابع ‪ DownloadString‬ال ذي يمكنن ا اس تخدامه‬
‫لعرض محتوى السكربت والتوقيع في نافذة ‪ PowerShell‬كما يلي‪:‬‬
‫)"‪$script.DownloadString("https://chocolatey.org/install.ps1‬‬
‫بعد مطالعة السكربت‪ ،‬يمكننا تثبيت ‪ Chocolatey‬عن طريق كتابة ما يلي في ‪:PowerShell‬‬
‫‪iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex‬‬
‫تس مح لن ا ‪ iwr‬أو ‪ Invoke-WebRequest‬ال تي تخص ‪ cmdlet‬باس تخراج البيان ات من‬
‫الش بكة‪ .‬س يؤدي ه ذا إلى تمري ر الس كربت إلى ‪ iex‬أو ‪ ،Invoke-Expression‬وال ذي س ينفذ‬
‫محتويات السكربت‪ ،‬وتنفيذ سكربت التثبيت لمدير الحزم ‪.Chocolatey‬‬
‫اسمح لبرنامج ‪ PowerShell‬بتث بيت ‪ .Chocolatey‬بمج رد تثبيت ه بالكام ل‪ ،‬يمكنن ا الب دء في‬
‫تثبيت أدوات إضافية باستخدام األمر ‪.choco‬‬
‫إن احتجت إلى ترقية ‪ Chocolatey‬مستقباًل ‪ ،‬يمكنك تنفيذ األمر التالي‪:‬‬
‫‪choco upgrade chocolatey‬‬
‫بعد تثبيت مدير الحزم‪ ،‬يمكننا متابعة تثبيت ما نحتاجه لبيئة البرمجة خاصتنا‪.‬‬
‫د‪ .‬تثبيت محرر النصوص ‪( nano‬اختياري)‬
‫س نثبِّت اآلن ‪ ،nano‬وه و مح ِّرر نص وص يس تخدم واجه ة س طر األوام ر‪ ،‬وال ذي يمكنن ا‬
‫استخدامه لكتابة البرامج مباشرة داخل ‪ .PowerShell‬ه ذه ليس ت خط وة إلزامي ة‪ ،‬إذ يمكن ك ب دال‬
‫من ذلك استخدام محرر نص وص بواجه ة مس تخدم رس ومية مث ل ‪ ،Notepad‬لكن م يزة ‪ nano‬أنه‬
‫س ُي ِّ‬
‫عودك على اس تخدام ‪ .PowerShell‬دعن ا نس تخدم ‪ Chocolatey‬لتث بيت ‪ nano‬وذل ك بتنفي ذ‬
‫األمر التالي‪:‬‬
‫‪34‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪choco install -y nano‬‬
‫الخيار ‪ -y‬يعني َّ‬
‫تلقائي ا دون الحاج ة إلى تأكي د‪ .‬بع د تث بيت‬
‫أنك توافق على تنفي ذ الس كربت‬
‫ً‬
‫‪ ،nano‬سنكون قادرين على استخدام األمر ‪ nano‬إلنشاء ملف ات نص ية جدي دة‪ ،‬وسنس تخدمه بع د‬
‫حين لكتابة أول برامجنا في بايثون‪.‬‬
‫ه‪ .‬تثبيت بايثون ‪3‬‬
‫مثلما فعلنا مع ‪ nano‬أعاله‪ ،‬سنستخدم ‪ Chocolatey‬لتثبيت بايثون ‪:3‬‬
‫‪choco install -y python3‬‬
‫س تثبِّت ‪ PowerShell‬اآلن ب ايثون ‪ ،3‬م ع ع رض بعض المخرج ات أثن اء العملي ة‪ .‬بع د اكتم ال‬
‫العملية‪ ،‬سترى المخرجات التالية‪:‬‬
‫‪Environment Vars (like PATH) have changed. Close/reopen your‬‬
‫‪shell to‬‬
‫‪See the changes (or in powershell/cmd.exe just type‬‬
‫‪'refreshenv').‬‬
‫‪The install of python3 was successful.‬‬
‫‪likely‬‬
‫‪Software installed as 'EXE', install location is‬‬
‫‪default.‬‬
‫‪Chocolatey installed 1/1 packages. 0 packages failed.‬‬
‫\‪See the log for details (C:\ProgramData\chocolatey\logs‬‬
‫‪chocolatey.log).‬‬
‫بعد االنتهاء من التث بيت‪ ،‬س تحتاج إلى التحق ق من تث بيت ب ايثون وجهوزيته ا للعم ل‪ .‬لرؤي ة‬
‫التغي يرات‪ ،‬اس تخدم األم ر ‪ refreshenv‬أو أغل ق ‪ PowerShell‬ثم أع د فتحه ا بص الحيات م دير‬
‫‪35‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫النظام‪ ،‬ثم تحقق من إصدار بايثون على جهازك‪:‬‬
‫‪python -V‬‬
‫المثبت‪.‬‬
‫ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون‬
‫َّ‬
‫‪Python 3.7.0‬‬
‫ٌ‬
‫أداة تعم ل م ع لغ ة ب ايثون ُت َثبِّ ت وت دير الح زم‬
‫س نثبِّ ت األداة ‪ ،pip‬إلى ج انب ب ايثون‪ ،‬وهي‬
‫البرمجي ة ال تي ق د نحت اج إلى اس تخدامها في تط وير مش اريعنا (س نتعلم المزي د عن الوح دات‬
‫المخصص للوحدات)‪.‬‬
‫َّ‬
‫والحزم التي يمكنك تثبيتها باألداة ‪ pip‬في الفصل‬
‫ِّ‬
‫سنحدث ‪ pip‬عبر األمر التالي‪:‬‬
‫‪python -m pip install --upgrade pip‬‬
‫يمكنن ا اس تدعاء ب ايثون من ‪ Chocolatey‬ع بر األم ر ‪ .python‬سنس تخدم الراي ة ‪ -m‬لتنفي ذ‬
‫الوحدة كأنها سكربت‪ ،‬وإنهاء قائمة الخيارات‪ ،‬ومن ثمَّ نستخدم ‪ pip‬لتثبيت اإلصدار األحدث‪.‬‬
‫بع د تث بيت ب ايثون وتح ديث ‪ ،pip‬فنحن ج اهزون إلع داد بيئ ة افتراض ية لمش اريع‬
‫التطوير خاصتنا‪.‬‬
‫و‪ .‬إعداد بيئة افتراضية‬
‫اآلن بع د تث بيت ‪ Chocolatey‬و ‪ nano‬وب ايثون‪ ،‬يمكنن ا المض ي ق دمً ا إلنش اء بيئ ة البرمج ة‬
‫خاصتنا عبر الوحدة ‪.venv‬‬
‫ُت ِّ‬
‫مكن ك البيئ ات االفتراض ية من إنش اء مس احة معزول ة في حاس وبك مخصص ة لمش اريع‬
‫أن كل مشروع تعمل عليه ستكون له اعتماديَّ ات ه (‪ )dependencies‬الخاص ة ب ه‪،‬‬
‫بايثون‪ ،‬مما يعني َّ‬
‫ِّ‬
‫تؤثر على غيره من المشاريع‪.‬‬
‫والتي لن‬
‫‪36‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫ي ِّ‬
‫دارات‬
‫ٍ‬
‫وفر لن ا ض بط بيئ ةٍ برمجي ةٍ تحكمً ا أك بر بمش اريع ب ايثون‪ ،‬وإمكاني ة التعام ل م ع إص‬
‫مختلفةٍ من حزم بايثون‪ .‬وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية‪.‬‬
‫أي ع ددٍ تش اء من البيئ ات االفتراض َّية‪ ،‬وك ل بيئ ة س تكون ممثل ة بمجل د في‬
‫يمكن ك ض بط ِّ‬
‫حاسوبك يحتوي على عدد من السكربتات‪.‬‬
‫اختر المجلد الذي تريد أن تضع فيه بيئات ب ايثون‪ ،‬أو يمكن ك إنش اء مجل د جدي د باس تخدام‬
‫األمر ‪ mkdir‬كما يلي‪:‬‬
‫‪mkdir environments‬‬
‫‪cd environments‬‬
‫َ‬
‫انتقلت إلى المجلد الذي تريد احت واء البيئ ات في ه‪ ،‬تس تطيع اآلن إنش اء بيئ ة جدي دة‬
‫بعد أن‬
‫بتنفيذ األمر التالي‪:‬‬
‫‪python -m venv my_env‬‬
‫س ِّ‬
‫ننفذ باس تخدام األم ر ‪ python‬الوح دة ‪ venv‬إلنش اء البيئ ة االفتراض ية ال تي أطلقن ا عليه ا‬
‫في هذه الحالة ‪.my_env‬‬
‫ستنش ئ ‪ venv‬مجل ًدا جدي ًدا يحت وي على بعض العناص ر ال تي يمكن عرض ها باس تخدام‬
‫األمر ‪:ls‬‬
‫‪ls my_env‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪Length Name‬‬
‫‪LastWriteTime‬‬
‫‪Mode‬‬
‫‪------ ----‬‬
‫‪-------------‬‬
‫‪----‬‬
‫‪Include‬‬
‫‪2:20 PM‬‬
‫‪8/22/2016‬‬
‫‪d-----‬‬
‫‪37‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪2:20 PM‬‬
‫‪8/22/2016‬‬
‫‪d-----‬‬
‫‪Lib‬‬
‫‪Scripts‬‬
‫‪2:20 PM‬‬
‫‪8/22/2016‬‬
‫‪d-----‬‬
‫‪107 pyvenv.cfg‬‬
‫‪2:20 PM‬‬
‫‪8/22/2016‬‬
‫‪-a----‬‬
‫تعم ل ه ذه الملف ات م ع بعض ها لض مان أن تك ون مش اريعك معزول ٌة عن س ياق اآلل ة المحلي ة‪،‬‬
‫أن‬
‫لكي ال تختلط ملفات النظ ام م ع ملف ات المش اريع‪ .‬وه ذا أم رٌ حس ٌن إلدارة اإلص دارات ولض مان َّ‬
‫الحزم التي يحتاجها‪.‬‬
‫كل مشروع يملك وصواًل إلى‬
‫ٍ‬
‫عليك تفعيل البيئة الستخدامها‪ ،‬وذلك بكتاب ة األم ر الت الي ال ذي س ُي ِّ‬
‫نفذ س كربت التفعي ل في‬
‫المجلد ‪:Scripts‬‬
‫‪my_env\Scripts\activate‬‬
‫ٌ‬
‫ابقة (‪ )prefix‬في المِ َحث (‪ )prompt‬وال تي هي اس م البيئ ة‬
‫يجب أن تظه ر اآلن س‬
‫المستخدمة‪ ،‬وفي حالتنا هذه يكون اسمها ‪.my_env‬‬
‫>‪(my_env) PS C:\Users\Sammy\Environments‬‬
‫حاليا‪ ،‬وهذا يع ني َّ‬
‫أنن ا لن سنس تخدم إال‬
‫أن البيئة ‪ my_env‬مفعَّ لة‬
‫تتيح لنا هذه البادئة معرفة َّ‬
‫ً‬
‫إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة‪.‬‬
‫ز‪ .‬إنشاء برنامج بسيط‬
‫ِ‬
‫لننش ئ برنامج ا بس يطا يع رض العب ارة «مرحب ا‬
‫بع د أن أكملن ا ض بط بيئتن ا االفتراض ية‪،‬‬
‫أن البيئ ة تعم ل بالش كل الص حيح‪ ،‬ولكي تتع وَّ د على إنش اء ب رامج‬
‫بالع الم!»‪ ،‬وبه ذا س نتحقق من َّ‬
‫َ‬
‫كنت واف ًدا جدي ًدا على اللغة‪.‬‬
‫بايثون إن‬
‫علينا أواًل تشغيل المحرر ‪ nano‬وإنشاء ملف جديد‪:‬‬
‫‪38‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪(my_env) PS C:\Users\Sammy> nano hello.py‬‬
‫بعد فتح الملف في نافذة الطرفية‪ ،‬سنكتب البرنامج الخاص بنا‪:‬‬
‫)"!‪print("Hello, World‬‬
‫أغلق محرر ‪ nano‬بالضغط على ‪ Ctrl+x‬ثم اضغط على ‪ y‬عندما يسألك عن حفظ الملف‪.‬‬
‫بعد أن يُ َ‬
‫غلق المُ ِّ‬
‫حرر ‪ nano‬وتعود إلى سطر األوامر‪ ،‬حاول تنفيذ البرنامج‪:‬‬
‫‪(my_env) PS C:\Users\Sammy> python hello.py‬‬
‫َ‬
‫أنشأته إلى طباعة الناتج التالي في الطرفية‪:‬‬
‫سيؤدي برنامج ‪ hello.py‬الذي‬
‫!‪Hello, World‬‬
‫للخروج من البيئة‪ ،‬اكتب األمر ‪ deactivate‬وستعود إلى مجلدك األص لي‪ .‬ح ان اآلن ال وقت‬
‫للتعم ق بلغ ة ب ايثون وإنش اء ب رامج رائع ة! انتق ل إلى الفص ل الت الي‪ ،‬اس تخدام س طر أوام ر‬
‫بايثون التفاعلي‪.‬‬
‫‪39‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪ .2‬أوبنتو‬
‫رش ُدك ه ذا القس م خط ً‬
‫سي ِ‬
‫وة بخط وة إلى كيفي ة تث بيت ب ايثون ‪ 3‬على خ ادم أوبنت و ‪،20.04‬‬
‫ُ‬
‫البرمجة على الخوادم لها العديد من الميزات‪ ،‬كما تدعم المشاريع التعاونية‪.‬‬
‫أن المف اهيم‬
‫ٌ‬
‫ص‬
‫أن ه ذا القس م يش رح عملي ة التث بيت على خ ادم أوبنت و ‪ ،20.04‬إال َّ‬
‫حيح َّ‬
‫األساسية فيه تنطبق على جميع توزيعات دبيان لينكس (‪.)Debian Linux‬‬
‫ا‪ .‬المتطلبات المسبقة‬
‫يجب أن تملك ص الحيات مس تخدم غ ير ج ذري (‪ ) non-root user‬م ع امتي ازات ‪ sudo‬على‬
‫خ ادم أوبنت و ‪ .20.04‬إذا لم تكن ل ك خ برة في التعام ل م ع بيئ ة الناف ذة الطرفي ة‪ ،‬فيمكن ك مطالع ة‬
‫طرفيِة لينكس ‪.»Linux Terminal‬‬
‫المقال «مدخل إلى‬
‫ّ‬
‫ب‪ .‬إعداد بايثون ‪3‬‬
‫مثبت ة مس ً‬
‫بقا‪.‬‬
‫في أوبنتو ‪ 20.04‬واإلصدارات األخ رى من دبي ان لينكس‪ ،‬س تجد أن ب ايثون ‪3‬‬
‫َّ‬
‫للتأك‬
‫أن إص‬
‫د من َّ‬
‫دارات ب‬
‫ايثون حديث‬
‫ة‪ ،‬س‬
‫ِّ‬
‫نحدث النظ‬
‫َّ‬
‫ونرقي‬
‫ام‬
‫تخدام‬
‫ه باس‬
‫األمر ‪ apt‬للعمل مع أداة التحزيم المتقدمة من أوبنتو ( ‪:)Ubuntu’s Advanced Packaging Tool‬‬
‫‪sudo apt update‬‬
‫‪sudo apt -y upgrade‬‬
‫الخي ار ‪ -y‬يع ني َّ‬
‫أنك تواف ق على تث بيت جمي ع الح زم القابل ة للتح ديث‪ ،‬لكن ق د تحت اج إلى‬
‫تأكي د ذل ك عن د تح ديث النظ ام وذل ك اعتم ا ًدا على الح زم ال تي س ُتح َّدث‪ ،‬ونس خة نظام ك‪ .‬بع د‬
‫ثبت في النظام بكتابة‪:‬‬
‫إكمال العملية‪ ،‬يمكن التحقق من إصدار بايثون ‪ 3‬المُ َّ‬
‫‪40‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪python3 -V‬‬
‫المثبت‪ .‬قد يختلف‬
‫ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون‬
‫َّ‬
‫ً‬
‫شبيها بما يلي‪:‬‬
‫بناء على النسخة المثبتة في توزيعتك‪ ،‬لكن يجب أن يكون‬
‫ً‬
‫الرقم‬
‫‪Python 3.8.2‬‬
‫ٌ‬
‫أداة تعم ل م ع لغ ة ب ايثون ُت َثبِّت‬
‫إلدارة الحزم البرمجي ة الخاص ة بب ايثون‪ ،‬س نثبِّ ت ‪ ،pip‬وهي‬
‫وتدير الح زم البرمجي ة ال تي ق د نحت اج إلى اس تخدامها في تط وير مش اريعنا (س نتعلم المزي د عن‬
‫المخصص للوحدات)‪:‬‬
‫َّ‬
‫الوحدات والحزم التي يمكنك تثبيتها باألداة ‪ pip‬في الفصل‬
‫‪sudo apt install -y python3-pip‬‬
‫يمكن تثبيت حزم بايثون بكتابة ما يلي مع تبديل ‪ package_name‬باسم الحزمة‪:‬‬
‫‪pip3 install package_name‬‬
‫علي ك وض ع اس م الحزم ة أو المكتب ة التابع ة لب ايثون مك ان ‪ package_name‬مث ل ‪Django‬‬
‫لتط وير ال ويب‪ ،‬أو ‪ NumPy‬لتثبيته ا؛ ل ذا‪ ،‬إن ش َ‬
‫ئت تث بيت ‪ NumPy‬فيمكن ك تنفي ذ األم ر‬
‫‪.pip3 install numpy‬‬
‫أن بيئة البرمجة جاهزة‪:‬‬
‫هناك عدة حزم وأدوات تطوير أخرى يجب تثبيتها للتأكد من ّ‬
‫‪sudo apt install -y build-essential libssl-dev libffi-dev‬‬
‫‪python3-dev‬‬
‫بع د أن انتهين ا من ض بط ب ايثون وتث بيت ‪ ،pip‬يمكنن ا اآلن إنش اء «بيئ ة افتراض ية»‬
‫(‪ )virtual environment‬لمشاريعنا‪.‬‬
‫‪41‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫ج‪ .‬إعداد بيئة افتراضية‬
‫ُت ِّ‬
‫مك نك البيئات االفتراضية من إنشاء مساحة معزولة في خادمك مخصصة لمشاريع ب ايثون‪،‬‬
‫أن كل مش روع تعم ل علي ه س تكون ل ه اعتماديَّ ات ه (‪ )dependencies‬الخاص ة ب ه‪ ،‬وال تي‬
‫مما يعني َّ‬
‫ِّ‬
‫تؤثر على غيره من المشاريع‪.‬‬
‫لن‬
‫ي ِّ‬
‫دارات‬
‫ٍ‬
‫وفر لن ا ض بط بيئ ةٍ برمجي ةٍ تحكمً ا أك بر بمش اريع ب ايثون‪ ،‬وإمكاني ة التعام ل م ع إص‬
‫مختلفةٍ من حزم بايثون‪ .‬وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية‪.‬‬
‫أي ع ددٍ تش اء من البيئ ات االفتراض ية‪ ،‬وك ل بيئ ة س تكون ممثل ة بمجل د في‬
‫يمكن ك ض بط ُّ‬
‫خادمك يحتوي على عدد من السكربتات‪.‬‬
‫هناك عدة طرق إلعداد بيئة برمجية في بايثون‪ ،‬لكننا سنس تخدم وح دة (‪ )module‬برمجي ة‬
‫باس م ‪ ،venv‬وهي ج ٌ‬
‫زء من مكتب ة ب ايثون ‪ 3‬القياس ية‪ .‬س نثبِّت ‪ venv‬على نظامن ا بتنفي ذ‬
‫األمر التالي‪:‬‬
‫‪sudo apt-get install -y python3-venv‬‬
‫بعد إتمام التثبيت‪ ،‬فنحن جاهزون إلنشاء البيئ ات االفتراض ية‪ ،‬يمكنن ا اآلن إمَّ ا اختي ار مجل د‬
‫نضع فيه بيئات بايثون‪ ،‬أو إنشاء مجلد جديد باستخدام األمر ‪ mkdir‬كما يلي‪:‬‬
‫‪mkdir environments‬‬
‫‪cd environments‬‬
‫َ‬
‫انتقلت إلى المجلد الذي تريد احت واء البيئ ات في ه‪ ،‬تس تطيع اآلن إنش اء بيئ ة جدي دة‬
‫بعد أن‬
‫بتنفيذ األمر اآلتي‪:‬‬
‫‪python3.6 -m venv my_env‬‬
‫‪42‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫سي ِ‬
‫نش ئ األم ر ‪ pyvenv‬مجل ًدا جدي ًدا في ه بعض الملف ات ال تي يمكن عرض ها باس تخدام‬
‫ُ‬
‫األمر ‪:ls‬‬
‫‪ls my_env‬‬
‫ستظهر لك مخرجات شبيهة بالمخرجات التالية‪:‬‬
‫‪bin include lib lib64 pyvenv.cfg share‬‬
‫أن تك ون مش اريعك معزول ٌة عن س ياق اآلل ة المحلي ة‪،‬‬
‫تعم ل ه ذه الملف ات م ع بعض ها لض مان َ‬
‫أن‬
‫لكي ال تختلط ملفات النظ ام م ع ملف ات المش اريع‪ .‬وه ذا أم رٌ حس ٌن إلدارة اإلص دارات ولض مان َّ‬
‫ً‬
‫أيض ا ‪ ،Python Wheels‬وال تي هي‬
‫الحزم ال تي يحت اج إليه ا‪ .‬تت وافر‬
‫كل مشروع يملك وصواًل إلى‬
‫ٍ‬
‫زم مبني ة (‪ )built-package format‬لب ايثون‪ ،‬وال تي يمكن أن ُتس ِّرع من تط وير ال برامج‬
‫ص يغة ح ٍ‬
‫ٌ‬
‫ودة في‬
‫بتقلي ل ع دد الم رات ال تي تحت اج فيه ا إلى تص ريف (‪ )compile‬المش روع‪ ،‬وهي موج‬
‫المجلد ‪ share‬في توزيعة أوبنتو ‪.20.04‬‬
‫سي ِّ‬
‫نفذ سكربت التفعيل‪:‬‬
‫عليك تفعيل البيئة الستخدامها‪ ،‬وذلك بكتابة األمر التالي الذي ُ‬
‫‪source my_env/bin/activate‬‬
‫ٌ‬
‫ابقة (‪ )prefix‬في المِ حث (‪ )prompt‬وال تي هي اس م البيئ ة‬
‫يجب أن تظه ر اآلن س‬
‫ً‬
‫مختلف ا في توزيع ة‬
‫المستخدمة‪ ،‬وفي حالتنا هذه يكون اس مها ‪ ،my_env‬وق د يك ون مظه ر المِ َحث‬
‫دبي ان‪ ،‬وذل ك اعتم ا ًدا على اإلص دار المس تخدم؛ لكن يجب أن تش اهد اس م البيئ ة بين قوس ين في‬
‫بداية السطر‪:‬‬
‫‪(my_env) sammy@ubuntu:~/environments$‬‬
‫‪43‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫أن البيئ ة ‪ my_env‬مفعَّ ل ة حالي ا‪ ،‬وه ذا يع ني َّ‬
‫أنن ا سنس تخدم‬
‫ستس مح ل ك الس ابقة بمعرف ة َّ‬
‫إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة‪.‬‬
‫ً‬
‫جاهزة لالستخدام بعد اتباعك للخطوات السابقة‪.‬‬
‫يجب أن تكون بيئتك االفتراضية‬
‫مالحظة‪ :‬يمكنك داخل البيئة االفتراضية أن تستخدم األمر ‪ python‬بداًل من ‪ python3‬واألمر ‪ pip‬ب داًل من‬
‫‪pip3‬‬
‫َ‬
‫كنت تس تخدم ب ايثون‪ 3‬خ ارج البيئ ة االفتراض َّية‪ ،‬فيجب علي ك حينه ا اس تخدام‬
‫ئت أم ا إذا‬
‫إن ش َ‪.‬‬
‫‪ python3‬و ‪ pip3‬حصرًا‪.‬‬
‫د‪ .‬إنشاء برنامج بسيط‬
‫ِ‬
‫لننش ئ برنامج ا بس يطا يع رض العب ارة‬
‫بع د أن أكملن ا ض بط بيئتن ا االفتراض ية‪،‬‬
‫َّ‬
‫أن البيئ ة تعم ل بالش كل الص حيح‪ ،‬ولكي تتع وَّ د على إنش اء‬
‫«!‪ ،»Hello World‬وبهذا س ن‬
‫َتحقق من َّ‬
‫َ‬
‫كنت واف ًدا جدي ًدا على اللغة‪.‬‬
‫برامج بايثون إن‬
‫علينا أواًل تشغيل محرر ملفات نصية إلنشاء ملف جديد‪ ،‬وليكن المُ ِّ‬
‫حرر ‪ nano‬الذي يعمل من‬
‫سطر األوامر‪:‬‬
‫‪(my_env) sammy@ubuntu:~/environments$ nano hello.py‬‬
‫بعد فتح الملف في نافذة الطرفية‪ ،‬سنكتب البرنامج الخاص بنا‪:‬‬
‫)"!‪print("Hello World‬‬
‫أغلق محرر ‪ nano‬بالضغط على ‪ Ctrl+x‬ثم اضغط على ‪ y‬عندما يسألك عن حفظ المل ف‪ .‬بع د‬
‫أن يُ َ‬
‫غلق المحرر ‪ nano‬وتعود إلى سطر األوامر‪ ،‬حاول تنفيذ البرنامج‪:‬‬
‫‪(my_env) sammy@ubuntu:~/environments$ python hello.py‬‬
‫‪44‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫َ‬
‫أنشأته إلى طباعة الناتج اآلتي في الطرفية‪:‬‬
‫سيؤدي برنامج ‪ hello.py‬الذي‬
‫!‪Hello World‬‬
‫للخروج من البيئة‪ ،‬اكتب األمر ‪ deactivate‬وستعود إلى مجلدك األصلي‪.‬‬
‫َ‬
‫ضبطت اآلن بيئة تطوير للغة بايثون ‪ 3‬على خادم أوبنتو‪ ،‬وح ان ال وقت للتعم ق‬
‫تهانينا! لقد‬
‫بلغة بايثون وإنشاء برامج رائعة! انتقل إلى الفصل التالي‪ ،‬استخدام سطر أوامر بايثون التفاعلي‪.‬‬
‫‪45‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫‪ .3‬دبيان‬
‫رش ُدك ه ذا القس م خط ً‬
‫سي ِ‬
‫وة بخط وة إلى كيفي ة تث بيت ب ايثون ‪ 3‬على لينكس‪ ،‬وتث بيت بيئ ة‬
‫ُ‬
‫أن‬
‫ٌ‬
‫برمج ة ع بر س طر األوام ر‪ .‬ص‬
‫أن ه ذا القس م يش رح عملي ة التث بيت في دبي ان ‪ ،10‬إال َّ‬
‫حيح َّ‬
‫المفاهيم األساسية فيه تنطبق على جميع توزيعات دبيان لينكس (‪.)Debian Linux‬‬
‫ا‪ .‬المتطلبات المسبقة‬
‫يجب أن تمل ك ص الحيات مس تخدم غ ير ج ذري ( ‪ )non-root user‬م ع امتي ازات ‪ sudo‬على‬
‫توزيعة دبيان ‪ ،10‬أو توزيعة أخرى من دبيان لينكس (‪.)Debian Linux‬‬
‫إذا لم تكن ل ك خ برة في التعام ل م ع بيئ ة الناف ذة الطرفي ة‪ ،‬فيمكن ك مطالع ة المق ال‬
‫طرفية لينكس ‪.»Linux Terminal‬‬
‫«مدخل إلى‬
‫ّ‬
‫ب‪ .‬إعداد بايثون ‪3‬‬
‫س ُنثبِّ ت ونض بط ب ايثون ع بر س طر األوام ر‪ ،‬وال ذي ه و طريق ٌة غ يرُ رس وميةٍ للتعام ل م ع‬
‫ِّ‬
‫ظهر ل ك‬
‫الحاس وب‪ ،‬فب داًل من الض غط على األزرار‪ ،‬س تكتب ًّ‬
‫نص ا وتعطي ه للحاس وب لينفذه‪ ،‬وس ُي ِ‬
‫ً‬
‫ً‬
‫أيضا‪ .‬يمكن أن يساعدك سطر األوامر على تعديل أو أتمتة مختلف المهام التي تنجزه ا‬
‫نصيا‬
‫ناتجا‬
‫ً‬
‫أداة أساس ٌ‬
‫ٌ‬
‫ية لمط وري البرمجي ات‪ ،‬وهنال ك الكث ير من األوام ر ال تي‬
‫على الحاس وب يومي ا‪ ،‬وه و‬
‫علي ك تعلمه ا لكي تتمكن من االس تفادة من ه‪ .‬هنال ك مق االت في أكاديمي ة حس وب (مث ل مق ال‬
‫م دخل إلى طرفي ة لينكس ‪ )Linux Terminal‬س تعلمك أساس يات س طر األوام ر‪ ،‬وهنال ك كت اب‬
‫«سطر أوامر لينكس» الذي يُ ع ُّد مرجعً ا لطريقة التعامل مع سطر األوامر‪.‬‬
‫‪46‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫ستجد تط بيق ‪( Terminal‬البرن امج ال ذي تس تعمله للوص ول إلى س طر األوام ر) بفتح القائم ة‬
‫في الزاوية السفلى اليسرى من الشاشة ثم كتاب ة «‪ »terminal‬في ش ريط البحث‪ ،‬ثم الض غط على‬
‫أيقون ة التط بيق ال تي س تظهر بعدئ ذٍ‪ .‬أو يمكن ك أن تض غط على ‪ Ctrl+Alt+T‬في لوح ة المف اتيح‬
‫بنفس الوقت لتشغيل تطبيق ‪.Terminal‬‬
‫مثبت ة مس ً‬
‫بقا‪ .‬للتأك د من‬
‫في دبيان ‪ 10‬واإلصدارات األخرى من دبيان لينكس‪ ،‬ستجد ب ايثون َّ‬
‫أن إص‬
‫َّ‬
‫دارات ب‬
‫ايثون حديث‬
‫ة‪ ،‬س‬
‫ِّ‬
‫نحدث النظ‬
‫ِّ‬
‫ونرقي‬
‫ام‬
‫ه باس‬
‫تخدام‬
‫األمر ‪:apt‬‬
‫‪sudo apt update‬‬
‫‪sudo apt -y upgrade‬‬
‫‪47‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫الخي ار ‪ -y‬يع ني َّ‬
‫أنك تواف ق على تث بيت جمي ع الح زم القابل ة للتح ديث‪ ،‬لكن ق د تحت اج إلى‬
‫تأكيد ذلك عند تحديث النظام وذلك اعتما ًدا على الحزم التي ُ‬
‫ستح َّدث‪ ،‬ونسخة لينكس‪.‬‬
‫ثبت في النظام بكتابة‪:‬‬
‫بعد إكمال‬
‫العملية‪ ،‬يمكننا التحقق من إصدار بايثون ‪ 3‬المُ َّ‬
‫َّ‬
‫‪python3 -V‬‬
‫المثبت‪ .‬قد يختلف‬
‫ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون‬
‫َّ‬
‫ً‬
‫شبيها بما يلي‪:‬‬
‫المثبتة في توزيعتك‪ ،‬لكن يجب أن يكون‬
‫بناء على النسخة‬
‫ً‬
‫الرقم‬
‫َّ‬
‫‪Python 3.7.3‬‬
‫ٌ‬
‫أداة تعم ل م ع لغ ة ب ايثون ُت َثبِّت‬
‫إلدارة الحزم البرمجي ة الخاص ة بب ايثون‪ ،‬س نثبِّ ت ‪ ،pip‬وهي‬
‫وتدير الحزم البرمجية ال تي ق د نحت اج إلى اس تخدامها في تط وير مش اريعنا (س نتعلم المزي د عن‬
‫المخصص للوحدات)‪:‬‬
‫َّ‬
‫الوحدات والحزم التي يمكنك تثبيتها باألداة ‪ pip‬في الفصل‬
‫‪sudo apt install -y python3-pip‬‬
‫يمكن تثبيت حزم بايثون بكتابة ما يلي مع تبديل ‪ package_name‬باسم الحزمة‪:‬‬
‫‪pip3 install package_name‬‬
‫علي ك وض ع اس م الحزم ة أو المكتب ة التابع ة لب ايثون مك ان ‪ package_name‬مث ل ‪Django‬‬
‫َ‬
‫شئت تنزي ل ‪ NumPy‬فيمكن ك تنفي ذ‬
‫لتطوير الويب‪ ،‬أو ‪ NumPy‬إلجراء الحسابات العلمية؛ لذا‪ ،‬إن‬
‫األمر ‪.pip3 install numpy‬‬
‫أن بيئة البرمجة جاهزة‪:‬‬
‫هناك عدة حزم وأدوات تطوير أخرى يجب تثبيتها للتأكد من ّ‬
‫‪sudo apt install build-essential libssl-dev libffi-dev python3‬‬‫‪dev‬‬
‫‪48‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫بع د أن انتهين ا من ض بط ب ايثون وتث بيت ‪ ،pip‬يمكنن ا اآلن إنش اء «بيئ ة افتراض ية»‬
‫(‪ )virtual environment‬لمشاريعنا‪.‬‬
‫ج‪ .‬إعداد بيئة افتراضية‬
‫ُت ِّ‬
‫مكن ك البيئ ات االفتراض ية من إنش اء مس احة معزول ة في حاس وبك مخصص ة لمش اريع‬
‫أن كل مشروع تعمل عليه ستكون له اعتماديَّ ات ه (‪ )dependencies‬الخاص ة ب ه‪،‬‬
‫بايثون‪ ،‬مما يعني َّ‬
‫ِّ‬
‫تؤثر على غيره من المشاريع‪.‬‬
‫والتي لن‬
‫ي ِّ‬
‫دارات‬
‫ٍ‬
‫وإمكانية التعام ل م ع إص‬
‫وفر لن ا ض بط بيئ ةٍ برمجي ةٍ تحكم ا أك بر بمش اريع ب ايثون‪،‬‬
‫َّ‬
‫مختلفةٍ من حزم بايثون‪ .‬وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية‪.‬‬
‫أي ع ددٍ تش اء من البيئ ات االفتراض ية‪ ،‬وك ل بيئ ة س تكون ممثل ة بمجل د في‬
‫يمكن ك ض بط ُّ‬
‫حاسوبك يحتوي على عدد من السكربتات‪.‬‬
‫هناك عدة طرق إلعداد بيئة برمجية في بايثون‪ ،‬لكننا سنس تخدم وح دة (‪ )module‬برمجي ة‬
‫ٌ‬
‫جزء من مكتبة بايثون ‪ 3‬القياسية‪ .‬سنثبِّ ت ‪ venv‬على نظامنا بكتابة‪:‬‬
‫باسم ‪ ،venv‬وهي‬
‫‪sudo apt install -y python3-venv‬‬
‫بعد إتمام التثبيت‪ ،‬فنحن جاهزون إلنشاء البيئ ات االفتراض ية‪ ،‬يمكنن ا اآلن إمَّ ا اختي ار مجل د‬
‫نضع فيه بيئات بايثون‪ ،‬أو إنشاء مجلد جديد باستخدام األمر ‪ mkdir‬كما يلي‪:‬‬
‫‪mkdir environments‬‬
‫‪cd environments‬‬
‫َ‬
‫انتقلت إلى المجلد الذي تريد احت واء البيئ ات في ه‪ ،‬تس تطيع اآلن إنش اء بيئ ة جدي دة‬
‫بعد أن‬
‫بتنفيذ األمر اآلتي‪:‬‬
‫‪49‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪python3.7 -m venv my_env‬‬
‫سي ِ‬
‫نش ئ األم ر ‪ pyvenv‬مجل ًدا جدي ًدا في ه بعض الملف ات ال تي يمكن عرض ها باس تخدام‬
‫ُ‬
‫األمر ‪:ls‬‬
‫‪ls my_env‬‬
‫ستظهر لك مخرجات شبيهة بالمخرجات التالية‪:‬‬
‫‪bin include lib lib64 pyvenv.cfg share‬‬
‫أن تك ون مش اريعك معزول ٌة عن س ياق اآلل ة المحلي ة‪،‬‬
‫تعم ل ه ذه الملف ات م ع بعض ها لض مان َ‬
‫أن‬
‫لكي ال تختلط ملفات النظ ام م ع ملف ات المش اريع‪ .‬وه ذا أم رٌ حس ٌن إلدارة اإلص دارات ولض مان َّ‬
‫ً‬
‫أيض ا ‪ ،Python Wheels‬وال تي هي‬
‫الحزم ال تي يحت اج إليه ا‪ .‬تت وافر‬
‫كل مشروع يملك وصواًل إلى‬
‫ٍ‬
‫زم (مث ل ‪ )built-package format‬لب ايثون‪ ،‬وال تي يمكن أن ُتس ِّرع من تط وير‬
‫ص يغة بن اء ح ٍ‬
‫ٌ‬
‫ودة‬
‫ال برامج بتقلي ل ع دد الم رات ال تي تحت اج فيه ا إلى تص ريف (‪ )compile‬المش روع‪ ،‬وهي موج‬
‫في كل المجلدات المُ سمّ اة ‪.lib‬‬
‫سي ِّ‬
‫نفذ سكربت التفعيل‪:‬‬
‫عليك تفعيل البيئة الستخدامها‪ ،‬وذلك بكتابة األمر التالي الذي ُ‬
‫‪source my_env/bin/activate‬‬
‫ٌ‬
‫ابقة (‪ )prefix‬في المِ حث (‪ )prompt‬وال تي هي اس م البيئ ة‬
‫يجب أن تظه ر اآلن س‬
‫ً‬
‫مختلف ا في توزيع ة‬
‫المستخدمة‪ ،‬وفي حالتنا هذه يكون اس مها ‪ ،my_env‬وق د يك ون مظه ر المِ َحث‬
‫دبي ان‪ ،‬وذل ك اعتم ا ًدا على اإلص دار المس تخدم؛ لكن يجب أن تش اهد اس م البيئ ة بين قوس ين في‬
‫بداية السطر‪:‬‬
‫‪(my_env) sammy@sammy:~/environments$‬‬
‫‪50‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫أن البيئ ة ‪ my_env‬مفعل ة حالي ا‪ ،‬وه ذا يع ني أنن ا سنس تخدم‬
‫ستس مح ل ك الس ابقة بمعرف ة َّ‬
‫إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة‪.‬‬
‫ً‬
‫جاهزة لالستخدام بعد اتباعك للخطوات السابقة‪.‬‬
‫يجب أن تكون بيئتك االفتراضية‬
‫مالحظة‪ :‬يمكنك داخل البيئة االفتراضية أن تستخدم األمر ‪ python‬بداًل من ‪ python3‬واألمر ‪ pip‬ب داًل من‬
‫‪pip3‬‬
‫َ‬
‫كنت تس تخدم ب ايثون‪ 3‬خ ارج البيئ ة االفتراض ية‪ ،‬فيجب علي ك حينه ا اس تخدام‬
‫ئت أم ا إذا‬
‫إن ش َ‪.‬‬
‫‪ python3‬و ‪ pip3‬حصرًا‪.‬‬
‫د‪ .‬إنشاء برنامج بسيط‬
‫برنامجا بس ً‬
‫ً‬
‫ِ‬
‫يطا يع رض العب ارة «مرحب ا بالع الم!»‪،‬‬
‫لننشئ‬
‫االفتراضية‪،‬‬
‫بعد إكمال ضبط بيئتنا‬
‫َّ‬
‫أن البيئ ة تعم ل بالش كل الص حيح‪ ،‬ولكي تتع وّ د على إنش اء ب رامج ب ايثون إن‬
‫وبه ذا س نتحقق من َّ‬
‫َ‬
‫كنت واف ًدا جدي ًدا على اللغة‪.‬‬
‫علينا أواًل تشغيل محرر ملفات نصية إلنشاء ملف جديد‪ ،‬وليكن المحرر ‪ nano‬الذي يعمل من‬
‫سطر األوامر‪:‬‬
‫‪(my_env) sammy@sammy:~/environments$ nano hello.py‬‬
‫بعد فتح الملف في نافذة الطرفية‪ ،‬سنكتب البرنامج الخاص بنا‪:‬‬
‫)"!‪print("Hello, World‬‬
‫أغلق محرر ‪ nano‬بالضغط على ‪ Ctrl+x‬ثم اضغط على ‪ y‬عندما يسألك عن حفظ الملف‪.‬‬
‫بعد أن يُ َ‬
‫غلق المحرر ‪ nano‬وتعود إلى سطر األوامر‪ ،‬حاول تنفيذ البرنامج‪:‬‬
‫‪(my_env) sammy@sammy:~/environments$ python hello.py‬‬
‫‪51‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫َ‬
‫أنشأته إلى طباعة الناتج التالي في الطرفية‪:‬‬
‫سيؤدي برنامج ‪ hello.py‬الذي‬
‫!‪Hello, World‬‬
‫للخروج من البيئة‪ ،‬اكتب األمر ‪ deactivate‬وستعود إلى مجلدك األصلي‪.‬‬
‫َ‬
‫تطوير للغة بايثون ‪ 3‬في نظام لينكس دبيان‪ ،‬ح ان اآلن ال وقت‬
‫ضبطت اآلن بيئة‬
‫تهانينا! لقد‬
‫ٍ‬
‫للتعم ق بلغ ة ب ايثون وإنش اء ب رامج رائع ة! انتق ل إلى الفص ل الت الي‪ ،‬اس تخدام س طر أوام ر‬
‫بايثون التفاعلي‪.‬‬
‫‪52‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪CentOS .4‬‬
‫رش ُدك ه ذا القس م خط ً‬
‫سي ِ‬
‫وة بخط وة إلى كيفي ة تث بيت ب ايثون ‪ 3‬على ‪ ،CentOS 8‬وتث بيت‬
‫ُ‬
‫بيئة برمجة عبر سطر األوامر‪.‬‬
‫ا‪ .‬المتطلبات المسبقة‬
‫يجب أن تملك صالحيات مس تخدم أساس ي غ ير ج ذري (‪ )non-root superuser‬على نظ ام‬
‫‪ CentOS 8‬متصل بالشبكة‪.‬‬
‫إذا لم تكن ل ك خ برة في التعام ل م ع بيئ ة الناف ذة الطرفي ة‪ ،‬فيمكن ك مطالع ة المق ال‬
‫طرفية لينكس ‪.»Linux Terminal‬‬
‫«مدخل إلى‬
‫ّ‬
‫ب‪ .‬تحضير النظام‬
‫س ُنثبِّ ت ونض بط ب ايثون ع بر س طر األوام ر‪ ،‬إن ك ان نظ ام ‪ CentOS 8‬يب دأ بس طح مكتب ذي‬
‫واجهة مس تخدم رس ومية (‪ ،)GUI‬فيمكن ك ال دخول إلى س طر األوام ر بفتح القائم ة‪ ،‬وال دخول إلى‬
‫‪ Applications‬ثم ‪ Utilities‬ثم النق ر على ‪ .Terminal‬هنال ك مق االت في أكاديمي ة حس وب‬
‫طرفية لينكس ‪ )Linux Terminal‬ستعلمك أساسيات سطر األوامر‪ ،‬وهنالك‬
‫(مثل مقال مدخل إلى‬
‫ّ‬
‫كتاب «سطر أوامر لينكس» الذي يُ ع ُّد مرجعً ا لطريقة التعامل مع سطر األوامر‪.‬‬
‫سنس‬
‫تخدم أداة إدارة الح‬
‫زم مفتوح‬
‫ة المص‬
‫در ‪( DNF‬اختص‬
‫ار للعب‬
‫ارة‬
‫‪ Dandified YUM‬وه و الجي ل الث اني من م دير الح زم ‪ Yellowdog Updater, Modified‬المع روف‬
‫باالختصار ‪ .)YUM‬هذه أداة شائعة االستخدام إلدارة الحزم على أنظمة لينكس المس تندة إلى ‪Red‬‬
‫‪ ،Hat‬مثل ‪ ،CentOS‬إذ تتيح لك تثبيت الحزم وتحديثها بسهولة‪ ،‬وكذلك إزالة الحزم من الجهاز‪.‬‬
‫‪53‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫أن لدينا أحدث إصدار من ‪ yum‬عبر تنفيذ األمر التالي‪:‬‬
‫قبل أن نبدأ التثبيت‪ ،‬دعنا نتأكد من َّ‬
‫‪sudo dnf update -y‬‬
‫أنك ت درك َّ‬
‫الخي ار ‪ -y‬يع ني َّ‬
‫الطرفية من طلب تأكي د قب ل‬
‫أنك تح دث تغي يرات‪ ،‬وذل ك لمن ع‬
‫َّ‬
‫تنفيذ األمر‪.‬‬
‫بمجرَّ د تثبيت وتحديث كل شيء‪ ،‬فنحن جاهزون لتثبيت بايثون ‪.3‬‬
‫ج‪ .‬تثبيت وإعداد بايثون ‪3‬‬
‫نظ ام ‪ CentOS‬مش تق من ‪( RHEL‬اختص ار للجمل ة ‪ ، )Red Hat Enterprise Linux‬وال ذي‬
‫يرك ز على الثب ات واالس تقرار‪ .‬أي لن تج د في ه ذا النظ ام إال اإلص دارات المس تقرة والمُ خت برة من‬
‫التطبيقات والحزم القابلة للتنزيل‪ ،‬لذلك وباستعمال مدير حزم ‪CentOS‬‬
‫ستجد أحدث إص دار من‬
‫بايثون دومً ا‪:‬‬
‫‪sudo dnf install python3 -y‬‬
‫بعد إكمال العملية‪ ،‬يمكننا التحقق من نجاح عملية التثبيت بطلب إصدار بايثون بكتابة‪:‬‬
‫‪python3 -V‬‬
‫المثبت‪ .‬قد يختلف‬
‫ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون‬
‫َّ‬
‫ً‬
‫شبيها بما يلي‪:‬‬
‫بناء على النسخة المثبتة في توزيعتك‪ ،‬لكن يجب أن يكون‬
‫ً‬
‫الرقم‬
‫‪Python 3.6.8‬‬
‫ً‬
‫انطالق ا من‬
‫تاليا أدوات تطوير ‪ CentOS‬ال تي تس مح ل ك ببن اء التطبيق ات وتص ريفها‬
‫سنثبِّ ت ً‬
‫شيفرتها المصدرية‪:‬‬
‫‪54‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪sudo dnf -y groupinstall development‬‬
‫ننتق ل بع د اكتم ال التث بيت للخط وة التالي ة وهي ض بط وإع داد بيئ ة تطويري ة لكتاب ة ب رامج‬
‫بايثون وتنفيذها‪.‬‬
‫د‪ .‬إعداد بيئة افتراضية‬
‫ثبتن ا ب ايثون وأع ددنا النظ ام‪ ،‬يمكنن ا المض ي ق دمً ا إلنش اء بيئ ة البرمج ة ال تي‬
‫اآلن بع د أن َّ‬
‫سنعمل فيها باستخدام ‪.venv‬‬
‫ُت ِّ‬
‫مخصص ة لمش اريع‬
‫َّ‬
‫مكن ك البيئ ات االفتراض ية من إنش اء مس احة معزول ة في حاس وبك‬
‫أن كل مشروع تعمل عليه ستكون له اعتماديَّ ات ه (‪ )dependencies‬الخاص ة ب ه‪،‬‬
‫بايثون‪ ،‬مما يعني َّ‬
‫ِّ‬
‫تؤثر على غيره من المشاريع‪.‬‬
‫والتي لن‬
‫ي ِّ‬
‫دارات‬
‫ٍ‬
‫وإمكانية التعام ل م ع إص‬
‫وفر لن ا ض بط بيئ ةٍ برمجي ةٍ تحكمً ا أك بر بمش اريع ب ايثون‪،‬‬
‫َّ‬
‫مختلفةٍ من حزم بايثون‪ .‬وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية‪.‬‬
‫أي ع ددٍ تش اء من البيئ ات االفتراض َّية‪ ،‬وك ل بيئ ة س تكون ممثل ة بمجل د في‬
‫يمكن ك ض بط ِّ‬
‫حاسوبك يحتوي على عدد من السكربتات‪.‬‬
‫بعد إتمام التثبيت‪ ،‬فنحن جاهزون إلنشاء البيئات االفتراض ية‪ ،‬يمكنن ا اآلن إم ا اختي ار مجل د‬
‫نضع فيه بيئات بايثون‪ ،‬أو إنشاء مجلد جديد باستخدام األمر ‪ mkdir‬كما يلي‪:‬‬
‫‪mkdir environments‬‬
‫‪cd environments‬‬
‫َ‬
‫انتقلت إلى المجلد الذي تريد احت واء البيئ ات في ه‪ ،‬تس تطيع اآلن إنش اء بيئ ة جدي دة‬
‫بعد أن‬
‫بتنفيذ األمر اآلتي‪:‬‬
‫‪55‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫‪python3 -m venv my_env‬‬
‫سنس‬
‫تعمل االس‬
‫م ‪ my_env‬مج‬
‫ً‬
‫ازا للبيئ‬
‫ة ولكن يجب أن تخت‬
‫ار اس‬
‫مً ا ذا معنًى‬
‫يناسب المشروع‪.‬‬
‫سي ِ‬
‫نش ئ األم ر ‪ pyvenv‬مجل ًدا جدي ًدا في ه بعض الملف ات ال تي يمكن عرض ها باس تخدام‬
‫ُ‬
‫األمر ‪:ls‬‬
‫‪ls my_env‬‬
‫ستظهر لك مخرجات شبيهة بالمخرجات التالية‪:‬‬
‫‪bin include lib lib64 pyvenv.cfg‬‬
‫أن تك ون مش اريعك معزول ٌة عن س ياق اآلل ة المحلي ة‪،‬‬
‫تعم ل ه ذه الملف ات م ع بعض ها لض مان َ‬
‫أن‬
‫لكي ال تختلط ملفات النظ ام م ع ملف ات المش اريع‪ .‬وه ذا أم رٌ حس ٌن إلدارة اإلص دارات ولض مان َّ‬
‫الحزم التي يحتاج إليها‪.‬‬
‫كل مشروع يملك وصواًل إلى‬
‫ٍ‬
‫سي ِّ‬
‫نفذ سكربت التفعيل‪:‬‬
‫عليك تفعيل البيئة الستخدامها‪ ،‬وذلك بكتابة األمر التالي الذي ُ‬
‫‪source my_env/bin/activate‬‬
‫ٌ‬
‫ابقة (‪ )prefix‬في المِ حث (‪ )prompt‬وال تي هي اس م البيئ ة‬
‫يجب أن تظه ر اآلن س‬
‫المستخدمة‪ ،‬وفي حالتنا هذه يكون اسمها ‪:my_env‬‬
‫‪(my_env) [sammy@centosserver environments]$‬‬
‫حالي ا‪ ،‬وه ذا يع ني َّ‬
‫أنن ا سنس تخدم‬
‫أن البيئ ة ‪ my_env‬مفعل ة‬
‫ستس مح ل ك الس ابقة بمعرف ة َّ‬
‫ً‬
‫إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة‪.‬‬
‫الح ظ أن م دير ح زم ب ايثون ‪ pip‬ق د ُثبِّت مس ً‬
‫بقا وال ذي سنس تعمله لتث بيت الح زم البرمجي ة‬
‫‪56‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫وإدارتها في بيئتنا البرمجية السابقة‪ ،‬فيمكننا تثبيت أي حزمة بتنفيذ األمر التالي‪:‬‬
‫‪(my_env) [sammy@centosserver environments]$ sudo pip install‬‬
‫‪package_name‬‬
‫يش ير ‪ package_name‬هن ا إلى أي حزم ة أو مكتب ة من ب ايثون مث ل ‪ Django‬الحزم ة‬
‫المخصص ة لتط وير ال ويب أو ‪ NumPy‬الحزم ة المخصص ة إلج راء الحس ابات الرياض ية المتقدم ة‪،‬‬
‫فإذا أردت تثبيت الحزمة األخيرة‪ ،‬يمكنك ببساطة تنفيذ األمر ‪.pip install numpy‬‬
‫ً‬
‫جاهزة لالستخدام بعد اتباعك للخطوات السابقة‪.‬‬
‫يجب أن تكون بيئتك االفتراضية‬
‫مالحظة‪ :‬يمكنك داخل البيئة االفتراضية أن تستخدم األمر ‪ python‬ب داًل من ‪ python3.6‬واألم ر ‪ pip‬ب داًل‬
‫من ‪pip3.6‬‬
‫َ‬
‫كنت تس تخدم ب ايثون‪ 3‬خ ارج البيئ ة االفتراض ية‪ ،‬فيجب علي ك حينه ا اس تخدام‬
‫ئت أم ا إذا‬
‫إن ش َ‪.‬‬
‫‪ python3.6‬و ‪ pip3.6‬حصرًا‪.‬‬
‫ه‪ .‬إنشاء برنامج بسيط‬
‫ً‬
‫ً‬
‫ِ‬
‫يطا يع رض العب ارة‬
‫برنامج ا بس‬
‫لننش ئ‬
‫بع د أن أكملن ا ض بط بيئتن ا االفتراض ية‪،‬‬
‫َّ‬
‫أن البيئ ة تعم ل بالش كل الص حيح‪ ،‬ولكي تتع وَّ د على إنش اء‬
‫«مرحبا بالع الم!»‪ ،‬وبه ذا س‬
‫نتحقق من َّ‬
‫َ‬
‫كنت واف ًدا جدي ًدا على اللغة‪.‬‬
‫برامج بايثون إن‬
‫علينا أواًل تشغيل محرر ملفات نصية إلنشاء ملف جديد‪ ،‬وليكن المحرر ‪:vi‬‬
‫‪(my_env) [sammy@centosserver environments]$ vi hello.py‬‬
‫بع د فتح المل ف في ناف ذة الطرفي ة‪ ،‬اكتب الح رف ‪ i‬لل دخول إلى وض ع اإلدراج‬
‫(‪ ،)insert mode‬بعدها يمكننا كتابة البرنامج‪:‬‬
‫‪57‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫)"!‪print("Hello, World‬‬
‫اآلن اض غط على ال زر ‪ ESC‬للخ روج من وض ع اإلدراج‪ .‬بع د ذل ك ‪ ،‬اكتب ‪ :x‬ثم ‪ ENTER‬لحف ظ‬
‫الملف وإغالقه‪.‬‬
‫نحن جاهزون اآلن لتنفيذ البرنامج‪:‬‬
‫‪(my_env) [sammy@centosserver environments]$ python hello.py‬‬
‫َ‬
‫أنشأته إلى طباعة الناتج التالي في الطرفية‪:‬‬
‫سيؤدي برنامج ‪ hello.py‬الذي‬
‫!‪Hello, World‬‬
‫للخروج من البيئة‪ ،‬اكتب األمر ‪ deactivate‬وستعود إلى مجلدك األصلي‪.‬‬
‫َ‬
‫تطوير للغة بايثون ‪ 3‬في ‪ ،CentOS 8‬ح ان اآلن ال وقت للتعم ق‬
‫ضبطت اآلن بيئة‬
‫تهانينا! لقد‬
‫ٍ‬
‫بلغة بايثون وإنشاء برامج رائعة! انتقل إلى الفصل التالي‪ ،‬استخدام سطر أوامر بايثون التفاعلي‪.‬‬
‫‪58‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫‪macOS .5‬‬
‫رش ُدك ه ذا القس م خط ً‬
‫سي ِ‬
‫وة بخط وة إلى كيفي ة تث بيت ب ايثون ‪ 3‬في ‪ ،macOS‬وتث بيت بيئ ة‬
‫ُ‬
‫برمجة عبر سطر األوامر‪.‬‬
‫ا‪ .‬المتطلبات المسبقة‬
‫يجب أن تمل ك جه ً‬
‫ازا علي ه نظ ام ‪ macOS‬متص ل بالش بكة م ع ص الحيات م دير‬
‫(‪.)administrative access‬‬
‫إذا لم تكن ل ك خ برة في التعام ل م ع بيئ ة الناف ذة الطرفي ة‪ ،‬فيمكن ك مطالع ة المق ال‬
‫طرفية لينكس ‪.»Linux Terminal‬‬
‫«مدخل إلى‬
‫ّ‬
‫ب‪ .‬فتح نافذة الطرفية‬
‫سنجري معظم أطوار التثبيت واإلعدادات عبر سطر األوامر‪ ،‬والذي ه و طريق ٌة غ يرُ رس وميةٍ‬
‫نص ا وتعطي ه للحاس وب لينف ذه‪،‬‬
‫للتعام ل م ع الحاس وب‪ ،‬فب داًل من الض غط على األزرار‪ ،‬س تكتب ًّ‬
‫ً‬
‫ً‬
‫أيضا‪ .‬يمكن أن يساعدك سطر األوامر على تعديل أو أتمتة مختلف المه ام‬
‫نصيا‬
‫ناتجا‬
‫ظهر لك‬
‫ُ‬
‫ً‬
‫وسي ِ‬
‫ٌ‬
‫ٌ‬
‫أساسية لمطوري البرمجيات‪.‬‬
‫أداة‬
‫يوميا‪ ،‬وهو‬
‫التي تنجزها على الحاسوب‬
‫ً‬
‫طرفي ة م اك ( ‪ )macOS Terminal‬هي تط بيق يمكن ك اس تخدامه لل دخول إلى واجه ة س طر‬
‫األوام ر‪ .‬مث ل التطبيق ات األخ رى‪ ،‬س تجد تط بيق الطرفي ة بال ذهاب إلى ‪ ،Finder‬وفتح المجل د‬
‫‪ ،Applications‬ثم ال ذهاب إلى المجل د ‪ ،Utilities‬ثم النق ر الم زدوج على ‪ Terminal‬لفتح ه‪ .‬أو‬
‫يمكن ك اس تخدام ‪ Spotlight‬ع بر الض غط على ال زرّ ين ‪ command‬و ‪ spacebar‬للعث ور على‬
‫‪ Terminal‬بكتابته في المربع الذي سيظهر‪.‬‬
‫‪59‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫هنالك الكثير من األوامر التي عليك تعلمها لكي تتمكن من االستفادة منه‪ .‬هنال ك مق االت في‬
‫طرفي ة لينكس ‪ )Linux Terminal‬س تعلمك أساس يات‬
‫أكاديمي ة حس وب (مث ل مق ال م دخل إلى‬
‫ّ‬
‫س طر األوام ر‪ ،‬وهنال ك كت اب «س طر أوام ر لينكس» ال ذي يُ ع َت بر مرجع ا لطريق ة التعام ل م ع س طر‬
‫األوامر في لينكس‪ ،‬والذي يشبه نظيره في ماك‪.‬‬
‫ج‪ .‬تثبيت ‪Xcode‬‬
‫‪ Xcode‬هي بيئ ة تط وير متكامل ة (‪ )IDE‬تت ألف من أدوات تط وير ال برامج لنظ ام التش غيل‬
‫ً‬
‫سلفا‪ .‬للتحقق من ذلك‪ ،‬اكتب في نافذة الطرفية ما يلي‪:‬‬
‫‪ .MacOS‬قد يكون ‪ Xcode‬مثب ًتا عندك‬
‫‪xcode-select -p‬‬
‫‪60‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫أن مثبت ‪:Xcode‬‬
‫إن حصلت على المخرجات التالية‪ ،‬فهذا يعني ّ‬
‫‪/Library/Developer/CommandLineTools‬‬
‫االفتراضية‪.‬‬
‫إن تلقيت خطأ‪ ،‬فثبِّ ت ‪ Xcode‬من المتجر ‪ App Store‬واعتمد الخيارات‬
‫َّ‬
‫الطرفية‪ .‬ثم ثبِّ ت التطبيق ‪ Command Line Tools‬عن‬
‫بعد تثبيت ‪ ،Xcode‬ارجع إلى النافذة‬
‫َّ‬
‫طريق كتابة‪:‬‬
‫‪xcode-select --install‬‬
‫عن د ه ذه المرحل ة‪ ،‬يك ون ق د ثبِّ ت ‪ ،Xcode‬والتط بيق ‪ Command Line Tools‬الخ اص ب ه‪،‬‬
‫ونحن اآلن مستعدون لتثبيت مدير الحزم ‪.Homebrew‬‬
‫د‪ .‬تثبيت وإعداد ‪Homebrew‬‬
‫أن طرفي ة ‪ macOS‬تتمت ع ب الكثير من وظ ائف طرفي ة لينكس وأنظم ة ي ونكس‬
‫في حين َّ‬
‫األخ رى‪ ،‬إال أنه ا ال ت أتي بم دير ح زم جي د‪ .‬م دير الح زم (‪ )package manager‬ه و مجموع ة من‬
‫أدوات البرمجي ات ال تي تعم ل على أتمت ة عملي ات التث بيت‪ ،‬بم ا في ذل ك التث بيت األولي لل برامج‪،‬‬
‫وترقيته ا‪ ،‬وإع دادها‪ ،‬وإزالته ا عن د الحاج ة‪ .‬تحف ظ ه ذه األدوات التثبيت ات في موق ع مرك زي‪،‬‬
‫ويمكنه ا ص يانة جمي ع ح زم ال برامج على النظ ام وف ق تنس يقات (‪ )formats‬معروف ة‪ .‬ت وفر‬
‫‪ Homebrew‬لنظ ام التش غيل ‪ macOS‬نظ ام إدارة ح زم مج اني ومفت وح المص در يبس ط عملي ة‬
‫تثبيت البرنامج‪ .‬لتثبيت ‪ِّ ،Homebrew‬‬
‫نفذ في الطرفية األمر التالي‪:‬‬
‫‪/usr/bin/ruby -e "$(curl -fsSL‬‬
‫‪https://raw.githubusercontent.com/Homebrew/install/master/insta‬‬
‫")‪ll‬‬
‫‪61‬‬
‫|‬
‫▲‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫البرمجة بلغة بايثون‬
‫ِّ‬
‫يعدل مس ار روبي على جه ازك‪ .‬يس حب األم ر ‪curl‬‬
‫ط ِّور ‪ Homebrew‬ع بر روبي‪ ،‬ل ذلك س‬
‫ُ‬
‫الس كربت من عن وان ‪ URL‬المح دد‪ .‬سيوض ح ذل ك الس كربت م ا س يفعله‪ ،‬ثم يوق ف العملي ة ليطلب‬
‫منك التأكيد‪ .‬يوفر لك هذا الكثير من المالحظات حول ما سيفعله الس كربت في نظام ك‪ ،‬ويمنح ك‬
‫الفرصة للتحقق من العملية‪.‬‬
‫الح ظ َّ‬
‫أنك عن د إدخ ال كلم ة الم رور‪ ،‬فلن تع رض الطرفي ة المح ارف ال تي تكتبه ا‪ ،‬ولكنَّه ا‬
‫ست ِّ‬
‫ُ‬
‫سجل‪ ،‬بعد إدخال كلمة المرور اضغط على الزر ‪ .return‬واض غط على الح رف ‪ y‬إن ُطلِب من ك‬
‫تأكيد التثبيت‪.‬‬
‫لنلق نظرة على الرايات (‪ )flags‬المرتبطة باألمر ‪:curl‬‬
‫•‬
‫تخ بر الرايت ان ‪ -f‬أو ‪ --fail‬الطرفي ة بع دم إعط اء مخرج ات على هيئ ة مس تند ‪HTML‬‬
‫عند حدوث أخطاء في الخادم‪.‬‬
‫•‬
‫ُتص مِ ت الرايت ان ‪ -s‬أو ‪ --silent‬األم ر ‪ ،curl‬بمع نى أن ه لن يع رض معلوم ات التق دم‪،‬‬
‫وعن د جمعه ا م ع الراي تين ‪ -S‬أو ‪ ،--show-error‬س تجعل ‪ُ curl‬تظه ر رس الة خط أ في‬
‫حال الفشل‪.‬‬
‫•‬
‫تطلب الرايتان ‪ -L‬أو ‪ --location‬من ‪ curl‬إع ادة الطلبي ة (‪ )request‬إلى مك ان جدي د‬
‫بأن الصفحة المطلوبة قد ُنقِ لت إلى موقع أخر‪.‬‬
‫إذا أبلغ الخادم َّ‬
‫بمج رد اكتم ال عملي ة التث بيت‪ ،‬سنض ع مجل د ‪ Homebrew‬في أعلى متغ ير البيئ ة ‪.PATH‬‬
‫سيض من ذل ك أن يتم اس تدعاء عملي ات تث بيت ‪ Homebrew‬ع بر األدوات ال تي ق د يختاره ا نظ ام‬
‫تلقائي ا‪ ،‬والتي قد تتعارض مع بيئة التطوير التي تنشئها‪.‬‬
‫التشغيل ‪Mac OS X‬‬
‫ً‬
‫‪62‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫يجب علي ك إنش اء أو فتح المل ف ‪ ~/.bash_profile‬باس تخدام مح رر نص وص س طر‬
‫األوامر ‪ nano‬باستخدام األمر ‪:nano‬‬
‫‪nano ~/.bash_profile‬‬
‫بعد فتح الملف في نافذة الطرفية‪ ،‬اكتب ما يلي‪:‬‬
‫‪export PATH=/usr/local/bin:$PATH‬‬
‫لحف ظ التغي يرات‪ ،‬اض غط على المفت اح ‪ control‬والح رف ‪ o‬ب التزامن‪ ،‬وعن د مطالبت ك‬
‫بالتأكي د‪ ،‬اض غط على المفت اح ‪ .return‬يمكن ك اآلن الخ روج من ‪ nano‬عن طري ق الض غط على‬
‫المفتاح ‪ control‬والحرف ‪ x‬بالتزامن‪.‬‬
‫لتفعيل هذه التغييرات‪ ،‬اكتب في نافذة الطرفية‪:‬‬
‫‪source ~/.bash_profile‬‬
‫أن‬
‫ستص ير اآلن التغي يرات ال تي أجريته ا على متغ ير البيئ ة ‪ PATH‬فعال ة‪ .‬يمكنن ا التحق ق من َّ‬
‫‪ Homebrew‬قد ُثبِّ ت بنجاح عن طريق كتابة‪:‬‬
‫‪brew doctor‬‬
‫إذا لم تكن هناك حاجة إلى أي تحديثات في هذا الوقت‪ ،‬فستطبع الطرفية ما يلي‪:‬‬
‫‪Your system is ready to brew.‬‬
‫خالف ذلك‪ ،‬قد تحصل على تنبيه يدعوك إلى تنفيذ أمر آخ ر مث ل ‪ brew update‬للتأك د من‬
‫أن ‪ Homebrew‬مح َّدث‪ .‬بمجرد أن تصبح ‪ Homebrew‬جاهزة‪ ،‬يمكنك تثبيت بايثون ‪.3‬‬
‫َّ‬
‫‪63‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫ه‪ .‬تثبيت بايثون ‪3‬‬
‫يمكن ك اس تخدام ‪ Homebrew‬للبحث عن ال برامج ال تي يمكن ك تثبيته ا ع بر‬
‫األم ر ‪ ،brew search‬ويمكن ك الحص ول على قائم ة الح زم والوح دات ذات العالق ة بب ايثون فق ط‬
‫عبر تنفيذ األمر التالي‪:‬‬
‫‪brew search python‬‬
‫نافذة الطرفية ستخرج قائمة من الحزم والوحدات التي يمكنك تثبيتها على النحو التالي‪:‬‬
‫‪python3‬‬
‫‪micropython‬‬
‫‪app-engine-python‬‬
‫‪wxpython‬‬
‫‪python‬‬
‫‪boost-python‬‬
‫‪zpython‬‬
‫‪python-markdown‬‬
‫‪gst-python‬‬
‫‪homebrew/versions/gst-‬‬
‫‪homebrew/apache/mod_python‬‬
‫‪python010‬‬
‫‪Caskroom/cask/kk7ds-‬‬
‫‪homebrew/python/python-dbus‬‬
‫‪python-runtime‬‬
‫‪Caskroom/cask/mysql-‬‬
‫‪homebrew/python/vpython‬‬
‫‪connector-python‬‬
‫سيكون بايثون ‪ 3‬من بين العناصر المدرجة في القائمة‪ .‬لذلك دعنا نثبِّتها‪:‬‬
‫‪brew install python3‬‬
‫الطرفية مالحظات بشأن عملية تثبيت بايثون ‪ ،3‬وقد يستغرق األمر بضع‬
‫ستعرض لك نافذة‬
‫َّ‬
‫دقائق قبل اكتمال التثبيت‪.‬‬
‫إلى ج انب ب ايثون ‪ ،3‬س تثبِّ ت ‪ Homebrew‬و ‪ pip‬و ‪ setuptools‬و ‪ .wheel‬سنس تخدم ‪،pip‬‬
‫ٌ‬
‫أداة تعم ل م ع ب ايثون ُت َثبِّ ت وت دير الح زم البرمجي ة ال تي ق د نحت اج إلى اس تخدامها في‬
‫وهي‬
‫المخصص للوحدات)‪.‬‬
‫َّ‬
‫تطوير مشاريعنا (سنتعلم المزيد عن الوحدات والحزم في الفصل الالحق‬
‫‪64‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫يمكن تثبيت حزم بايثون بكتابة ما يلي مع تبديل ‪ package_name‬باسم الوحدة‪:‬‬
‫‪pip3 install package_name‬‬
‫علي ك وض ع اس م الحزم ة أو المكتب ة التابع ة لب ايثون مك ان ‪ package_name‬مث ل ‪Django‬‬
‫َ‬
‫شئت تنزيل ‪ NumPy‬فيمكن ك تنفي ذ‬
‫لتطوير الويب‪ ،‬أو ‪ NumPy‬إلجراء الحسابات العلمية‪ .‬لذا‪ ،‬إن‬
‫األمر ‪.pip3 install numpy‬‬
‫تس ّهل األداة ‪ setuptools‬تح زيم مش اريع ب ايثون‪ ،‬أم ا ‪ wheel‬فهي تنس يق ح زم‬
‫(‪ )built-package format‬لب ايثون يمكن ه تس ريع إنتاجي ة ال برامج عن طري ق تقلي ل ع دد الم رات‬
‫التي تحتاج فيها إلى التصريف‪.‬‬
‫ثبت في النظام بكتابة‪:‬‬
‫بعد إكمال العملية‪ ،‬يمكننا التحقق من إصدار بايثون ‪ 3‬المُ َّ‬
‫‪python3 --version‬‬
‫المثبت‪ .‬وال ذي‬
‫ستحص ل على مخرج ات في ناف ذة الطرفي ة وال تي س تريك إص دار ب ايثون‬
‫َّ‬
‫افتراضيا أحدث إصدار مستقر ومتاح من بايثون ‪.3‬‬
‫سيكون‬
‫ً‬
‫لتحديث إصدار بايثون ‪ ،3‬يمكنك أوالً تحديث ‪ ،Homebrew‬ثمَّ تحديث بايثون‪:‬‬
‫‪brew update‬‬
‫‪brew upgrade python3‬‬
‫من الممارسات الجيدة تحديث إصدار بايثون الذي تعمل به من حين آلخر‪.‬‬
‫و‪ .‬إعداد بيئة افتراضية‬
‫اآلن بع د تث بيت ‪ Xcode‬و ‪ Homebrew‬وب ايثون‪ ،‬يمكنن ا المض ي ق دمً ا إلنش اء بيئ ة‬
‫البرمجة خاصتنا‪.‬‬
‫‪65‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫ُت ِّ‬
‫مكن ك البيئ ات االفتراض ية من إنش اء مس احة معزول ة في حاس وبك مخصص ة لمش اريع‬
‫أن كل مشروع تعمل عليه ستكون له اعتماديَّ ات ه (‪ )dependencies‬الخاص ة ب ه‪،‬‬
‫بايثون‪ ،‬مما يعني َّ‬
‫ِّ‬
‫تؤثر على غيره من المشاريع‪.‬‬
‫والتي لن‬
‫ي ِّ‬
‫دارات‬
‫ٍ‬
‫وفر لن ا ض بط بيئ ةٍ برمجي ةٍ تحكمً ا أك بر بمش اريع ب ايثون‪ ،‬وإمكاني ة التعام ل م ع إص‬
‫مختلفةٍ من حزم بايثون‪ .‬وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية‪.‬‬
‫أي ع ددٍ تش اء من البيئ ات االفتراض ية‪ ،‬وك ل بيئ ة س تكون ممثل ة بمجل د في‬
‫يمكن ك ض بط ِّ‬
‫حاسوبك يحتوي على عدد من السكربتات‪.‬‬
‫اختر المجلد الذي تريد أن تضع فيه بيئات ب ايثون‪ ،‬أو يمكن ك إنش اء مجل د جدي د باس تخدام‬
‫األمر ‪ mkdir‬كما يلي‪:‬‬
‫‪mkdir environments‬‬
‫‪cd environments‬‬
‫َ‬
‫انتقلت إلى المجلد الذي تريد احت واء البيئ ات في ه‪ ،‬تس تطيع اآلن إنش اء بيئ ة جدي دة‬
‫بعد أن‬
‫بتنفيذ األمر التالي‪:‬‬
‫‪python3.6 -m venv my_env‬‬
‫سي ِ‬
‫نشئ هذا األمر مجل ًدا جدي ًدا (في هذه الحالة يُ سمى ‪ )my_env‬فيه بعض الملفات‪:‬‬
‫ُ‬
‫•‬
‫يشير الملف ‪ pyvenv.cfg‬إلى توزيعة بايثون التي استخدمتها لتنفيذ األمر‪.‬‬
‫•‬
‫يحت وي المجل د الف رعي ‪ lib‬نس خة من إص دار ب ايثون‪ ،‬ويحت وي على مجل د يس مى‬
‫ً‬
‫سيس تخدم لتخ زين وح دات‬
‫‪ ،site-packages‬والذي س يكون‬
‫فارغ ا في البداي ة‪ ،‬ولكن ه ُ‬
‫الطرف الثالث التي ستثبِّتها‪.‬‬
‫•‬
‫المجلد الفرعي ‪ include‬يُ ِّ‬
‫صرف (‪ )packages‬الحزم‪.‬‬
‫‪66‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫يحت وي المجل د الف رعي ‪ bin‬نس خة من رُ قام ة ب ايثون ( ‪ )Python binary‬جنب ا إلى جنب‬
‫•‬
‫سيستخدم‪.‬‬
‫مع سكربت التفعيل (‪ )activate shell script‬الذي ُ‬
‫أن تك ون مش اريعك معزول ٌة عن س ياق اآلل ة المحلي ة‪،‬‬
‫تعم ل ه ذه الملف ات م ع بعض ها لض مان َ‬
‫أن‬
‫لكي ال تختلط ملفات النظ ام م ع ملف ات المش اريع‪ .‬وه ذا أم رٌ حس ٌن إلدارة اإلص دارات ولض مان َّ‬
‫الحزم التي يحتاج إليها‪.‬‬
‫كل مشروع يملك وصواًل إلى‬
‫ٍ‬
‫سي ِّ‬
‫نفذ سكربت التفعيل‪:‬‬
‫عليك تفعيل البيئة الستخدامها‪ ،‬وذلك بكتابة األمر التالي الذي ُ‬
‫‪source my_env/bin/activate‬‬
‫ٌ‬
‫ابقة (‪ )prefix‬في المِ حث (‪ )prompt‬وال تي هي اس م البيئ ة‬
‫يجب أن تظه ر اآلن س‬
‫المس تخدمة‪ ،‬وفي حالتن ا ه ذه يك ون اس مها ‪ ،my_env‬وه ذا يع ني أنن ا لن سنس تخدم إال إع دادات‬
‫وحزم هذه البيئة عند إنشاء مشاريع جديدة‪.‬‬
‫ً‬
‫جاهزة لالستخدام بعد اتباعك للخطوات السابقة‪.‬‬
‫يجب أن تكون بيئتك االفتراضية‬
‫مالحظة‪ :‬يمكنك داخل البيئة االفتراضية أن تستخدم األمر ‪ python‬بداًل من ‪ python3‬واألمر ‪ pip‬ب داًل من‬
‫‪pip3‬‬
‫َ‬
‫كنت تس تخدم ب ايثون‪ 3‬خ ارج البيئ ة االفتراض ية‪ ،‬فيجب علي ك حينه ا اس تخدام‬
‫ئت أم ا إذا‬
‫إن ش َ‪.‬‬
‫ألن ‪ python‬و‪ pip‬ستستدعيان إصدارًا قديمً ا من بايثون‬
‫‪ python3‬و ‪ pip3‬حصرًا‪َّ .‬‬
‫ز‪ .‬إنشاء برنامج بسيط‬
‫ً‬
‫ً‬
‫ِ‬
‫يطا يع رض العب ارة‬
‫برنامج ا بس‬
‫لننش ئ‬
‫بع د أن أكملن ا ض بط بيئتن ا االفتراض ية‪،‬‬
‫أن البيئ ة تعم ل بالش كل الص حيح‪ ،‬ولكي تتع وَّ د على إنش اء‬
‫«مرحبا بالع الم!»‪ ،‬وبه ذا س نتحقق من َّ‬
‫َ‬
‫كنت واف ًدا جدي ًدا على اللغة‪.‬‬
‫برامج بايثون إن‬
‫‪67‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫تثبيت بايثون وإعداد بيئة العمل‬
‫علينا أواًل تشغيل محرر ملفات نصية إلنشاء ملف جديد‪ ،‬وليكن المحرر ‪ nano‬الذي يعمل من‬
‫سطر األوامر‪:‬‬
‫‪(my_env) sammys-MBP:~ sammy$ nano hello.py‬‬
‫بعد فتح الملف في نافذة الطرفية‪ ،‬سنكتب البرنامج الخاص بنا‪:‬‬
‫)"!‪print("Hello, World‬‬
‫أغلق محرر ‪ nano‬بالضغط على ‪ Ctrl+x‬ثم اضغط على ‪ y‬عندما يسألك عن حفظ الملف‪.‬‬
‫بعد أن يُ َ‬
‫غلق المحرر ‪ nano‬وتعود إلى سطر األوامر‪ ،‬حاول تنفيذ البرنامج‪:‬‬
‫‪python hello.py‬‬
‫‪(my_env) sammys-MBP:~ sammy$‬‬
‫َ‬
‫أنشأته إلى طباعة الناتج التالي في الطرفية‪:‬‬
‫سيؤدي برنامج ‪ hello.py‬الذي‬
‫!‪Hello, World‬‬
‫للخروج من البيئة‪ ،‬اكتب األمر ‪ deactivate‬وستعود إلى مجلدك األصلي‪.‬‬
‫َ‬
‫وير للغ ة ب ايثون ‪ 3‬في نظ ام ‪ ،Mac OS X‬ح ان اآلن ال وقت‬
‫تهانين ا! لق د ض‬
‫بطت اآلن بيئ ة تط ٍ‬
‫للتعمق بلغة بايثون وإنشاء برامج رائعة!‬
‫‪68‬‬
‫|‬
‫▲‬
‫‪3‬‬
‫سطر أوامر بايثون‬
‫التفاعلي‬
‫‪69‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫ً‬
‫أيض ا م ترجم‬
‫ي وفر س طر أوام ر ب ايثون التف اعلي (‪ ،)Python interactive console‬ويس مى‬
‫ب ايثون (‪ )Python interpreter‬للم برمجين طريق ة س ريعة لتنفي ذ األوام ر‪ ،‬وتجرب ة أو اختب ار‬
‫التعليمات البرمجية دون الحاجة إلى إنشاء وكتابة أي شيفرة برمجية‪.‬‬
‫يمكن الوص ول من خالل س طر األوام ر التف اعلي إلى جمي ع دوال ب ايثون المُ ض مّ نة‪ ،‬وجمي ع‬
‫ثبت ة‪ ،‬وت اريخ األوام ر‪ ،‬واإلكم ال التلق ائي‪ .‬وي وفر س طر األوام ر التف اعلي الفرص ة‬
‫الوح دات المُ َّ‬
‫الستكشاف وتجربة ش يفرات تعليم ات ب ايثون‪ ،‬والق درة على نس خ الش يفرة البرمجي ة ولص قها في‬
‫ملف الشيفرة المصدرية عندما تصبح جاهزة أي بعد تجريبها والتأكد من عملها‪.‬‬
‫س يتناول ه ذا الفص ل كيفي ة العم ل بس طر األوام ر التف اعلي لب ايثون‪ ،‬وكيفي ة االس تفادة من ه‬
‫أثناء كتابة الشيفرة‪.‬‬
‫‪ .1‬فتح سطر األوامر التفاعلي‬
‫مثبت في ه ب ايثون‪.‬‬
‫أي حاسوب محلي أو خادم َّ‬
‫يمكن الوصول إلى سطر األوامر التفاعلي من ّ‬
‫التعليم ة ال تي ستس تخدمها عمومً ا لل دخول إلى س طر األوام ر التف اعلي في اإلص دار االفتراض ي‬
‫لبايثون هي‪:‬‬
‫‪python‬‬
‫إذا أع د َّدت البيئ ة البرمجي ة وجهزته ا وف ق إرش ادات الفص ل الس ابق‪ ،‬فيمكن ك إنش اء بيئ ة‬
‫ثبت ة فيه ا عن طري ق ال دخول أواًل إلى تل ك البيئ ة (إن لم‬
‫واس تعمال إص دار ب ايثون والوح دات المُ َّ‬
‫ِّ‬
‫وجهز البيئة الوهمية قبل تنفيذ األوامر التالية)‪:‬‬
‫ُتهيِّ ئ البيئة الوهمية بعد‪ ،‬فعد إلى الفصل السابق‬
‫‪cd environments‬‬
‫‪. my_env/bin/activate‬‬
‫‪70‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫ثم اكتب األمر ‪:python‬‬
‫‪(my_env) sammy@ubuntu:~/environments$ python‬‬
‫في مثالن ا الح الي‪ ،‬اإلص دار االفتراض ي ه و ‪ ،Python 3.7.7‬وال ذي يُ ع رَ ض في المخرج ات‬
‫بمجرد إدخال األمر‪ ،‬إلى جانب إشعار حقوق الملكية‪ ،‬وبعض األوامر التي يمكن ك كتابته ا للحص ول‬
‫على معلومات إضافية‪:‬‬
‫)‪4 2020, 15:43:14‬‬
‫‪Python 3.7.7 (default, Jun‬‬
‫‪[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux‬‬
‫‪Type "help", "copyright", "credits" or "license" for more‬‬
‫‪information.‬‬
‫>>>‬
‫في بداية كل سطر ستجد ثالث عالمات "أكبر من" (<<<)‪:‬‬
‫>>>‬
‫يمكنك استهداف إصدارات محددة من بايثون عن طريق إلح اق رقم اإلص دار ب األمر‪ ،‬وب دون‬
‫مسافات مثل تنفيذ األمر ‪:python2.7‬‬
‫)‪Python 2.7.18 (default, Apr 20 2020, 00:00:00‬‬
‫‪[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux2‬‬
‫‪Type "help", "copyright", "credits" or "license" for more‬‬
‫‪information.‬‬
‫>>>‬
‫ت بيِّ ن المخرج ات لن ا َّ‬
‫أنن ا نس تخدم اإلص دار ‪ .Python 2.7.17‬إذا ك ان ه ذا ه و اإلص دار‬
‫ً‬
‫أيض ا ال دخول إلى س طر األوام ر التف اعلي باس تخدام‬
‫االفتراض ي لب ايثون ‪ ،2‬فيمكنن ا‬
‫األمر ‪.python2‬‬
‫‪71‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫بالمقاب ل‪ ،‬يمكنن ا اس تدعاء إص دار ب ايثون ‪ 3‬االفتراض ي باس تخدام األم ر ‪ python3‬فنحص ل‬
‫على المخرجات التالية‪:‬‬
‫)‪4 2020, 15:43:14‬‬
‫‪Python 3.7.7 (default, Jun‬‬
‫‪[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux‬‬
‫‪Type "help", "copyright", "credits" or "license" for more‬‬
‫‪information.‬‬
‫>>>‬
‫ً‬
‫أيضا أن نفتح سطر األوام ر التف اعلي أعاله باس تخدام األم ر ‪ .python3.7‬بع د تش غيل‬
‫يمكن‬
‫سطر األوامر التفاعلي لبايثون‪ ،‬يمكننا المضي قدمً ا والبدء في العمل‪.‬‬
‫‪ .2‬العمل في سطر أوامر بايثون التفاعلي‬
‫يقبل مترجم بايثون التفاعلي (‪ )Python interactive interpreter‬قواعد لغة بايثون‪ ،‬والتي‬
‫تضعها بعد البادئة <<<‪.‬‬
‫يمكننا‪ ،‬على سبيل المثال‪ ،‬إنشاء متغيِّ ر وإسناد قيمة له بالشكل التالي‪:‬‬
‫‪>>> birth_year = 1868‬‬
‫بمج رد تع يين قيم ة الع دد الص حيح ‪ 1868‬إلى المتغيِّ ر ‪ ،birth_year‬سنض غط على زر‬
‫اإلدخال ونحصل على سطر جديد يبدأ بثالث عالمات "أكبر من" (<<<)‪:‬‬
‫‪>>> birth_year = 1868‬‬
‫>>>‬
‫يمكننا االستمرار في تعيين المتغيِّ رات‪ ،‬وإجراء الحسابات الرياضياتية‪:‬‬
‫‪72‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫‪>>> birth_year = 1868‬‬
‫‪>>> death_year = 1921‬‬
‫‪>>> age_at_death = death_year - birth_year‬‬
‫)‪>>> print(age_at_death‬‬
‫‪53‬‬
‫>>>‬
‫كم ا نفع ل في ملف ات ال برامج النص ية (الس كربتات)‪ ،‬أنش أنا متغ يرات جدي دة أخ رى وأس ندنا‬
‫قيم ًة له ا تناس ب اس مها‪ ،‬ثم طرحن ا قيم ة متغيِّ ٍر من آخ ر‪ ،‬وطلبن ا من س طر األوام ر طباع ة المتغ ير‬
‫الذي ِّ‬
‫يمثل الفرق عبر الدالة )(‪.print‬‬
‫ً‬
‫أيضا استخدام سطر األوامر التفاعلي كآلة حاسبة‪:‬‬
‫يمكنك‬
‫‪>>> 203 / 20‬‬
‫‪10.15‬‬
‫>>>‬
‫هنا‪ ،‬قسمنا العدد الصحيح ‪ 203‬على ‪ ،20‬لنحصل على الناتج ‪.10.15‬‬
‫تعدد األسطر‬
‫‪.3‬‬
‫ُّ‬
‫عن دما نكتب ش يفرة متع ددة األس طر‪ ،‬سيس تخدم الم ترجم أس طر االس تمرارية‪ ،‬وهي أس طر‬
‫مس بوقة بثالث نق اط ‪ ...‬وللخ روج من ه ذا الوض ع‪ ،‬س تحتاج إلى الض غط على ال زر‬
‫‪ ENTER‬مرتين‪.‬‬
‫رطية لتحدي د م ا‬
‫تعين الش يفرة التالي ة قيم تي متغيِّ رين‪ ،‬ثم تس تخدم تعليم ة ش‬
‫َّ‬
‫َّ‬
‫يجب طباعته‪:‬‬
‫‪73‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫'‪>>> sammy = 'Sammy‬‬
‫'‪>>> shark = 'Shark‬‬
‫‪>>> if len(sammy) > len(shark):‬‬
‫‪...‬‬
‫)'‪print('Sammy codes in Java.‬‬
‫‪... else:‬‬
‫‪...‬‬
‫)'‪print('Sammy codes in Python.‬‬
‫‪...‬‬
‫‪Sammy codes in Python.‬‬
‫>>>‬
‫في هذه الحالة‪ ،‬يتساوى طوال السلسلتين النصيتين‪ ،‬لذلك يتم تنفيذ التعليمة ‪.else‬‬
‫الحظ َّ‬
‫أنك ستحتاج إلى الحفاظ على مسافة بادئة بايثون (‪ )Python indenting‬المؤلفة من‬
‫ٌأ‬
‫سي َ‬
‫طلق خط ‪:‬‬
‫أربعة مسافات بيضاء‪ ،‬وإال ُ‬
‫‪>>> if len(sammy) > len(shark):‬‬
‫)'‪... print('Sammy codes in Java.‬‬
‫‪File "<stdin>", line 2‬‬
‫)'‪print('Sammy codes in Java.‬‬
‫^‬
‫‪IndentationError: expected an indented block‬‬
‫>>>‬
‫ً‬
‫أيض ا‬
‫إض افة إلى تجرب ة التعليم ات البرمجي ة متع ددة األس طر في س طر األوام ر‪ ،‬يمكن ك‬
‫استيراد الوحدات‪.‬‬
‫‪ .4‬استيراد الوحدات‬
‫ِّ‬
‫ً‬
‫ً‬
‫متوفرة في بيئ ة‬
‫معينة‬
‫سريعة للتحقق مما إذا كانت وحدات‬
‫طريقة‬
‫يوفر لك مترجم بايثون‬
‫َّ‬
‫الحالية‪ .‬يمكنك ذلك باستخدام التعليمة ‪:import‬‬
‫البرمجة‬
‫َّ‬
‫‪74‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
>>> import matplotlib
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'matplotlib'
‫ لتث بيت‬.‫ متاح ة في بيئ ة البرمج ة الحالي ة‬matplotlib ‫ لم تكن الوح دة‬،‫في الحال ة أعاله‬
pip ‫ وتثبيته ا باس تخدام أداة إدارة الح زم‬،‫ س تحتاج إلى ت رك الم ترجم التف اعلي‬،‫تل ك الوح دة‬
:‫مثل العادة‬
(my_env) sammy@ubuntu:~/environments$ pip install matplotlib
Collecting matplotlib
Downloading matplotlib-2.0.2-cp35-cp35m-manylinux1_x86_64.whl
(14.6MB)
...
Installing collected packages: pyparsing, cycler, pythondateutil, numpy, pytz, matplotlib
Successfully installed cycler-0.10.0 matplotlib-2.0.2 numpy1.13.0 pyparsing-2.2.0 python-dateutil-2.6.0 pytz-2017.2
‫ يمكن ك الع ودة إلى‬،‫ هي وجمي ع تبعياته ا بنج اح‬matplotlib ‫بمج رد تث بيت الوح دة‬
:‫المترجم التفاعلي‬
(my_env) sammy@ubuntu:~/environments$ python
‫ ويمكن ك اس تخدام الوح دة‬،‫أي رسالة خطأ إن استوردت الوح دة‬
َّ ‫ لن تتلقى‬،‫في هذه المرحلة‬
.‫ أو داخل ملف‬،‫المثبتة إما داخل سطر األوامر‬
▲
|
75
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫‪ .5‬الخروج من سطر أوامر بايثون التفاعلي‬
‫هن اك طريقت ان رئيس يتان للخ روج من س طر األوام ر التف اعلي‪ :‬إم ا اس تخدام اختص ار لوح ة‬
‫المفاتيح‪ ،‬أو استخدام دالة من دوال بايثون‪.‬‬
‫اختص ار لوح ة المف اتيح ه و ‪ CTRL+D‬في أنظم ة *نيكس (أي لينكس وي ونكس)‪ ،‬أو ‪CTRL+Z‬‬
‫األصلية‪:‬‬
‫الطرفية‬
‫ثم ‪ CTRL‬في أنظمة ويندوز‪ ،‬وبذلك ستخرج من سطر األوامر‪ ،‬وتعود إلى البيئة‬
‫َّ‬
‫َّ‬
‫‪...‬‬
‫‪>>> age_at_death = death_year - birth_year‬‬
‫)‪>>> print(age_at_death‬‬
‫‪53‬‬
‫>>>‬
‫‪sammy@ubuntu:~/environments$‬‬
‫ب داًل من ذل ك‪ ،‬س تنهي الدال ة )(‪ quit‬س طر األوام ر التف اعلي‪ ،‬وتعي دك إلى بيئ ة المحط ة‬
‫ً‬
‫سابقا‪:‬‬
‫الطرفية األصلية التي كنت فيها‬
‫'‪>>> octopus = 'Ollie‬‬
‫)(‪>>> quit‬‬
‫‪sammy@PythonUbuntu:~/environments$‬‬
‫في ح ال اس تخدام الدال ة )(‪ ،quit‬فس ُتؤرَّ خ في مل ف الت اريخ (‪ ،)history file‬بالمقاب ل لن‬
‫يُ َّ‬
‫سجل اختصار لوحة المفاتيح ‪ CTRL+D‬ذلك‪:‬‬
‫‪76‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫سطر أوامر بايثون التفاعلي‬
‫الملف ‪# /home/sammy/.python_history‬‬
‫‪...‬‬
‫‪age_at_death = death_year - birth_year‬‬
‫)‪print(age_at_death‬‬
‫'‪octopus = 'Ollie‬‬
‫)(‪quit‬‬
‫يمكن إنهاء مترجم بايثون بكال الطريقتين‪ ،‬فاختر ما يناسبك‪.‬‬
‫‪ .6‬االطالع على التاريخ‬
‫أن جمي ع أوام رك ت ؤرَّ خ في المل ف ‪ .python_history‬في‬
‫من فوائ د س طر األوام ر التف اعلي ّ‬
‫أي محرر نصي‪ ،‬مثل ‪:nano‬‬
‫أنظمة *ينكس‪ ،‬بحيث يمكنك االطالع عليها في ّ‬
‫‪nano ~/.python_history‬‬
‫بمج رد فتح ه باس تخدام مح رر نص وص‪ ،‬س يبدو مل ف ت أريخ ب ايثون الخ اص ب ك على‬
‫هذا النحو‪:‬‬
‫الملف ‪# /home/sammy/.python_history‬‬
‫‪import pygame‬‬
‫)(‪quit‬‬
‫‪if 10 > 5:‬‬
‫)"‪print("hello, world‬‬
‫‪else:‬‬
‫)"‪print("nope‬‬
‫'‪sammy = 'Sammy‬‬
‫'‪shark = 'Shark‬‬
‫‪...‬‬
‫بمجرد االنتهاء من ملفك‪ ،‬يمكنك الضغط على ‪ CTRL+X‬للخروج‪.‬‬
‫‪77‬‬
‫|‬
‫▲‬
‫سطر أوامر بايثون التفاعلي‬
‫البرمجة بلغة بايثون‬
‫من خالل تتبع األحداث المُ ؤرَّخة في بايثون‪ ،‬يمكنك الرجوع إلى األوام ر والتج ارب الس ابقة‪،‬‬
‫ونسخ ولصق أو تعديل الشيفرة الستخدامها في الملفات البرمجية أو في ‪.Jupyter Notebook‬‬
‫‪ .7‬خالصة الفصل‬
‫سطر األوامر التفاعلي ه و فض ٌ‬
‫اء لتجرب ة ش يفرة ب ايثون‪ ،‬إذ يمكن ك اس تخدامه أداة لالختب ار‬
‫والتجريب وغير ذلك‪.‬‬
‫لتنقيح (‪ )Debug‬ملف ات البرمج ة في ب ايثون‪ ،‬يمكن ك اس تخدام الوح دة ‪ code‬لفتح م ترجم‬
‫تف اعلي داخ ل مل ف‪ ،‬وس نتحدث عن ذل ك بالتفص يل في الفص ل الالح ق‪ :‬كيفي ة تنقيح ب ايثون‬
‫باستخدام سطر األوامر التفاعلي‪.‬‬
‫‪78‬‬
‫|‬
‫▲‬
‫‪4‬‬
‫التعليقات‬
‫واستخداماتها‬
‫‪79‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
‫زءا منه ا‪ ،‬إذ تتجاهله ا‬
‫التعليق ات هي عب ارات دخيل ة على الش يفرات البرمجي ة وليس ت ج ً‬
‫المُ ص ِّرفات (‪ )compilers‬والمترجم ات (‪ .)interpreters‬يُ س ِّهل تض مين التعليق ات في الش يفرات‬
‫من قراءتها وفهمها ومعرفة وظيفة كل جزء من أجزائها‪َّ ،‬‬
‫ألنها توفر معلومات وش روحات ح ول م ا‬
‫يفعله كل جزء من البرنامج‪.‬‬
‫اء على الغ رض من البرن امج‪ ،‬يمكن أن تك ون التعليق ات بمثاب ة مُ َّ‬
‫ذكرات ل ك‪ ،‬أو يمكن ك‬
‫بن ً‬
‫كتابتها لمساعدة المبرمجين اآلخرين على فهم الشيفرة‪.‬‬
‫ستحسن كتابة التعليقات أثناء كتابة البرامج أو تح ديثها‪َّ ،‬‬
‫يُ‬
‫ألنك ق د تنس ى الس ياق وتسلس ل‬
‫َ‬
‫ً‬
‫الحقا‪ ،‬والتعليقات القديمة قد تصبح عديمة الفائدة ومضللة إن لم ُتح َّدث‪.‬‬
‫األفكار‬
‫‪ .1‬صياغة التعليقات‬
‫تبدأ التعليقات السطرية في بايثون بالعالمة ‪ #‬ومسافة بيض اء‪ ،‬وتس تمر ح تى نهاي ة الس طر‪.‬‬
‫بشكل عام‪ ،‬ستبدو التعليقات على النحو التالي‪:‬‬
‫هذا تعليق ‪#‬‬
‫ألن التعليق ات ال ُت َّ‬
‫نفذ‪ ،‬فعن د تش غيل البرن امج‪ ،‬لن ت رى أي إش ارة للتعليق ات‪ ،‬فالتعليق ات‬
‫نظرًا َّ‬
‫توض ع في الش يفرة المص درية ليقرأه ا الن اس‪ ،‬وليس للتنفي ذ‪ .‬في برن امج " !‪ "Hello, World‬ق د‬
‫يبدو التعليق كما يلي‪:‬‬
‫طبع "!‪ "Hello, World‬في سطر األوامر ‪#‬‬
‫)"!‪print("Hello, World‬‬
‫‪80‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
‫في الحلقة ‪ ،for‬قد تبدو التعليقات كما يلي‪:‬‬
‫تعريف المتغير ‪ sharks‬كمصفوفة من السالسل النصية ‪#‬‬
‫‪sharks = ['hammerhead', 'great white', 'dogfish', 'frilled',‬‬
‫]'‪'bullhead', 'requiem‬‬
‫حلقة ‪ For‬تمر على المصفوفة ‪# sharks‬‬
‫‪for shark in sharks:‬‬
‫)‪print(shark‬‬
‫يجب أن ُتح اذى التعليق ات على نفس المس افة البادئ ة (‪ )indent‬للش يفرة ال تي َّ‬
‫تعلق عليه ا‪.‬‬
‫ً‬
‫أيض ا ب دون مس افة بادئ ة‪،‬‬
‫أن التعليق ات على دال ة ليس له ا مس افة بادئ ة س تكون هي‬
‫بمع نى َّ‬
‫وسيكون لكل مستوى من المسافات البادئة التالي ة تعليق ات تتواف ق م ع الش يفرات البرمجي ة ال تي‬
‫ِّ‬
‫تعلق عليها‪.‬‬
‫على س بيل المث ال‪ ،‬الش يفرة التالي ة تع رّ ف الدال ة )(‪ again‬ال تي تس أل المس تخدم إن ك ان‬
‫يريد استخدام الحاسبة مج َّد ًدا‪ ،‬مع بعض التعليقات‪:‬‬
‫‪...‬‬
‫تعريف الدالة )(‪ again‬لسؤال المستخدم ‪#‬‬
‫إن كان يريد استخدام الحاسبة مجددا ‪#‬‬
‫‪def again():‬‬
‫أخذ المدخالت من المستخدم ‪#‬‬
‫'''(‪calc_again = input‬‬
‫?‪Do you want to calculate again‬‬
‫‪Please type Y for YES or N for NO.‬‬
‫)'''‬
‫ُنّ‬
‫فذ الدالة )(‪# calculate‬‬
‫إن أدخل المستخدم ‪ Y‬فست‬
‫‪81‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
‫‪if calc_again == 'Y':‬‬
‫)(‪calculate‬‬
‫إن كتب المستخدم ‪ N‬فقل وداعا للمستخدم وأنه البرنامج ‪#‬‬
‫‪elif calc_again == 'N':‬‬
‫)'‪print('See you later.‬‬
‫ًا آخر‪ ،‬فأعد تنفيذ الدالة ‪#‬‬
‫إن أدخل المستخدم حرف‬
‫‪else:‬‬
‫)(‪again‬‬
‫أي ش خص آخ ر يس تخدم مش روعه أو‬
‫الهدف من التعليقات هو مساعدة المبرمج األص لي‪ ،‬أو َّ‬
‫ً‬
‫حيحا‪ ،‬وب التوازي م ع‬
‫يتع اون مع ه‪ ،‬على فهم ه‪ .‬وإذا تع ّذر ص يانة التعليق ات وتح ديثها تح دي ًثا ص‬
‫فإن عدم تضمين التعليقات قد يكون أفضل من كتابة تعليق يتناقض مع الشيفرة‪.‬‬
‫الشيفرة‪،‬‬
‫َّ‬
‫يجب أن تجيب التعليق ات عن س ؤال "لم اذا" ب داًل من "م اذا" أو "كي ف"‪َّ .‬‬
‫ألنه م ا لم تكن‬
‫َّ‬
‫اف لفهم م ا ال ذي تفعل ه الش يفرة‪ ،‬أو‬
‫ومعقدة‪ ،‬ف إن النظ ر إلى الش يفرة عمومً ا ك ٍ‬
‫الش يفرة ص عبة‬
‫كيف تفعله‪.‬‬
‫‪ .2‬التعليقات الكتلية‬
‫يمكن اس تخدام التعليق ات الكتلي ة (‪ )Block Comments‬لتوض يح الش يفرات البرمجي ة‬
‫َّ‬
‫المعقدة ال تي ال تتوق ع أن يك ون الق ارئ على دراي ة به ا‪ .‬تنطب ق ه ذه التعليق ات الطويل ة على ج زء‬
‫من الشيفرة أو جميعها‪ ،‬كما توضع في نفس مستوى المسافة البادئة للشيفرة‪.‬‬
‫في التعليقات الكتلية‪ ،‬يبدأ كل سطر بالعالمة ‪ #‬تليها بمسافة بيضاء واحدة‪ .‬إذا كنت بحاجة‬
‫إلى استخدام أكثر من فقرة واحدة‪ ،‬فيجب فصلها بسطر يحتوي على عالمة ‪ #‬واحدة‪.‬‬
‫‪82‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
‫فيما يلي مثال على كتلة تعليقات تشرح ما يحدث في الدالة )(‪ main‬المعرفة أدناه‪:‬‬
‫سوف تحلل الدالة ‪ main‬الوسائط عبر المتغير ‪# parser‬‬
‫ّ‬
‫َد بواسطة المستخدم على سطر األوامر‪ .‬هذا سيمرر ‪#‬‬
‫ُحد‬
‫الوسائط ست‬
‫الوسيط ‪ word‬الذي يريد المستخدم تحليله مع اسم الملف ‪#‬‬
‫ُدخل ‪#‬‬
‫المراد استخدامه‪ ،‬وكذلك تقديم نص مساعد إذا لم ي‬
‫المستخدم الوسيط بشكل صحيح ‪#‬‬
‫‪def main():‬‬
‫)(‪parser = argparse.ArgumentParser‬‬
‫(‪parser.add_argument‬‬
‫‪"word",‬‬
‫"‪help="the word to be searched for in the text file.‬‬
‫)‬
‫(‪parser.add_argument‬‬
‫‪"filename",‬‬
‫"‪help="the path to the text file to be searched through‬‬
‫)‬
‫‪...‬‬
‫ً‬
‫عادة عندما تك ون الش يفرة غ ير واض حة‪ ،‬وتتطلب ش ً‬
‫رحا ش امال‪.‬‬
‫ُتستخ َدم التعليقات الكتلية‬
‫يجب أن تتجنب اإلفراط في التعليق على الشيفرة‪ ،‬ويجب أن تث ق في ق درة الم برمجين اآلخ رين‬
‫على فهم الشيفرة‪ ،‬إال إذا كنت تكتب لجمهور معين‪.‬‬
‫‪ .3‬التعليقات السطرية‬
‫توضع التعليقات السطرية (‪ )Inline comments‬على نفس الس طر ال ذي توج د في ه التعليم ة‬
‫البرمجية‪ .‬ومثل التعليقات األخرى‪َّ ،‬‬
‫فإنها تبدأ بالعالمة ‪ #‬ومسافة بيضاء واحدة‪.‬‬
‫بشكل عام‪ ،‬تبدو التعليقات السطرية كما يلي‪:‬‬
‫تعليق مضمن حول الشيفرة ‪#‬‬
‫]‪[code‬‬
‫‪83‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
‫ال ينبغي اإلكثار من استخدام التعليقات السطرية‪ ،‬ولكن عند اس تخدامها في محله ا يمكن أن‬
‫أيض ا إن ظننت َّ‬
‫ً‬
‫أنك ق د ال تت ذكر‬
‫تكون فعالة لشرح األجزاء الصعبة من الشيفرة‪ .‬وقد تكون مفيدة‬
‫س ط ًرا من الش يفرة في المس تقبل‪ ،‬أو إذا كنت تتع اون م ع ش خص ق د ال يك ون على دراي ة بجمي ع‬
‫جوانب الشيفرة‪.‬‬
‫أن‬
‫على سبيل المث ال‪ ،‬إذا لم يكن هن اك توض يح مس بق‪ ،‬فق د ال تعلم أنت أو المتع اونون مع ك َّ‬
‫الشيفرة التالية تنشئ عد ًدا عِ قديًّ ا‪ ،‬لذلك قد ترغب في إضافة تعليق مضمَّ ن‪:‬‬
‫إنشاء عدد عقدي ‪#‬‬
‫‪z = 2.5 + 3j‬‬
‫ً‬
‫أيض ا اس تخدام التعليق ات الس طريَّ ة لش رح الس بب وراء فع ل ش يء م ا‪ ،‬أو بعض‬
‫يمكن‬
‫المعلومات اإلضافية‪ ،‬كما في المثال التالي‪:‬‬
‫ابتداء ‪ x‬بقيمة عشوائية ‪#‬‬
‫‪x = 8‬‬
‫يجب اس تخدام التعليق ات الس طرية عن د الض رورة وحس ب‪ ،‬كم ا ينبغي أن ت ِّ‬
‫وفر إرش ادات‬
‫مفيدة للشخص الذي يقرأ البرنامج‪.‬‬
‫‪ .4‬تعليق جزء من الشيفرة بدواعي االختبار والتنقيح‬
‫باإلض افة إلى اس تخدام التعليق ات وس ً‬
‫ً‬
‫أيض ا اس تخدام العالم ة ‪#‬‬
‫يلة لتوثي ق الش يفرة‪ ،‬يمكن‬
‫لتعلي ق ج زء من الش يفرة وتعطيل ه أثن اء اختب ار أو تنقيح البرن امج ال ذي تعم ل علي ه‪ .‬أي عن دما‬
‫تواج ه أخط اء بع د إض افة أس طر جدي دة إلى الش يفرة‪ ،‬فق د ت رغب في تعلي ق بعض ها لمعرف ة‬
‫موض ع الخل ل‪ .‬يمكن أن ي تيح ل ك اس تخدام العالم ة ‪ #‬تجرب ة ب دائل أخ رى أثن اء إع داد الش يفرة‪.‬‬
‫على س بيل المث ال‪ ،‬ق د تفاض ل بين اس تخدام الحلق ة ‪ while‬أو حلق ة ‪ for‬أثن اء برمج ة لعب ة‪،‬‬
‫ويمكنك تعليق إحداهما بينما تختبر أيّ هما أفضل‪:‬‬
‫‪84‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليقات واستخداماتها‬
import random
number = random.randint(1, 25)
# number_of_guesses = 0
for i in range(5):
# while number_of_guesses < 5:
print('Guess a number between 1 and 25:')
guess = input()
guess = int(guess)
# number_of_guesses = number_of_guesses + 1
if guess < number:
print('Your guess is too low')
if guess > number:
print('Your guess is too high')
if guess == number:
break
if guess == number:
print('You guessed the number!')
else:
print('You did not guess the number. The number was ' +
str(number))
▲
|
85
‫التعليقات واستخداماتها‬
‫البرمجة بلغة بايثون‬
‫برمجية‪ ،‬باإلض افة إلى‬
‫ي تيح ل ك تعلي ق الش يفرة البرمجي ة تجرب ة ع َّدة طرائ ق ومقارب ات‬
‫َّ‬
‫مساعدتك على العثور على مكمن الخطأ من خالل التعليق المنهجي لبعض أجزاء البرنامج‪.‬‬
‫‪ .5‬خالصة الفصل‬
‫واء‬
‫سيس اعدك اس تخدام التعليق ات في ب رامج ب ايثون على جع ل برامج ك أك ثر مقروئي ة‪ ،‬س ً‬
‫ِّ‬
‫ستسهل تع اون اآلخ رين مع ك في مش اريع‬
‫لك أو لغيرك‪ .‬التعليقات المناسبة وذات الصلة والمفيدة‬
‫البرمجة وتجعل شيفرتك أكثر قيمة‪.‬‬
‫‪86‬‬
‫|‬
‫▲‬
‫‪5‬‬
‫المتغيرات‬
‫واستخداماتها‬
‫‪87‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫المتغ يرات (‪ )variables‬هي مفه وم ب رمجي مهم‪َّ .‬‬
‫إنه ا رم وز ت دل على البيان ات ال تي‬
‫تستخدمها في برنامجك‪ ،‬أي تعد حاويات للبيانات التي ستتعامل معها في برنامج‪.‬‬
‫ً‬
‫حيحا في‬
‫سيغطي هذا الفصل بعض أساسيات المتغ يرات‪ ،‬وكيفي ة اس تخدامها اس تخدامً ا ص‬
‫برامج بايثون ‪.3‬‬
‫‪ .1‬فهم المتغيرات‬
‫خصص للمتغير مساحة تخزيني ة في ال ذاكرة توض ع القيم ة المرتبط ة ب ه‬
‫من الناحية الفنية‪ ،‬يُ َّ‬
‫فيها‪ .‬يُ ستخدم اسم المتغير لإلشارة إلى تلك القيمة المُ َّ‬
‫خزنة في ذاكرة البرنامج التي هي جزء من‬
‫عينة‪:‬‬
‫ذاكرة الحاسوب‪ .‬المُ تغيِّ ر أشبه بعنوان ُتلصقه على قيمة مُ َّ‬
‫حيحا يس اوي ‪ ،103204934813‬ونري د تخزين ه في متغيِّ ر ب داًل‬
‫ً‬
‫أن ل دينا ع د ًدا ص‬
‫لنف ترض ّ‬
‫من إع ادة كتاب ة ه ذا الع دد الطوي ل ك ل م رة‪ ،‬ل ذلك سنس تخدم ش يًئ ا يُ س ِّهل ت ُّ‬
‫ذكره‪ ،‬مثل‬
‫المتغير ‪:my_int‬‬
‫‪my_int = 103204934813‬‬
‫إذا نظرنا إليه على َّ‬
‫عنوان مرتبط بقيمة‪ ،‬فسيبدو على النحو التالي‪:‬‬
‫أنه‬
‫ٌ‬
‫‪88‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫عن وان القيم ة ه و ‪ my_int‬المكت وب عليه ا‪ ،‬والقيم ة هي ‪( 103204934813‬نوعه ا ع دد‬
‫صحيح‪ ،‬سنتطرق إلى أنواع البيانات في الفصل التالي)‪.‬‬
‫التعليم ة ‪= 103204934813‬‬
‫‪ my_int‬هي تعليم ة إس ناد ( ‪،)assignment statement‬‬
‫وتتألف من األجزاء التالية‪:‬‬
‫•‬
‫اسم المتغير (‪)my_int‬‬
‫•‬
‫ً‬
‫أيضا باسم "عالمة المساواة" (=)‬
‫معامل اإلسناد‪ ،‬المعروف‬
‫•‬
‫ُأ‬
‫القيمة التي س ِن َدت إلى اسم المتغير (‪)103204934813‬‬
‫تش كل ه ذه األج زاء الثالث ة معً ا التعليم ة ال تي ُتس نِد على المتغ ير ‪ my_int‬القيم ة العددي ة‬
‫الصحيحة ‪. 103204934813‬‬
‫هيئن ا أو أنش أنا ذل ك المتغ ير‪ .‬وبع د ذل ك‪ ،‬يمكنن ا‬
‫بمج رد تع يين قيم ة متغيِّ ر م ا‪ ،‬نك ون ق د َّ‬
‫اس تخدام ذل ك المتغ ير ب داًل من القيم ة‪ .‬في ب ايثون‪ ،‬ال يل زم التص ريح عن المتغيِّ رات قب ل‬
‫اس تخدامها كم ا ه و الح ال في بعض لغ ات البرمج ة األخ رى‪ ،‬إذ يمكن ك الب دء في اس تخدام‬
‫ً‬
‫مباشرة‪.‬‬
‫المتغير‬
‫بمج رد إس ناد القيم ة القيم ة ‪ 103204934813‬إلى المتغ ير ‪ ،my_int‬يمكنن ا اس تخدام ‪my_int‬‬
‫مكان العدد الصحيح‪ ،‬كما في المثال التالي‪:‬‬
‫‪89‬‬
‫|‬
‫▲‬
‫المتغيرات واستخداماتها‬
‫البرمجة بلغة بايثون‬
‫)‪print(my_int‬‬
‫والمخرجات هي‪:‬‬
‫‪103204934813‬‬
‫اس تخدام المتغ يرات يس هل علين ا إج راء العملي ات الحس ابية‪ .‬في المث ال الت الي‪ ،‬سنس تخدم‬
‫التعليمة السابقة‪ ، my_int = 1040 ،‬ثم سنطرح من المتغير ‪ my_int‬القيمة ‪: 813‬‬
‫)‪print(my_int - 813‬‬
‫وسينتج لنا‪:‬‬
‫‪103204934000‬‬
‫في هذا المثال‪ ،‬يج ري ب ايثون العملي ة الحس ابية‪ ،‬ويط رح ‪ 813‬من المتغ ير ‪ ، my_int‬ويعي د‬
‫القيمة ‪.103204934000‬‬
‫يمكن ضبط المتغيرات وجعلها تساوي ناتج عملية حس ابية‪ .‬دعن ا نجم ع ع ددين معً ا‪ ،‬ونخ ِّزن‬
‫قيمة المجموع في المتغير ‪:x‬‬
‫‪x = 76 + 145‬‬
‫يشبه المثال أعاله إحدى المعادالت التي تراها في كتب الجبر‪ .‬في الج بر‪ُ ،‬تس تخ َدم الح روف‬
‫والرم وز لتمثي ل األع داد والكمي ات داخ ل الص يغ والمع ادالت‪ ،‬وبش كل مماث ل‪ ،‬المتغ يرات أس ماء‬
‫ايثون‪،‬أن َعلي ك التأك د دائمً ا من وض ع‬
‫معين‪ .‬الف رق في لغ ة ب‬
‫رمزي ة تمث ل قيم ة من ن وع بيان ات‬
‫ّ‬
‫َّ‬
‫المتغير على الجانب األيسر من المعادلة‪.‬‬
‫‪90‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫لنطبع ‪:x‬‬
‫)‪print(x‬‬
‫والمخرجات‪:‬‬
‫‪221‬‬
‫َّ ُأ‬
‫ألنه سنِد إلى المتغير ‪ x‬مجموع ‪ 76‬و ‪.145‬‬
‫أعادت بايثون القيمة ‪221‬‬
‫يمكن أن تحوي المتغيِّ رات أي نوع من أنواع البيانات‪ ،‬وليس األعداد الصحيحة فقط‪:‬‬
‫'!‪my_string = 'Hello, World‬‬
‫‪my_flt = 45.06‬‬
‫القيم المنطقية ستعيد إما ‪ False‬أو ‪my_bool = 5 > 9 # True‬‬
‫]'‪my_list = ['item_1', 'item_2', 'item_3', 'item_4‬‬
‫)'‪my_tuple = ('one', 'two', 'three‬‬
‫}'&' ‪my_dict = {'letter': 'g', 'number': 'seven', 'symbol':‬‬
‫إذا طبعت أيًّ ا من المتغيِّ رات الم ذكورة أعاله‪ ،‬فس تعيد ب ايثون قيم ة المتغيِّ ر‪ .‬على س بيل‬
‫المثال‪ ،‬في الشيفرة التالية سنطبع متغيرًا يحتوي قائمة‪:‬‬
‫]'‪my_list = ['item_1', 'item_2', 'item_3', 'item_4‬‬
‫)‪print(my_list‬‬
‫وسينتج لنا‪:‬‬
‫]'‪['item_1', 'item_2', 'item_3', 'item_4‬‬
‫لق د مرَّ رن ا القيم ة ['‪ 'item_1‬و '‪ 'item_2‬و '‪ 'item_3‬و '‪ ]'item_4‬إلى‬
‫المتغير ‪ ،my_list‬ثم استخدمنا الدالة )(‪ print‬لطباعة تلك القيمة باستدعاء ‪.my_list‬‬
‫‪91‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫ً‬
‫ً‬
‫غيرة من ذاك رة الحاس وب‪ ،‬وتقب ل قيمً ا ُت َ‬
‫ُت ِّ‬
‫وض ع بع د ذل ك في‬
‫احة ص‬
‫خص ص المتغيِّ رات مس‬
‫تلك المساحة‪.‬‬
‫‪ .2‬قواعد تسمية المتغيرات‬
‫تتس م تس مية المتغ يرات بمرون ة عالي ة‪ ،‬ولكن هن اك بعض القواع د ال تي علي ك أخ ذها‬
‫في الحسبان‪:‬‬
‫•‬
‫يجب أن تكون أسماء المتغيرات من كلمة واحدة فقط (بدون مسافات)‬
‫•‬
‫يجب أن تتكوَّ ن أسماء المتغيرات من األحرف واألرقام والشرطة السفلية (_) فقط‬
‫•‬
‫ال ينبغي أن تبدأ أسماء المتغيرات برقم‬
‫باتباع القواعد المذكورة أعاله‪ ،‬دعنا نلقي نظرة على بعض األمثلة‪:‬‬
‫اسم غير صحيح‬
‫اسم صحيح‬
‫لماذا غير صالح؟‬
‫‪my-int‬‬
‫‪my_int‬‬
‫غير مسموح بالشرطات‬
‫‪4int‬‬
‫‪int4‬‬
‫ال يمكن البدء برقم‬
‫‪$MY_INT‬‬
‫‪MY_INT‬‬
‫أي رمز غير‬
‫ال يمكن استخدام ّ‬
‫‪another int‬‬
‫‪another_int‬‬
‫الشرطة السفلية‬
‫ال ينبغي أن يتكون االسم من أكثر‬
‫من كلمة واحدة‬
‫من األم ور ال تي يجب أخ ذها في الحس بان عن د تس مية المتغ يرات‪ ،‬ه و َّ‬
‫أنه ا حساس ة لحال ة‬
‫أن ‪ my_int‬و ‪ MY_INT‬و ‪ My_Int‬و ‪ mY_iNt‬كله ا مختلف ة‪ .‬ينبغي أن تتجنب‬
‫األحرف‪ ،‬وهذا يعني َّ‬
‫‪92‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫اس تخدام أس ماء متغيِّ رات متماثل ة لض مان أال يح دث خل ط عن دك أو عن د المتع اونين مع ك‪ ،‬س واء‬
‫الحاليين والمستقبليِّ ين‪.‬‬
‫أخ يرًا‪ ،‬ه ذه بعض المالحظ ات ح ول أس لوب التس مية‪ .‬من المتع ارف علي ه عن د تس مية‬
‫المتغيرات أن تبدأ اسم المتغير بحرف ص غير‪ ،‬وأن تس تخدم الش رطة الس فلية عن د فص ل الكلم ات‪.‬‬
‫ِّ‬
‫ً‬
‫يفض ل بعض األش خاص اس تعمال تنس يق س نام الجم ل‬
‫أيض ا‪ ،‬وق د‬
‫الب دء بح رف كب ير مقب ول‬
‫ولكن ه ذه الخي ارات‬
‫(‪ ،camelCase‬الخلط بين األحرف الكب يرة والص غيرة) عن د كتاب ة المتغ يرات‪،‬‬
‫َّ‬
‫أقل شهرة‪.‬‬
‫تنسيق غير شائع‬
‫تنسيق شائع‬
‫‪myInt‬‬
‫‪my_int‬‬
‫‪Int4‬‬
‫‪int4‬‬
‫‪myFirstString‬‬
‫‪my_first_string‬‬
‫لماذا غير متعارف عليه‬
‫أسلوب سنام الجمل‬
‫(‪ )camelCase‬غير شائع‬
‫الحرف األول كبير‬
‫أسلوب سنام الجمل‬
‫(‪ )camelCase‬غير شائع‬
‫الخي ار األهم ال ذي علي ك التمس ك ب ه ه و االتس اق‪ .‬إذا ب دأت العم ل في مش روع يس تخدم‬
‫تنسيق سنام الجمل في تسمية المتغيرات‪ ،‬فمن األفضل االستمرار في استخدام ذلك التنسيق‪.‬‬
‫يمكنك مراجعة توثيق تنس يق الش يفرات البرمجي ة في ب ايثون في موس وعة حس وب للمزي د‬
‫من التفاصيل‪.‬‬
‫‪93‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫‪ .3‬تغيير قيم المتغيرات‬
‫كما تشير إلى ذلك كلمة "متغيِّ ر"‪ ،‬يمكن تغيير قيم المتغيرات في ب ايثون بس هولة‪ .‬ه ذا يع ني‬
‫ُأ‬
‫ً‬
‫َّ‬
‫مسبقا بسهولة بالغة‪.‬‬
‫أنه يمكنك تعيين قيمة مختلفة إلى متغير س ِن َدت له قيمة‬
‫القدرة على إع ادة إس ناد القيم مفي دة للغاي ة‪ ،‬إذ ق د تحت اج خالل أط وار برنامج ك إلى قب ول‬
‫قيم ينشئها المستخدم ُ‬
‫وتحيلها على متغير‪.‬‬
‫ً‬
‫أيض ا في ال برامج الكب يرة ال تي ق د تحت اج خالله ا إلى‬
‫سهولة إع ادة إس ناد المتغ يرات مفي دة‬
‫تغيير القيم باستمرار‪.‬‬
‫ً‬
‫صحيحا‪ ،‬ثم نعيد إسناد سلسلة نصية إليه‪:‬‬
‫س ُنسند إلى المتغير ‪ x‬أواًل عد ًدا‬
‫تعيين ‪ x‬إلى قيمة عددية ‪#‬‬
‫‪x = 76‬‬
‫)‪print(x‬‬
‫إعادة تعيين ‪ x‬إلى سلسلة نصية ‪#‬‬
‫"‪x = "Sammy‬‬
‫)‪print(x‬‬
‫وسينتج لنا‪:‬‬
‫‪76‬‬
‫‪Sammy‬‬
‫يوضح المث ال أعاله أن ه يمكنن ا أواًل إس ناد قيم ة عددي ة إلى المتغ ير ‪ ،x‬ثم إع ادة إس ناد قيم ة‬
‫نصية إليه‪.‬‬
‫إذا أعدنا كتابة البرنامج بالشكل التالي‪:‬‬
‫‪94‬‬
‫|‬
‫▲‬
‫المتغيرات واستخداماتها‬
‫البرمجة بلغة بايثون‬
‫‪x = 76‬‬
‫"‪x = "Sammy‬‬
‫)‪print(x‬‬
‫ألن تلك القيمة هي األحدث‪:‬‬
‫لن نتلقى سوى القيمة المسندة الثانية في المخرجات‪َّ ،‬‬
‫‪Sammy‬‬
‫ق د تك ون إع ادة إس ناد القيم إلى المتغ يرات مفي دة في بعض الح االت‪ ،‬لكن علي ك أن تبقي‬
‫ً‬
‫واضحا قدر اإلمكان‪.‬‬
‫عينك على مقروئية الشيفرة‪ ،‬وأن تحرص على جعل البرنامج‬
‫‪ .4‬اإلسناد المتعدد (‪)Multiple Assignment‬‬
‫في ب ايثون‪ ،‬يمكن ك إس ناد قيم ة واح دة إلى ع دة متغ يرات في ال وقت نفس ه‪ .‬ي تيح ل ك ه ذا‬
‫ً‬
‫ً‬
‫الحق ا‪ ،‬أو من خالل‬
‫دة‪ ،‬وال تي يمكن ك إع ادة إس نادها‬
‫تهيئ ة ع َّدة متغ يرات دفع ًة واح‬
‫مدخالت المستخدم‪.‬‬
‫يمكن ك من خالل اإلس نادات المتع ددة إس ناد قيم ة واح دة إلى ع َّدة متغ يرات (مث ل المتغ ير‬
‫‪ x‬و‪ y‬و ‪ )z‬في سطر واحد‪:‬‬
‫‪x = y = z = 0‬‬
‫)‪print(x‬‬
‫)‪print(y‬‬
‫)‪print(z‬‬
‫الناتج سيكون‪:‬‬
‫‪0‬‬
‫‪0‬‬
‫‪0‬‬
‫‪95‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫عرفنا في هذا المثال ثالثة متغيرات (‪ x‬و ‪ y‬و ‪ ،)z‬وأسندنا إليها القيمة ‪.0‬‬
‫ً‬
‫أيضا بإسناد ع َّدة قيم لع َّدة متغيِّ رات ض من الس طر نفس ه‪ .‬ه ذه القيم يمكن‬
‫تسمح لك بايثون‬
‫أن تكون من أنواع بيانات مختلفة‪:‬‬
‫‪j, k, l = "shark", 2.05, 15‬‬
‫)‪print(j‬‬
‫)‪print(k‬‬
‫)‪print(l‬‬
‫وهذه هي المخرجات‪:‬‬
‫‪shark‬‬
‫‪2.05‬‬
‫‪15‬‬
‫في المث ال أعاله‪ُ ،‬أ س ن َدت السلس لة النص ية "‪ "shark‬إلى المتغ ير ‪ ،j‬والع دد العش ري ‪2.05‬‬
‫إلى المتغير ‪ ،k‬والعدد الصحيح ‪ 15‬إلى المتغير ‪.l‬‬
‫إس ناد ع دة متغ يرات بع دة قيم في س طر واح د يمكن أن يختص ر الش يفرة ويقل ل من ع دد‬
‫أن ذلك ليس على حساب المقروئية‪.‬‬
‫أسطرها‪ ،‬ولكن تأكد من َّ‬
‫‪ .5‬المتغيرات العامة والمحلية‬
‫عن د اس تخدام المتغ يرات داخ ل البرن امج‪ ،‬من المهم أن تض ع نط اق (‪ )scope‬المتغ ير في‬
‫حساباتك‪ .‬يشير نطاق المتغ ير إلى المواض ع ال تي يمكن الوص ول منه ا إلى المتغيِّ ر داخ ل الش يفرة‪،‬‬
‫َّ‬
‫ألنه ال يمكن الوص ول إلى جمي ع المتغ يرات من جمي ع أج زاء البرن امج‪ ،‬فبعض المتغ يرات عامة‬
‫دئيا‪ُ ،‬تع رَّ ف المتغ يرات العام ة خ ارج ال دوال؛ أمَّ ا المتغ يرات‬
‫(‪ ،)global‬وبعض ها محلي (‪ .)local‬مب ًّ‬
‫المحلية‪ ،‬فتعرَّ ف داخل الدوال‪.‬‬
‫‪96‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫المثال التالي يعطي فكرة عن المتغيرات العامة والمحلية‪:‬‬
‫إنشاء متغير عام‪ ،‬خارج الدالة ‪#‬‬
‫"‪glb_var = "global‬‬
‫‪def var_function():‬‬
‫إنشاء متغير محلي داخل دالة ‪#‬‬
‫"‪lcl_var = "local‬‬
‫)‪print(lcl_var‬‬
‫استدعاء دالة لطباعة المتغير المحلي ‪#‬‬
‫)(‪var_function‬‬
‫طباعة متغير عام خارج دالة ‪#‬‬
‫)‪print(glb_var‬‬
‫المخرجات الناتجة‪:‬‬
‫‪local‬‬
‫‪global‬‬
‫يُ س نِد البرن امج أعاله سلس لة نص ية إلى المتغ ير العم ومي ‪ glb_var‬خ ارج الدال ة‪ ،‬ثم يع ِّرف‬
‫وسي ِ‬
‫محليا باس م ‪ ،lcl_var‬ثم يطبع ه‬
‫نش ئ داخ ل تل ك الدال ة متغيِّ ًرا‬
‫الدال ة )(‪.var_function‬‬
‫ُ‬
‫ًّ‬
‫قيمته‪ .‬ينتهي البرنامج باستدعاء الدالة )(‪ ،var_function‬وطباعة قيمة المتغير ‪.glb_var‬‬
‫لمَّ ا ك ان ‪ glb_var‬متغ يرًا عامًّ ا‪ ،‬فيمكنن ا الوص ول إلي ه داخ ل الدال ة )(‪.var_function‬‬
‫المثال التالي يبيِّ ن ذلك‪:‬‬
‫"‪glb_var = "global‬‬
‫‪def var_function():‬‬
‫"‪lcl_var = "local‬‬
‫‪97‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫)‪print(lcl_var‬‬
‫طباعة ‪ glb_var‬داخل الدالة ‪print(glb_var) #‬‬
‫)(‪var_function‬‬
‫)‪print(glb_var‬‬
‫المخرجات‪:‬‬
‫‪local‬‬
‫‪global‬‬
‫‪global‬‬
‫لقد طبعنا المتغير العام ‪ glb_var‬مرتين‪ ،‬إذ ُطبع داخل الدالة وخارجها‪.‬‬
‫ماذا لو حاولنا استدعاء المتغير المحلي خارج الدالة؟‬
‫"‪glb_var = "global‬‬
‫‪def var_function():‬‬
‫"‪lcl_var = "local‬‬
‫)‪print(lcl_var‬‬
‫)‪print(lcl_var‬‬
‫ال يمكنن ا اس تخدام متغ ير محلي خ ارج الدال ة ال تي ُ‬
‫ص ِّرح عن ه فيه ا‪ .‬إذا حاولن ا القي ام ب ذلك‪،‬‬
‫فسيطلق الخطأ ‪.NameError‬‬
‫ُ‬
‫‪NameError: name 'lcl_var' is not defined‬‬
‫دعنا ننظر إلى مثال آخر‪ ،‬حيث سنستخدم االسم نفسه لمتغير عام وآخر محلي‪:‬‬
‫‪98‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المتغيرات واستخداماتها‬
‫متغير عام ‪num1 = 5 #‬‬
‫‪def my_function():‬‬
‫استخدام نفس اسم المتغير ‪num1 = 10 # num1‬‬
‫تعيين متغير محلي ‪#‬‬
‫‪num2 = 7‬‬
‫طباعة المتغير المحلي ‪print(num1) # num1‬‬
‫طباعة المتغير المحلي ‪print(num2) # num2‬‬
‫استدعاء )(‪# my_function‬‬
‫)(‪my_function‬‬
‫طباعة المتغير العام ‪# num1‬‬
‫)‪print(num1‬‬
‫الناتج‪:‬‬
‫‪10‬‬
‫‪7‬‬
‫‪5‬‬
‫ألن المتغ ير المحلي ‪ُ num1‬‬
‫أن ‪num1‬‬
‫ص ِّرح عن ه‬
‫محلي ا داخ ل إح دى ال دوال‪ ،‬فس نرى َّ‬
‫نظ ًرا َّ‬
‫ً‬
‫يس اوي القيم ة المحلي ة ‪ 10‬عن د اس تدعاء الدال ة‪ .‬عن دما نطب ع القيم ة العام ة للمتغ ير ‪ num1‬بع د‬
‫أن المتغير العام ‪ num1‬ال يزال مساويً ا للقيمة ‪.5‬‬
‫استدعاء الدالة )(‪ ،my_function‬سنرى َّ‬
‫من الممكن الوص ول إلى المتغ يرات العام ة واس تعمالها داخ ل دال ة باس تخدام الكلم ة‬
‫المفتاحية ‪:global‬‬
‫‪99‬‬
‫|‬
‫▲‬
‫المتغيرات واستخداماتها‬
‫البرمجة بلغة بايثون‬
‫‪def new_shark():‬‬
‫جعل المتغير عاما ‪#‬‬
‫‪global shark‬‬
‫"‪shark = "Sammy‬‬
‫استدعاء الدالة )(‪# new_shark‬‬
‫)(‪new_shark‬‬
‫طباعة المتغير العام ‪# shark‬‬
‫)‪print(shark‬‬
‫أن المتغ ير المحلي ‪ shark‬عُ يِّ ن داخ ل الدال ة )(‪ ،new_shark‬إال َّ‬
‫أنه يمكن الوص ول إلي ه‬
‫رغم َّ‬
‫من خارج الدالة بسبب الكلمة المفتاحية ‪ global‬المستخدمة قبل اسم المتغير داخل الدالة‪.‬‬
‫َ‬
‫أي خطأ عندما نستدعي )‪ print(shark‬خ ارج الدال ة‪.‬‬
‫بسبب استخدام ‪ ،global‬فلن يُ طلق ُّ‬
‫رغم َّ‬
‫أن ذل ك يُ ع ُّد من الع ادات غ ير المس تحبة في‬
‫أنه يمكن ك اس تعمال متغ ير ع ام داخ ل دال ة‪ ،‬إال َّ‬
‫البرمج ة‪َّ ،‬‬
‫ألنه ا ق د ت ؤثر على مقروئي ة الش يفرة ع دا عن الس ماح لج زء من الش يفرة بتع ديل قيم ة‬
‫متغير قد يستعمله جزء آخر‪.‬‬
‫هناك شيء آخر يجب تذكره‪ ،‬وهو َّ‬
‫أنك إذا أشرت إلى متغير داخل دال ة‪ ،‬دون إس ناد قيم ة ل ه‪،‬‬
‫محليا‪ ،‬يجب عليك إسناد قيمة له داخل متن الدالة‪.‬‬
‫متغير‬
‫ضمنيا‪ .‬لجعل‬
‫فسيعَ ّد هذا المتغير عامً ا‬
‫ُ‬
‫ًّ‬
‫ًّ‬
‫ٍ‬
‫عن د التعام ل م ع المتغ يرات‪ ،‬يك ون ل ك الخي ار بين اس تخدام المتغ يرات العام ة أو المحلي ة‪.‬‬
‫يُ َّ‬
‫فض ل في العادة استخدام المتغيرات المحلية‪ ،‬ولكن إن وجدت نفسك تس تخدم نفس المتغ ير في‬
‫عدة دوال‪ ،‬فقد ترغب في جعله عامً ا‪ .‬أمَّ ا إن كنت تحتاج المتغير داخل دالة أو ص نف واح د فق ط‪،‬‬
‫فقد يكون األولى استخدام متغير محلي‪.‬‬
‫‪100‬‬
‫|‬
‫▲‬
‫المتغيرات واستخداماتها‬
‫البرمجة بلغة بايثون‬
‫‪ .6‬خالصة الفصل‬
‫لق د مررن ا في ه ذا الفص ل على بعض ح االت االس تخدام الش ائعة للمتغ يرات في ب ايثون ‪.3‬‬
‫مثل حاض ً‬
‫المتغيرات هي لبنة مهمة في البرمجة‪ ،‬إذ ُت ِّ‬
‫نة لمختل ف أن واع البيان ات في ب ايثون وال تي‬
‫سنسلط عليها الضوء في الفصل التالي‪.‬‬
‫‪101‬‬
‫|‬
‫▲‬
‫‪6‬‬
‫أنواع البيانات‬
‫والتحويل بينها‬
‫‪102‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫ُت ِّ‬
‫صنف بايثون البيانات (‪ )data‬إلى أن واع‪ ،‬كم ا ه و الح ال في جمي ع لغ ات البرمج ة‪ .‬ه ذا مهم‬
‫ألن نوع البيانات الذي تستخدمه سيقيِّ د القيم التي يمكن تعيينها لها‪ ،‬وما الذي يمكن فعله بها (بم ا‬
‫َّ‬
‫في ذلك العمليات التي يمكن تنفيذها عليها)‪.‬‬
‫اء‬
‫لية لب ايثون‪ .‬ه ذا ليس استقص ً‬
‫س نتعرَّ ف في ه ذا الفص ل على أهم أن واع البيان ات األص َّ‬
‫شاماًل ألنواع البيانات‪ ،‬ولكنَّه سيساعدك على التعرف على الخيارات المتاحة لك في بايثون‪.‬‬
‫‪ .1‬خلفية عامة‬
‫أن واع البيان ات في ب ايثون مش ابهة إلى ح د م ا ألن واع البيان ات ال تي نس تخدمها في الع الم‬
‫الحقيقي‪ .‬من أمثلة أنواع البيانات في العالم الحقيقي األعداد‪ ،‬مث ل‪ :‬األع داد الص حيحة الطبيعي ة‬
‫(‪ ،)... ،2 ،1 ،0‬واألعداد الصحيحة النسبية (‪ ،)... ،1 ،0 ،1- ،...‬واألعداد غير النسبية (‪.)π‬‬
‫يمكننا عادة في الرياضيات جمع أعداد من أنواع مختلفة مثل إضافة ‪ 5‬إلى ‪:π‬‬
‫‪5 + π‬‬
‫يمكنن ا إمَّ ا االحتف اظ بالمعادل ة ِبع ِّدها إجاب ة‪ ،‬وس تكون النتيج ة ع د ًدا غ ير نس بي (‪irrational‬‬
‫‪ ،)number‬أو يمكنن ا تق ريب (‪ )round‬الع دد ‪ π‬إلى ع دد ذي من ازل عش رية مح ددة‪ ،‬ثم‬
‫نجمع العددين‪:‬‬
‫‪5 + π = 5 + 3.14 = 8.14‬‬
‫ولكن‪ ،‬إذا حاولن ا إض افة ع دد إلى ن وع بيان ات آخ ر‪ ،‬مث ل الكلم ات‪ ،‬فستص بح األم ور مربك ة‬
‫وغير ذات معنى‪ .‬فكيف ستحل المعادلة التالية مثاًل ؟‬
‫‪hsoub + 8‬‬
‫‪103‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫ً‬
‫مختلف ا تمامً ا‪ ،‬مث ل الكلم ات‬
‫بالنسبة إلى الكلمة ‪ ،hsoub‬يمكن ع ُّد كل نوع من أنواع البيان ات‬
‫وكيفية التعام ل معه ا‬
‫كيفية اس تخدامها‪،‬‬
‫يتعين علين ا ت وخي الح ذر بش أن‬
‫واألع داد‪ ،‬ل ذلك‬
‫َّ‬
‫َّ‬
‫َّ‬
‫في العمليات‪.‬‬
‫‪ .2‬األعداد‬
‫ً‬
‫فسر كل عدد ُتدخله إلى بايثون على َّ‬
‫راحة عن ن وع‬
‫أنه عدد؛ ليس مطلوبًا من ك اإلعالن ص‬
‫سي َّ‬
‫ُ‬
‫أي ع دد مكت وب ب دون فواص ل عش رية بمثاب ة ع دد ص حيح‬
‫البيانات الذي تدخل ه َّ‬
‫ألن ب ايثون َتع ُّد ّ‬
‫وأي ع دد مكت وب بفواص ل لعش رية بمثاب ة ع دد عش ري (‪ ،float‬كما‬
‫(‪ ،integer‬كما ه و ح ال ‪،)138‬‬
‫ُّ‬
‫هو حال ‪.)138.0‬‬
‫ا‪ .‬األعداد الصحيحة (‪)integer‬‬
‫كم ا ه و الح ال في الرياض يات‪ ،‬األع داد الص حيحة (‪ )integer‬في البرمج ة هي أع داد كامل ة‪،‬‬
‫ً‬
‫أيضا باسم ‪.int‬‬
‫يمكن أن تكون موجبة أو سالبة أو معدومة (‪ .)... ،1،0،1- ،...‬ويُ عرف هذا النوع‬
‫كما هو الحال مع لغات البرمجة األخرى‪ ،‬يجب أال تستخدم الفواصل في األع داد المؤلف ة من أربع ة‬
‫أرقام أو أكثر‪ ،‬لذلك ال تكتب ‪ 1,000‬في برنامجك‪ ،‬واكتب ‪.1000‬‬
‫يمكننا طباعة عدد صحيح على النحو التالي‪:‬‬
‫)‪print(-25‬‬
‫وسينتج‪:‬‬
‫‪-25‬‬
‫‪104‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫أو يمكننا اإلعالن عن متغير‪ ،‬والذي هو في هذه الحال ة رم ٌز للع دد ال ذي نس تخدمه أو نتعام ل‬
‫معه‪ ،‬مثال‪:‬‬
‫‪my_int = -25‬‬
‫)‪print(my_int‬‬
‫وسينتج لنا‪:‬‬
‫‪-25‬‬
‫ً‬
‫مباشرة مثل‪:‬‬
‫يمكننا أن نجري العمليات الحسابية على األعداد الصحيحة في بايثون‬
‫‪int_ans = 116 - 68‬‬
‫)‪print(int_ans‬‬
‫المخرجات‪:‬‬
‫‪48‬‬
‫يمكن استخدام األع داد الص حيحة بع دة طرائ ق في ب رامج ب ايثون‪ ،‬وم ع اس تمرارك في تعلم‬
‫المزي د عن ه ذه اللغ ة‪ ،‬س تتاح ل ك الكث ير من الف رص الس تخدام األع داد الص حيحة والتعام ل معه ا‬
‫وفهم المزيد عن هذا النوع من البيانات‪.‬‬
‫ب‪ .‬األعداد العشرية (‪)Floating-Point Numbers‬‬
‫األع داد العش رية هي أع داد حقيقي ة‪ ،‬مم ا يع ني أن ه يمكن أن تك ون أع دا ًدا جذري ة أو غ ير‬
‫نسبية‪ .‬لهذا الس بب‪ ،‬يمكن أن تحت وي األع داد العش رية على ج زء كس ري‪ ،‬مث ل ‪ 9.0‬أو ‪.-116.42‬‬
‫وببساطة‪ ،‬فاألعداد العشرية هي أعداد تحتوي الفاصلة العشرية‪.‬‬
‫كما فعلنا مع األعداد الصحيحة‪ ،‬يمكننا طباعة األعداد العشرية هكذا‪:‬‬
‫‪105‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫)‪print(17.3‬‬
‫وسينتج لنا‪:‬‬
‫‪17.3‬‬
‫ً‬
‫ِّ‬
‫متغير يحوى عد ًدا عشريًا‪ ،‬مثال‪:‬‬
‫أيضا أن نعلن عن‬
‫يمكننا‬
‫‪my_flt = 17.3‬‬
‫)‪print(my_flt‬‬
‫الناتج‪:‬‬
‫‪17.3‬‬
‫وكم ا ه و الح ال م ع األع داد الص حيحة‪ ،‬يمكنن ا أن نج رى العملي ات الحس ابية على‬
‫األعداد العشرية‪:‬‬
‫‪flt_ans = 564.0 + 365.24‬‬
‫)‪print(flt_ans‬‬
‫الناتج‪:‬‬
‫‪929.24‬‬
‫ألن ‪ 3‬عدد‬
‫أن ‪َّ ،3.0 ≠ 3‬‬
‫تختلف األعداد الصحيحة واألعداد العشرية عن بعضها عمومً ا‪ ،‬إذ َّ‬
‫صحيح‪ ،‬بينما ‪ 3.0‬عدد عشري‪.‬‬
‫‪ .3‬القيم المنطقية‬
‫هناك قيمتان فقط لنوع البيانات المنطقية (‪ ،)Boolean‬وهما ‪ True‬و ‪ُ .False‬تستخدم القيم‬
‫المنطقية لتمثيل قيم الحقيقة الموافقة للمنطق الرياضياتي (صح أو خطأ)‪.‬‬
‫‪106‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫ع ادة م ا يب دأ اس م البيان ات المنطقي ة ب الحرف ‪ ،B‬إش ارة إلى اس م ع الم الرياض يات ‪George‬‬
‫‪ .Boole‬القيمتان ‪ True‬و ‪ُ False‬تكتبان دائمً ا بحرفين كبيرين ‪ T‬و ‪َّ ،F‬‬
‫ألنها قيم خاصة في بايثون‪.‬‬
‫منطقيا‪ ،‬إما ‪ True‬أو ‪:False‬‬
‫الكثير من العمليات الحسابية في الرياضيات ُتنتج قيمً ا‬
‫ً‬
‫•‬
‫أكبر من‬
‫•‬
‫أصغر من‬
‫•‬
‫التساوي‬
‫‪bool_val = 500 > 100 # True‬‬
‫‪bool_val = 1 > 5‬‬
‫‪# False‬‬
‫‪bool_val = 200 < 400 # True‬‬
‫‪bool_val = 4 < 2‬‬
‫‪# False‬‬
‫‪bool_val = 5 = 5‬‬
‫‪# True‬‬
‫‪bool_val = 500 = 400 # False‬‬
‫كما هو الحال مع األعداد‪ ،‬يمكننا تخزين القيم المنطقية في المتغيرات‪:‬‬
‫‪my_bool = 5 > 8‬‬
‫يمكننا بعد ذلك طباعة القيمة المنطقية باستدعاء الدالة )(‪:print‬‬
‫)‪print(my_bool‬‬
‫أن العدد ‪ 5‬ليس أكبر من ‪ ،8‬فسوف نحصل على المخرجات التالية‪:‬‬
‫بما َّ‬
‫‪False‬‬
‫‪107‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫َّ‬
‫المنطقية‪ ،‬وكي ف يمكن لل دوال والعملي ات‬
‫كيفية اس تخدام القيم‬
‫تتعلم م ع م رور ال وقت‬
‫س‬
‫َّ‬
‫َّ‬
‫المنطقية أن تغيِّ ر مسار البرنامج‪.‬‬
‫َّ‬
‫‪ .4‬السالسل النصية‬
‫السلسلة النص ية (‪ )string‬هي عب ارة عن تسلس ل من مح رف واح د أو أك ثر (مح ارف وأع داد‬
‫ورم وز)‪ ،‬ويمكن أن تك ون ثابت ة أو متغ يرة‪ .‬تح اط السالس ل النص ية إم ا بعالم ات االقتب اس‬
‫المفردة ' أو عالمات االقتباس المزدوجة "‪ ،‬ل ذلك إلنش اء سلس لة نص ية‪ ،‬ض ع سلس لة من األح رف‬
‫بين عالمتي اقتباس‪:‬‬
‫'‪'This is a string in single quotes.‬‬
‫"‪"This is a string in double quotes.‬‬
‫يمكنك استخدام عالمات االقتب اس المف ردة أو عالم ات االقتب اس المزدوج ة‪ ،‬المهم أن تك ون‬
‫ً‬
‫متسقا في برنامجك‪.‬‬
‫البرن امج البس يط "!‪ "Hello, World‬يوض ح كي ف يمكن اس تخدام السالس ل النص ية في‬
‫أن حروف عبارة !‪ Hello, World‬تمثل سلسلة نصية‪.‬‬
‫البرمجة‪ ،‬إذ َّ‬
‫)"!‪print("Hello, World‬‬
‫كما هو الحال مع أنواع البيانات األخرى‪ ،‬يمكننا تخزين السالسل النصية في المتغيرات‪:‬‬
‫"!‪hw = "Hello, World‬‬
‫وطباعة السلسلة عن طريق استدعاء المتغيِّ ر‪:‬‬
‫!‪# Hello, World‬‬
‫)‪print(hw‬‬
‫‪108‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫مث ل األع داد‪ ،‬هن اك العدي د من العملي ات ال تي يمكن إجراؤه ا على السالس ل النص ية من أج ل‬
‫تحقي ق النت ائج ال تي نس عى إليه ا‪ .‬السالس ل النص ية مهم ة لتوص يل المعلوم ات إلى المس تخدم‪،‬‬
‫وكذلك لتمكين المستخدم من تمرير المعلومات إلى البرنامج‪.‬‬
‫‪ .5‬القوائم (‪)Lists‬‬
‫القائمة (‪ )list‬عب ارة عن تسلس ل م َّ‬
‫رتب قاب ل للتغي ير ( ‪ .)mutable‬وكم ا ُتع رَّ ف السالس ل‬
‫النصية باستخدام عالمات االقتباس‪ ،‬يتم تعريف القوائم باستخدام األقواس المعقوفة []‪.‬‬
‫َّ‬
‫ً‬
‫صحيحة‪:‬‬
‫مثاًل ‪ ،‬هذه قائمة تحوي أعدا ًدا‬
‫]‪[-3, -2, -1, 0, 1, 2, 3‬‬
‫وهذه قائمة من األعداد العشرية‪:‬‬
‫]‪[3.14, 9.23, 111.11, 312.12, 1.05‬‬
‫وهذه قائمة من السالسل النصية‪:‬‬
‫]'‪['shark', 'cuttlefish', 'squid', 'mantis shrimp‬‬
‫ِّ‬
‫سنسمي قائمة السالسل النصية خاصتنا باالسم ‪:sea_creatures‬‬
‫في المثال التالي‪،‬‬
‫‪sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis‬‬
‫]'‪shrimp‬‬
‫يمكننا طباعتها عن طريق استدعاء المتغير‪:‬‬
‫)‪print(sea_creatures‬‬
‫أن المخرجات تشبه تمامً ا القائمة التي أنشأناها‪:‬‬
‫وسترى َّ‬
‫]'‪['shark', 'cuttlefish', 'squid', 'mantis shrimp‬‬
‫‪109‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫الق وائم هي ن وع بيان ات م رن للغاي ة‪ ،‬ألنه ا قابل ة للتغي ير‪ ،‬حيث يمكن إض افة قيم إليه ا‪ ،‬أو‬
‫بي د َّ‬
‫أنه غ ير قاب ل للتغي ير‪ ،‬ويُ س مى‬
‫إزالت ه‪ ،‬أو تغييره ا‪ .‬هن اك ن وع بيان ات آخ ر مش ابه لق وائم‪ْ ،‬‬
‫الصف (‪.)tuple‬‬
‫‪ .6‬الصفوف (‪)Tuples‬‬
‫يُ ستخدم الصف (‪ )tuple‬لتجميع البيانات‪ ،‬وهو تسلسل ثابت من العناصر وغير قابل للتغيير‪.‬‬
‫الصفوف تشبه القوائم إلى حد كبير‪ ،‬لكنها تس تخدم األق واس () ب داًل من األق واس المعقوف ة []‪،‬‬
‫َّ‬
‫وألنها غير قابلة للتغيير‪ ،‬فال يمكن تغيير أو تعديل قيمها‪.‬‬
‫تبدو الصفوف كالتالي‪:‬‬
‫)'‪('blue coral', 'staghorn coral', 'pillar coral‬‬
‫يمكننا تخزين الصفوف في المتغيِّ رات وطباعتها‪:‬‬
‫)'‪coral = ('blue coral', 'staghorn coral', 'pillar coral‬‬
‫)‪print(coral‬‬
‫والمخرجات هي‪:‬‬
‫)'‪('blue coral', 'staghorn coral', 'pillar coral‬‬
‫كما هو الحال في أنواع البيان ات األخ رى‪ ،‬تطب ع ب ايثون الص فوف تمامً ا كم ا كتبناه ا‪ ،‬إذ تطب ع‬
‫سلسلة من القيم بين قوسين‪.‬‬
‫‪110‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫‪ .7‬القواميس (‪)Dictionaries‬‬
‫اتيح ب القيم المقابل ة له ا في‬
‫ُ‬
‫القاموس (‪ )dictionary‬هو ن وع مُ ض مّ ن في ب ايثون‪ ،‬إذ ُترب ط مف‬
‫ش كل أزواج‪ ،‬ه ذه األزواج مفي دة لتخ زين البيان ات في ب ايثون‪ .‬يتم إنش اء الق واميس باس تخدام‬
‫األقواس المعقوصة {}‪.‬‬
‫ُتس تخدم الق واميس ع ً‬
‫ادة لحف ظ البيان ات المترابط ة‪ ،‬مث ل المعلوم ات المقابل ة ل رقم تعري ف‪.‬‬
‫يبدو القاموس كما يلي‪:‬‬
‫‪{'name': 'Sammy', 'animal': 'shark', 'color': 'blue',‬‬
‫}'‪'location': 'ocean‬‬
‫س تالحظ أن ه باإلض افة إلى األق واس المعقوص ة‪ ،‬توج د عالم ات النقط تين الرأس يتين‬
‫(‪ )colons‬داخ ل الق اموس‪ .‬الكلم ات الموج ودة على يس ار النقط تين الرأس يتين هي المف اتيح‪.‬‬
‫أي نوع بيانات غير قابل للتغيير‪ .‬المفاتيح في القاموس أعاله هي‪:‬‬
‫المفاتيح قد تكون َّ‬
‫'‪'name', 'animal', 'color', 'location‬‬
‫الكلم ات الموج ودة على يمين النقط تين هي القيم‪ .‬يمكن أن تت ألف القيم من أي ن وع من‬
‫البيانات‪ .‬القيم في القاموس أعاله هي‪:‬‬
‫'‪'Sammy', 'shark', 'blue', 'ocean‬‬
‫مثل أنواع البيانات األخرى‪ ،‬يمكننا تخزين القواميس في متغيرات‪ ،‬وطباعتها‪:‬‬
‫‪sammy = {'name': 'Sammy', 'animal': 'shark', 'color': 'blue',‬‬
‫}'‪'location': 'ocean‬‬
‫)‪print(sammy‬‬
‫‪111‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫والمخرجات هي‪:‬‬
‫‪{'color': 'blue', 'animal': 'shark', 'name': 'Sammy',‬‬
‫}'‪'location': 'ocean‬‬
‫إذا أردت الحص ول على الل ون (‪ )color‬الخ اص بـ ‪ ،Sammy‬فيمكن ك القي ام ب ذلك عن طري ق‬
‫استدعاء ]'‪ .sammy ['color‬هذا مثال على ذلك‪:‬‬
‫‪print(sammy['color']) # blue‬‬
‫القواميس من أنواع البيانات المهمَّ ة في برامج بايثون‪.‬‬
‫‪ .8‬التحويل بين أنواع البيانات‬
‫ِّ‬
‫يحدد نوع البيانات ‪-‬كما ذكرنا‪ -‬القيم ال تي يمكن اس تعمالها‪ ،‬والعملي ات ال تي يمكن ك إجراؤه ا‬
‫وع إلى آخ ر ألج ل معالجته ا بطريق ة مختلف ة‪.‬‬
‫عليه ا‪ .‬هن اك أوق ات نحت اج إلى تحوي ل القيم من ن ٍ‬
‫على سبيل المثال‪ ،‬قد نحتاج إلى ضم (‪ )concatenate‬القيم العددية إلى سالسل نصية‪.‬‬
‫سيرشدك هذا القسم إلى كيفية التحويل بين األعداد والسالسل النصية والص فوف والق وائم‪،‬‬
‫باإلضافة إلى تقديم بعض األمثلة التوضيحية‪.‬‬
‫ا‪ .‬تحويل األنواع العددية‬
‫هن اك نوع ان من البيان ات العددي ة في ب ايثون كم ا رأين ا ً‬
‫آنف ا‪ :‬األع داد الص حيحة واألع داد‬
‫العش رية‪ .‬س تعمل في بعض األحي ان على ش يفرة برمجي ة كتبه ا ش خص آخ ر‪ ،‬وق د تحت اج إلى‬
‫تحوي ل ع دد ص حيح إلى ع دد عش ري‪ ،‬أو العكس‪ ،‬أو ق د تج د َّ‬
‫ً‬
‫حيحا في‬
‫أنك تس تخدم ع د ًدا ص‬
‫ال وقت ال ذي تحت اج إلى أع داد عش رية‪ .‬يت وفر في ب ايثون تواب ع مض مّ نة ُتس ِّهل علي ك تحوي ل‬
‫األعداد الصحيحة إلى أعداد عشريَّ ة‪ ،‬أو العكس‪.‬‬
‫‪112‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫تحويل األعداد الصحيحة إلى أعداد عشرية‬
‫يح وّ ل الت ابع )(‪ float‬األع داد الص حيحة إلى أع داد عش رية‪ .‬الس تخدام ه ذه الدال ة‪ ،‬ض ع‬
‫ً‬
‫صحيحا بين القوسين‪:‬‬
‫عد ًدا‬
‫)‪float(57‬‬
‫في هذه الحالة‪ ،‬سيحوَّ ل العدد الصحيح ‪ 57‬إلى العدد العشري ‪.57.0‬‬
‫ً‬
‫أيض ا اس تخدام ه ذه الدال ة م ع المتغ يرات‪ .‬ل ُنس نِد القيم ة ‪ 57‬إلى المتغيِّ ر ‪ ،f‬ثم نطب ع‬
‫يمكن ك‬
‫العدد العشري الجديد‪:‬‬
‫‪f = 57‬‬
‫))‪print(float(f‬‬
‫الناتج سيكون‪:‬‬
‫‪57.0‬‬
‫يمكننا باستخدام الدالة )(‪ float‬تحويل األعداد الصحيحة إلى أعداد عشرية‪.‬‬
‫تحويل األعداد العشرية إلى أعداد صحيحة‬
‫تملك بايثون دالة أخرى مضمَّ نة لتحويل األعداد عشرية إلى أعداد صحيحة‪ :‬وهي )(‪.int‬‬
‫تعمل الدالة )(‪ int‬بشكل مشابه للدالة )(‪ :float‬يمكنك إضافة عدد عشري داخل القوسين‬
‫لتحويله إلى عدد صحيح‪:‬‬
‫)‪int(390.8‬‬
‫سيحوَّ ل العدد العشري ‪ 390.8‬إلى العدد الصحيح ‪.390‬‬
‫في هذه الحالة‪ُ ،‬‬
‫‪113‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫ً‬
‫وأن ‪c‬‬
‫أن ‪ b‬يس اوي ‪،125.0‬‬
‫يمكن ك‬
‫َّ‬
‫أيض ا اس تخدام ه ذه الدال ة م ع المتغ يرات‪ .‬لنص ِّرح َّ‬
‫يساوي ‪ ،390.8‬ثم نطبع العددين العشريين الجديدين‪:‬‬
‫‪b = 125.0‬‬
‫‪c = 390.8‬‬
‫))‪print(int(b‬‬
‫))‪print(int(c‬‬
‫والمخرجات ستكون‪:‬‬
‫‪125‬‬
‫‪390‬‬
‫عن د تحوي ل األع داد العش رية إلى أع داد ص حيحة بواس طة الدال ة )(‪ ،int‬تقتط ع ب ايثون‬
‫األجزاء العشرية من العدد ُ‬
‫وتبقي القيمة الص حيحة؛ ل ذلك‪ ،‬لن ُتح ِّول الدال ة )(‪ int‬الع دد ‪390.8‬‬
‫إلى ‪.391‬‬
‫تحويل األعداد عبر القسمة‬
‫في بايثون ‪ ،3‬عند تقسيم ع دد ص حيح على آخ ر‪ ،‬س ينتج ع دد عش ري على خالف ب ايثون ‪.2‬‬
‫بمع نى َّ‬
‫أنه عن د قس مة ‪ 5‬على ‪ 2‬في ب ايثون ‪ ،3‬ستحص ل على ع دد عش ري (مث ل ‪ 2.5‬عن د‬
‫قسمة ‪ 5‬على ‪:)2‬‬
‫‪114‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫‪a = 5 / 2‬‬
‫)‪print(a‬‬
‫وسينتج لنا‪:‬‬
‫‪2.5‬‬
‫بينما في بايثون ‪ ،2‬ستحصل على ناتج صحيح‪ ،‬أي ‪ .2 = 5/2‬يمكن ك الحص ول على ع دد‬
‫صحيح ناتج عن عملية القسمة باستعمال المعامل ‪ //‬الجديد في بايثون ‪:3‬‬
‫‪a = 5 // 2‬‬
‫)‪print(a‬‬
‫وسينتج لنا‪:‬‬
‫‪2‬‬
‫ارج ع إلى فص ل «إص دارات ب ايثون‪ :‬ب ايثون ‪ 2‬مقاب ل ب ايثون ‪ »3‬لالطالع على المزي د من‬
‫الفروقات بين بايثون ‪ 2‬وبايثون ‪.3‬‬
‫ب‪ .‬التحويل مع السالسل النصية‬
‫السالسل النصية عبارة عن سلسلة مؤلفة من محرف واحد أو أك ثر (المح رف يمكن أن يك ون‬
‫ً‬
‫حرف ا‪ ،‬أو ع د ًدا‪ ،‬أو رم ًزا)‪ .‬السالس ل النص ية هي إح دى األش كال الش ائعة من البيان ات في ع الم‬
‫البرمجة‪ ،‬وقد نحتاج إلى تحويل السالسل النصية إلى أعداد أو أعداد إلى سالسل نص ية في كث ير‬
‫ً‬
‫خاصة عندما نعمل على البيانات التي ينشئها المستخدمون‪.‬‬
‫من األحيان‪،‬‬
‫‪115‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫تحويل األعداد إلى سالسل نصية‬
‫يمكنن ا تحوي ل األع داد إلى سالس ل نص ية ع بر الت ابع )(‪ .str‬يمكنن ا أن نم ِّرر إمَّ ا ع د ًدا أو‬
‫متغيرًا بين قوسي التابع‪ ،‬وبعد ذلك ُ‬
‫ستحوَّ ل تلك القيمة العددية إلى قيمة نصية‪.‬‬
‫دعنا ننظر أواًل في تحويل األعداد الصحيحة‪ .‬لتحويل العدد الصحيح ‪ 12‬إلى سلسلة نص ية‪،‬‬
‫يمكنك تمرير ‪ 12‬إلى التابع )(‪:str‬‬
‫)‪str(12‬‬
‫عند تنفيذ )‪ str(12‬في سطر أوام ر ب ايثون التف اعلي م ع األم ر ‪ python‬في ناف ذة الطرفي ة‪،‬‬
‫ستحصل على المخرجات التالية‪:‬‬
‫'‪'12‬‬
‫ً‬
‫حيحا‪ ،‬ولكنَّه أص بح اآلن‬
‫تشير عالمات االقتباس المحيطة بالعدد ‪ 12‬إلى أنه لم يع د ع د ًدا ص‬
‫سلسلة نصية‪.‬‬
‫سيص بح باس تخدام المتغ يرات تحوي ل األع داد الص حيحة إلى سالس ل نص ية أك ثر فائ دة‪.‬‬
‫لنف ترض َّ‬
‫يوميا مث ل أن ن دخل ع دد أس طر‬
‫أنن ا نري د متابع ة تق ُّدم مس تخدم في مج ال البرمج ة‬
‫ًّ‬
‫الشيفرة البرمجية التي كتبها‪ .‬نود أن نعرض ذلك على المستخدم‪ ،‬وذلك بطباع ة السالس ل النص ية‬
‫واألعداد في الوقت نفسه‪:‬‬
‫"‪user = "Sammy‬‬
‫‪lines = 50‬‬
‫‪print("Congratulations, " + user + "! You just wrote " + lines‬‬
‫)"‪+ " lines of code.‬‬
‫‪116‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫سي َ‬
‫طلق الخطأ التالي‪:‬‬
‫عند تنفيذ الشيفرة أعاله‪ُ ،‬‬
‫‪TypeError: Can't convert 'int' object to str implicitly‬‬
‫يتع ذر علين ا ض مُّ (‪ )concatenate‬األع داد إلى السالس ل النص ية في ب ايثون‪ ،‬ل ذلك يجب‬
‫تحويل المتغير ‪ lines‬إلى سلسلة نصية‪:‬‬
‫"‪user = "Sammy‬‬
‫‪lines = 50‬‬
‫‪print("Congratulations, " + user + "! You just wrote " +‬‬
‫)"‪str(lines) + " lines of code.‬‬
‫اآلن‪ ،‬عن دما ُن ِّ‬
‫البرمجية‪ ،‬سنحص ل على المخرج ات التالي ة‪ ،‬وفيه ا تهنئ ة‬
‫نفذ الش يفرة‬
‫َّ‬
‫للمستخدم على تق ُّدمه‪:‬‬
‫‪Congratulations, Sammy! You just wrote 50 lines of code.‬‬
‫إذا أردن ا تحوي ل ع دد عش ري إلى سلس لة نص ية ب داًل من تحوي ل ع دد ص حيح إلى سلس لة‬
‫نصية‪ ،‬فعلينا تتبع نفس الخطوات والص ياغة الس ابقة‪ .‬عن دما نم ِّرر ع د ًدا عش ريً ا إلى الت ابع )(‪،str‬‬
‫ُ‬
‫ستعاد سلسلة نصية‪ .‬يمكننا استخدام قيمة العدد العشري نفسها‪ ،‬أو يمكننا استخدام متغيِّ ر‪:‬‬
‫))‪print(str(421.034‬‬
‫‪f = 5524.53‬‬
‫))‪print(str(f‬‬
‫وسينتج لنا‪:‬‬
‫‪421.034‬‬
‫‪5524.53‬‬
‫‪117‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫يمكننا اختبار صحة التحويل عن طريق ضم الناتج إلى سلسلة نصية‪:‬‬
‫‪f = 5524.53‬‬
‫)"‪print("Sammy has " + str(f) + " points.‬‬
‫وهذا هو الناتج‪:‬‬
‫‪Sammy has 5524.53 points.‬‬
‫ألن عملي ة الض م ق د‬
‫أن ع ددنا العش ري ق د ُ‬
‫ح ِّول بنج اح إلى سلس لة نص ية‪َّ ،‬‬
‫اآلن تأك دنا من َّ‬
‫ُن ِّفذت دون خطأ‪.‬‬
‫تحويل السالسل النصية إلى أعداد‬
‫يمكن تحوي ل السالس ل النص ية إلى أع داد باس تخدام الت ابعين )(‪ float‬و )(‪ .int‬إذا لم‬
‫يكن في السلس لة النص ية من ازل عش رية‪ ،‬فاألفض ل أن تحوله ا إلى ع دد ص حيح باس تخدام‬
‫التابع )(‪.int‬‬
‫دعنا نستخدم مثال تتبع عدد أس طر الش يفرة ال ذي أوردن اه أعاله‪ .‬ق د ت رغب في التعام ل م ع‬
‫ولكن ه ذه القيم‬
‫ه ذه القيم باس تخدام الحس ابات الرياض ياتية لتق ديم نت ائج أدق للمس تخدم‪،‬‬
‫َّ‬
‫َّ‬
‫حاليا في سالسل نصية‪:‬‬
‫مخزنة‬
‫ًّ‬
‫"‪lines_yesterday = "50‬‬
‫"‪lines_today = "108‬‬
‫‪lines_more = lines_today - lines_yesterday‬‬
‫)‪print(lines_more‬‬
‫‪118‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫الناتج هو‪:‬‬
‫'‪TypeError: unsupported operand type(s) for -: 'str' and 'str‬‬
‫ًأ‬
‫َّ‬
‫أن معام ل‬
‫ألن القيمتين العدديتين‬
‫مخزنتان في سالسل نصية‪ ،‬تلقين ا خط ‪ .‬س بب ذل ك َّ‬
‫نظرًا َّ‬
‫الطرح ‪ -‬ال يصلح للسالسل النصية‪.‬‬
‫دعن ا نع ِّدل الش يفرة لتض مين الت ابع )(‪ int‬ال ذي س يحول السالس ل النص ية إلى أع داد‬
‫ص حيحة‪ ،‬ويس مح لن ا بالقي ام بالعملي ات الرياض ياتية على القيم ال تي ك انت سالس ل نص ية‬
‫في األصل‪.‬‬
‫"‪lines_yesterday = "50‬‬
‫"‪lines_today = "108‬‬
‫)‪lines_more = int(lines_today) - int(lines_yesterday‬‬
‫)‪print(lines_more‬‬
‫وهذه هي المخرجات‪:‬‬
‫‪58‬‬
‫تلقائيا‪ ،‬ويساوي القيمة العددية ‪ 58‬في هذا المثال‪.‬‬
‫المتغير ‪ line_more‬هو عدد صحيح‬
‫ًّ‬
‫أيضا تحويل األعداد في المثال أعاله إلى قيم عشرية باستخدام التابع )(‪ float‬بداًل‬
‫ً‬
‫يمكننا‬
‫من الت ابع )(‪ .int‬وب دالً من الحص ول على الن اتج ‪ ،58‬سنحص ل على الن اتج ‪ ،58.0‬وه و‬
‫عدد عشري‪.‬‬
‫‪119‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫ً‬
‫نقاطا على شكل قيم عشرية‪:‬‬
‫سيكسب المستخدم ‪Sammy‬‬
‫"‪total_points = "5524.53‬‬
‫"‪new_points = "45.30‬‬
‫‪new_total_points = total_points + new_points‬‬
‫)‪print(new_total_points‬‬
‫الناتج‪:‬‬
‫‪5524.5345.30‬‬
‫ً‬
‫الحة‪ ،‬لكن ه سيض م‬
‫في هذه الحالة‪ ،‬يع ُّد استخدام المعامل ‪ +‬م ع سلس لتين نص يتين عملي ًة ص‬
‫النص يتين ب داًل من جم ع القيم تين الع دديتين؛ ل ذلك‪ ،‬س يبدو الن اتج غ ير م ألوف‪َّ ،‬‬
‫ألنه‬
‫ّ‬
‫السلس لتين‬
‫ً‬
‫بعضا‪.‬‬
‫نتيجة لصق القيمتين إلى جانب بعضهما‬
‫سنحتاج إلى تحويل هذه السالسل النص ية إلى أع داد عش رية قب ل إج راء أي عملي ات عليه ا‪،‬‬
‫وذلك باستخدام التابع )(‪:float‬‬
‫"‪total_points = "5524.53‬‬
‫"‪new_points = "45.30‬‬
‫)‪new_total_points = float(total_points) + float(new_points‬‬
‫)‪print(new_total_points‬‬
‫وسينتج عن ذلك‪:‬‬
‫‪5569.83‬‬
‫‪120‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫اآلن‪ ،‬وبع د أن حوَّ لن ا السلس لتين النص يتين إلى ع ددين عش ريين‪ ،‬سنحص ل على النتيج ة‬
‫المتوقعة‪ ،‬والتي هي جمع ‪ 45.30‬و ‪.5524.53‬‬
‫إذا حاولنا تحويل سلسلة نصية ذات منازل عشرية إلى عدد صحيح‪ ،‬فسنحصل على خطأ‪:‬‬
‫"‪f = "54.23‬‬
‫))‪print(int(f‬‬
‫المخرجات‪:‬‬
‫'‪ValueError: invalid literal for int() with base 10: '54.23‬‬
‫إذا مرّ رنا عد ًدا عشريً ا موضوعً ا في سلسلة نص ية إلى الت ابع )(‪ ،int‬فسنحص ل على خط أ‪ ،‬إذ‬
‫لن ُتحوَّ ل إلى عدد صحيح‪.‬‬
‫ي تيح لن ا تحوي ل السالس ل النص ية إلى أع داد تع ديل ن وع البيان ات ال ذي نعم ل علي ه بس رعة‬
‫حتى نتمكن من إجراء عمليات على قيم عددية مكتوبة على شكل سالسل نصية‪.‬‬
‫ج‪ .‬التحويل إلى صفوف وقوائم‬
‫يمكن ك اس تخدام الت ابعين )(‪ list‬و )(‪ tuple‬لتحوي ل القيم المُ م رَّ رة إليهم ا إلى قائمة أو‬
‫صف على التوالي‪ .‬في بايثون‪:‬‬
‫•‬
‫القائم ة هي تسلس ل م َّ‬
‫رتب قاب ل للتغي ير من العناص ر الموض وعة داخ ل قوس ين‬
‫معقوفين []‪.‬‬
‫•‬
‫الص ف عب ارة عن تسلس ل م رتب ث ابت (غ ير قاب ل للتغي ير) من العناص ر الموض وعة بين‬
‫الهالليين ()‪.‬‬
‫القوسين‬
‫َّ‬
‫‪121‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫التحويل إلى صفوف‬
‫ِّ‬
‫يحس ن تحوي ل قائم ة إلى ص ف أداء‬
‫نظ ًرا لك ون الص فوف غ ير قابل ة للتغي ير‪ ،‬فيمكن أن‬
‫ال برامج تحس ينًا كب يرًا‪ .‬عن دما نس تخدم الت ابع )(‪ ،tuple‬فس وف يُ عي د القيم ة المُ م رَّ رة إلي ه على‬
‫هيئة صف‪.‬‬
‫‪print(tuple(['pull request', 'open source', 'repository',‬‬
‫))]'‪'branch‬‬
‫المخرجات‪:‬‬
‫)'‪('pull request', 'open source', 'repository', 'branch‬‬
‫أن العناص ر موض وعة اآلن بين قوس ين‪ ،‬ب داًل من‬
‫أن الص ف ق د ُطب ع في المخرج ات‪ ،‬إذ َّ‬
‫ن رى َّ‬
‫القوسين المربعين‪.‬‬
‫دعنا نستخدم )(‪ tuple‬مع متغير يحتوي قائمة‪:‬‬
‫‪sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis‬‬
‫]'‪shrimp‬‬
‫))‪print(tuple(sea_creatures‬‬
‫سينتج‪:‬‬
‫)'‪('shark', 'cuttlefish', 'squid', 'mantis shrimp‬‬
‫ح ِّولت إلى ص ف‪ ،‬كم ا يش ير إلى ذل ك القوس ان‪ .‬يمكنن ا تحوي ل أي‬
‫أن القائم ة ُ‬
‫مرة أخرى‪ ،‬ن رى َّ‬
‫نوع قابل للتكرار (‪ )iterable‬إلى صف‪ ،‬بما في ذلك السالسل النصية‪:‬‬
‫))'‪print(tuple('Sammy‬‬
‫‪122‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫المخرجات‪:‬‬
‫)'‪('S', 'a', 'm', 'm', 'y‬‬
‫لمَّ ا ك ان باإلمك ان الم رور (‪ )iterate‬على مح ارف السالس ل النص ية‪ ،‬فيمكنن ا تحويله ا إلى‬
‫صفوف باستخدام التابع )(‪ .tuple‬أمَّ ا أنواع البيانات غير القابلة للتك رار‪ ،‬مث ل األع داد الص حيحة‬
‫ُ‬
‫فستطلِق عملية تحويلها خطًأ‪:‬‬
‫واألعداد العشرية‪،‬‬
‫))‪print(tuple(5000‬‬
‫والناتج سيكون‪:‬‬
‫‪TypeError: 'int' object is not iterable‬‬
‫في حين أن ه من الممكن تحوي ل ع دد ص حيح إلى سلس لة نص َّية‪ ،‬ومن ثم تحوي ل السلس لة‬
‫النص ية إلى ص ف‪ ،‬كم ا في ))‪ ،tuple(str(5000‬فمن األفض ل تجنب مث ل ه ذه التعليم ات‬
‫َّ‬
‫المعقدة‪.‬‬
‫البرمجية‬
‫التحويل إلى قوائم‬
‫يمكن أن يك ون تحوي ل القيم‪ ،‬وخاص ة الص فوف‪ ،‬إلى ق وائم مفي ًدا عن دما تحت اج إلى نس خة‬
‫قابلة للتغيير من تلك القيم‪.‬‬
‫ألن ص ياغة الق وائم‬
‫سنس تخدم الت ابع )(‪ list‬لتحوي ل الص ف الت الي إلى قائم ة‪ .‬ونظ رً ا َّ‬
‫تس تخدم األق واس‪ ،‬تأك د من تض مين أق واس الت ابع )(‪ ،list‬وك ذلك األق واس الخاص ة‬
‫بالدالة )(‪:print‬‬
‫)))'‪print(list(('blue coral', 'staghorn coral', 'pillar coral‬‬
‫‪123‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫أنواع البيانات والتحويل بينها‬
‫المخرجات هي‪:‬‬
‫]'‪['blue coral', 'staghorn coral', 'pillar coral‬‬
‫ُأ‬
‫تش ير األق واس المعقوف ة [] إلى َّ‬
‫أنه ق د رجعَ ت قائم ة من الص ف األص لي ال ذي مُ ِّرر ع بر‬
‫الدالة )(‪.list‬‬
‫لجعل الشيفرة سهلة القراءة‪ ،‬يمكننا إزالة أحد أزواج األقواس باستخدام متغيِّ ر‪:‬‬
‫)'‪coral = ('blue coral', 'staghorn coral', 'pillar coral‬‬
‫)‪list(coral‬‬
‫إن طبعنا )‪ ،list(coral‬فسنتلقى المخرجات نفسها الموجودة أعاله‪.‬‬
‫تمامً ا مثل الصفوف‪ ،‬يمكن تحويل السالسل النصية إلى قوائم‪:‬‬
‫))'‪print(list('shark‬‬
‫الناتج‪:‬‬
‫]'‪['s', 'h', 'a', 'r', 'k‬‬
‫ِّ‬
‫يوفر لنا نسخة قابلة للتغيير من القيمة األصلية‪.‬‬
‫ُح ِّو َلت هنا السلسلة ‪ shark‬إلى قائمة‪ ،‬وهذا‬
‫‪ .9‬خالصة الفصل‬
‫في هذه المرحلة‪ ،‬يُ ف ترض أن يك ون ل ديك فهم جي د لبعض أن واع البيان ات الرئيس ية المتاح ة‬
‫طبيعيا من حياتك كمبرمج للغة بايثون‪.‬‬
‫جزءا‬
‫ً‬
‫في بايثون‪ .‬أنواع البيانات هذه ستصبح‬
‫ً‬
‫ً‬
‫كيفية تحويل العديد من أنواع البيانات األص لية المهمَّ ة إلى‬
‫أيضا في هذا الفصل‬
‫لقد وضحنا‬
‫َّ‬
‫أنواع بيانات أخرى‪ ،‬وذلك باستخدام التوابع المُ ضمّ نة‪ .‬يوفر تحويل أنواع البيان ات في ب ايثون ل ك‬
‫‪124‬‬
‫|‬
‫▲‬
‫أنواع البيانات والتحويل بينها‬
‫البرمجة بلغة بايثون‬
‫ً‬
‫ً‬
‫إضافية في مشاريعك البرمجية‪ .‬يمكنك التعرف على المزيد من التفاص يل عن ه ذه األن واع‬
‫مرونة‬
‫وطرائق التحويل بينها في موسوعة حسوب‪.‬‬
‫‪125‬‬
‫|‬
‫▲‬
‫‪7‬‬
‫السالسل النصية‬
‫والتعامل معها‬
‫‪126‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫«السلسلة النصية» (‪ )string‬هي مجموعة من المحارف (أي األحرف واألرقام والرم وز) ال تي‬
‫إمَّ ا أن تك ون قيم ة ثابت ة أو قيم ة لمتغ ير‪ .‬وه ذه السالس ل النص ية مُ ش َّكلة من مح ارف يونيك ود‬
‫وألن النص ه و ش ٌ‬
‫كل ش ائعٌ من أش كال البيان ات ال ذي‬
‫(‪ )Unicode‬وال تي ال يمكن تغي ير م دلولها‪.‬‬
‫َّ‬
‫ً‬
‫مثل ُل ً‬
‫وت ِّ‬
‫فإن السالسل النصية مهمة ج ًدا ُ‬
‫أساسية في البرمج ة‪ .‬سيس تعرض‬
‫بنة‬
‫يوميا‪ ،‬لذا‬
‫نستعمله‬
‫َّ‬
‫ً‬
‫كيفية إنش اء وطباع ة السالس ة النص ية‪ ،‬وكيفي ة جمعه ا م ع بعض ها وتكراره ا‪ ،‬وآلي ة‬
‫ه ذا الفص ل‬
‫َّ‬
‫تخزين السالسل النصية في متغيرات‪.‬‬
‫‪ .1‬إنشاء وطباعة السالسل النصية‬
‫تتواجد السالسل النصية إمَّ ا داخل عالمات اقتباس فردية ' أو عالمات اقتباس مزدوجة "‪،‬‬
‫ل ذا إلنش اء سلس لة نص ية‪ ،‬ك ل م ا علين ا فعل ه ه و وض ع مجموع ة من المح ارف بين أح د ن وعَ ي‬
‫َ‬
‫السابقين‪:‬‬
‫عالمات االقتباس‬
‫'‪.‬هذه سلسلة نصية ضمن عالمتي اقتباس مفردتين'‬
‫"هذه سلسلة نصية ضمن عالمتي اقتباس مزدوجتين"‬
‫يمكن ك االختي ار بين الن وعَ ين الس َ‬
‫ابقين‪ ،‬لكن أيًّ ا ك ان اختي ارك‪ ،‬فعلي ك أن تحاف ظ على‬
‫استخدامك له في كام ل برنامج ك‪ .‬يمكن ك طباع ة السالس ل النص ية إلى الشاش ة باس تدعاء الدال ة‬
‫)(‪ print‬بكل بساطة‪:‬‬
‫)"‪print("Let's print out this string.‬‬
‫‪Let's print out this string.‬‬
‫فهمت كيفي ة تهيئ ة السالس ل النص ية في ب ايثون‪ ،‬لنل ق نظ ً‬
‫َ‬
‫كيفية التعام ل‬
‫رة اآلن إلى‬
‫بعد أن‬
‫َّ‬
‫ِ‬
‫مع السالسل النصية في برامجك وتعديلها‪.‬‬
‫‪127‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫‪ .2‬آلية فهرسة السالسل النصية‬
‫إن ك ل مح رف في السلس لة‬
‫وكما في نوع البيانات ‪ list‬ال ذي في ه عناص ر مرتبط ة بأرق ام‪ ،‬ف َّ‬
‫دءا من الفه رس ‪ .0‬فللسلس لة النص ية !‪ Sammy Shark‬س تكون‬
‫معين‪ ،‬ب ً‬
‫النص ية يرتب ط بفه رس‬
‫ّ‬
‫الفهارس والمحارف المرتبطة بها كاآلتي‪:‬‬
‫!‬
‫‪k‬‬
‫‪r‬‬
‫‪a‬‬
‫‪h‬‬
‫‪s‬‬
‫‪11‬‬
‫‪10‬‬
‫‪9‬‬
‫‪8‬‬
‫‪7‬‬
‫‪6‬‬
‫‪5‬‬
‫‪y‬‬
‫‪m‬‬
‫‪m‬‬
‫‪a‬‬
‫‪s‬‬
‫‪4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫وكم ا الحظت‪ ،‬س يرتبط المح رف ‪ S‬ب الفهرس ‪ ،0‬وس تنتهي السلس لة النص ية ب الفهرس ‪ 11‬م ع‬
‫ً‬
‫رس خ ٌ‬
‫اص ب ه‪ ،‬وفي مثالن ا‬
‫الرم ز !‪ .‬الح ظ‬
‫أن الف راغ بين كلمتَي ‪ Sammy‬و ‪ Shark‬ل ه فه ٌ‬
‫أيض ا َّ‬
‫ً‬
‫رس خ ٌ‬
‫أيض ا‪ ،‬وأيَّ ة رم وز أو عالم ات ت رقيم‬
‫اص به ا‬
‫سيكون له الفهرس ‪ .5‬عالم ة التعجب ! له ا فه ٌ‬
‫أن المح ارف في ب ايثون له ا فه رس‬
‫أخرى مثل *‪ ?;.&$#‬سترتبط‬
‫ٍ‬
‫بفهرس مخص ص له ا‪ .‬حقيق ة َّ‬
‫أن بإمكاننا الوصول إلى السالسل النص ية وتع ديلها كم ا نفع ل م ع أن واع البيان ات‬
‫خاص بها ستعني َّ‬
‫المتسلسلة األخرى‪.‬‬
‫ا‪ .‬الوصول إلى المحارف بفهارس موجبة‬
‫يمكنن ا الحص ول على مح رف من سلس لة نص ية باإلش ارة إلي ه ع بر فهرس ه‪ .‬يمكنن ا فع ل ذل ك‬
‫لة نص ً‬
‫عرف في المث ال اآلتي سلس ً‬
‫بوض ع رقم الفه رس بين قوس ين معق وفين []‪ .‬س ُن ِّ‬
‫ية ونطب ع‬
‫المحرف المرتبط بالفهرس المذكور بين قوسين‪:‬‬
‫"!‪ss = "Sammy Shark‬‬
‫)]‪print(ss[4‬‬
‫‪128‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫الناتج‪:‬‬
‫‪y‬‬
‫معي ٍن في سلس لةٍ نص يةٍ ‪ ،‬فس ُتعيد ب ايثون المح رف الموج ود في ذاك‬
‫رس‬
‫عندما ُنشير إلى فه ٍ‬
‫ّ‬
‫الموض‬
‫ع‪ ،‬ولمَّ ا ك‬
‫ان المح‬
‫رف ‪ y‬موج‬
‫و ًدا في الفه‬
‫رس الراب‬
‫ع في السلس‬
‫ية‬
‫لة النص‬
‫"!‪ "Sammy Shark‬فعندما طبعنا ]‪ ss[4‬فظهر الحرف ‪.y‬‬
‫معين ة ض من‬
‫خالص ة م ا س بق‪ ،‬أرق ام الفه ارس ستس مح لن ا بالوص ول إلى مح ارف‬
‫ّ‬
‫سلسلة نصية‪.‬‬
‫ب‪ .‬الوصول إلى المحارف بفهارس سالبة‬
‫إذا ك انت ل ديك سلس ٌ‬
‫ً‬
‫انطالق ا من نهايته ا‪ ،‬فعندئ ذٍ‬
‫لة طويل ٌة وأردن ا تحدي د أح د محارفه ا لكن‬
‫دءا من الفه رس ‪ .-1‬ل و أردن ا أن نس تخدم الفه ارس‬
‫نستطيع اس تخدام األرق ام الس البة للفه ارس‪ ،‬ب ً‬
‫السالبة مع السلسلة النصية !‪ ،Sammy Shark‬فستبدو كما يلي‪:‬‬
‫!‬
‫‪k‬‬
‫‪r‬‬
‫‪a‬‬
‫‪h‬‬
‫‪s‬‬
‫‪-1‬‬
‫‪-2‬‬
‫‪-3‬‬
‫‪-4‬‬
‫‪-5‬‬
‫‪-6‬‬
‫‪-7‬‬
‫‪y‬‬
‫‪m‬‬
‫‪m‬‬
‫‪a‬‬
‫‪s‬‬
‫‪-8‬‬
‫‪-9‬‬
‫‪-10‬‬
‫‪-11‬‬
‫‪-12‬‬
‫يمكنن ا أن نطب ع المح رف ‪ r‬في السلس لة الس ابقة في ح ال اس تخدمنا الفه ارس الس البة‬
‫باإلشارة إلى المحرف الموجود في الفهرس ‪ -3‬كما يلي‪:‬‬
‫)]‪print(ss[-3‬‬
‫وج دنا َّ‬
‫أنه يمكنن ا االس تفادة من الفه ارس الس البة ل و أردن ا الوص ول إلى مح رف في آخ ر‬
‫سلسلة نصية طويلة‪.‬‬
‫‪129‬‬
‫|‬
‫▲‬
‫السالسل النصية والتعامل معها‬
‫البرمجة بلغة بايثون‬
‫‪ .3‬تقسيم السالسل النصية‬
‫يمكنن ا أن نحص ل على مج ال من المح ارف من سلس لة نص ية‪ ،‬فلنق ل مثاًل أنن ا نري د أن نطب ع‬
‫الكلمة ‪ Shark‬فقط‪ ،‬يمكننا فعل ذلك بإنشائنا «لقس م» من السلس لة النص ية‪ ،‬وال ذي ه و سلس ٌ‬
‫لة من‬
‫المحارف الموجودة ضمن السلسلة األصلية‪ .‬فاألقسام تسمح لن ا بالوص ول إلى ع ِّدة مح ارف دفع ًة‬
‫واحدة باستعمال مجال من أرقام الفهارس مفصولة فيما بينها بنقطتين رأسيتين [‪:]x:y‬‬
‫)]‪print(ss[6:11‬‬
‫الناتج‪:‬‬
‫‪Shark‬‬
‫عن د إنش ائنا لقس م مث ل [‪ ]6:11‬فس ُي ِّ‬
‫مثل أوَّ ل رقم مك ان ب دء القس م (متض منًا المح رف‬
‫الموج ود عن د ذاك الفه رس)‪ ،‬وال رقم الث اني ه و مك ان نهاي ة القس م (دون تض مين ذاك المح رف)‪،‬‬
‫وهذا هو السبب وراء استخدمنا لرقم فهرس يقع بعد نهاي ة القس م ال ذي نري د اقتطاع ه في المث ال‬
‫لة نص ً‬
‫نش ئ « سلس ً‬
‫ية فرعي ًة» (‪ )substring‬عن دما ُن ِّ‬
‫الس ابق‪ .‬نحن ُن ِ‬
‫قس م السالس ل النص ية‪ ،‬وال تي‬
‫هي سلس ٌ‬
‫ٌ‬
‫ودة ض من سلس لةٍ أخ رى‪ .‬وعن دما نس تخدم التعب ير ]‪ ss[6:11‬فنحن نس تدعي‬
‫لة موج‬
‫السلس لة النص ية ‪ Shark‬ال تي تتواج د ض من السلس لة النص ية !‪ .Sammy Shark‬إذا أردن ا تض مين‬
‫نهاي ة السلس لة (أو ب دايتها) في القس م ال ذي ُ‬
‫ست ِ‬
‫نش ئه‪ ،‬فيمكن أاّل نض ع أح د أرق ام الفه ارس في‬
‫]‪ .string[n:n‬فمثاًل ‪ ،‬نس تطيع أن نطب ع أوَّ ل كلم ة من السلس لة ‪ – ss‬أي ‪ – Sammy‬بكتاب ة‬
‫ما يلي‪:‬‬
‫)]‪print(ss[:5‬‬
‫‪130‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫فعلنا ذلك بحذف رقم الفه رس قب ل النقط تين الرأس يتين‪ ،‬ووض عنا رقم فه رس النهاي ة فق ط‪،‬‬
‫الفرعية‪ .‬لطباع ة منتص ف السلس لة النص ية‬
‫ال ذي يُ ش ير إلى مك ان إيق اف اقتط اع السلس لة النص ية‬
‫َّ‬
‫إلى آخرها‪ ،‬فسنضع فهرس البداية فقط قبل النقطتين الرأسيتين‪ ،‬كما يلي‪:‬‬
‫)]‪print(ss[7:‬‬
‫الناتج‪:‬‬
‫!‪hark‬‬
‫إن‬
‫بكتاب ة فه رس البداي ة فق ط قب ل النقط تين الرأس يتين وت رك تحدي د الفه رس الث اني‪ ،‬ف َّ‬
‫ً‬
‫أيض ا اس تخدام‬
‫السلسلة الفرعية ستبدأ من الفهرس األول إلى نهاية السلسلة النص ية كله ا‪ .‬يمكن ك‬
‫ً‬
‫سابقا‪ ،‬تبدأ أرقام الفهارس السلبية من الرقم‬
‫الفهارس السالبة في تقسيم سلسلة نصية‪ ،‬فكما ذكرنا‬
‫‪ ،-1‬ويستمر العد إلى أن نصل إلى بداية السلسلة النصية‪ .‬وعند استخدام الفه ارس الس البة فس نبدأ‬
‫من الرقم األصغر َّ‬
‫ألنه يقع أواًل في السلسلة‪ .‬لنستخدم فهرس ين ذوي رقمين س البين القتط اع ج زء‬
‫من السلسلة النصية ‪:ss‬‬
‫)]‪print(ss[-4:-1‬‬
‫الناتج‪:‬‬
‫‪ark‬‬
‫ألن الحرف ‪ a‬يق ع‬
‫السلسلة النصية "‪ "ark‬مأخوذة من السلسلة النصية "!‪َّ "Sammy Shark‬‬
‫ً‬
‫مباشرة‪.‬‬
‫في الموضع ‪ -4‬والحرف ‪ k‬يقع قبل الفهرس ‪-1‬‬
‫يمكن تحدي د الخط وة عن د تقس يم السالس ل النص ية وذل ك بتمري ر معام ل ث الث إض ً‬
‫افة إلى‬
‫فهرس ي البداي ة والنهاي ة‪ ،‬وه و الخط وة‪ ،‬ال تي ُتش ير إلى ع دد المح ارف ال تي يجب تجاوزه ا بع د‬
‫َ‬
‫‪131‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫أن قيمت ه‬
‫الحص ول على المح رف من السلس لة النص ية‪ .‬لم ُنح ِّدد إلى اآلن الخط وة في أمثلتن ا‪ ،‬إال َّ‬
‫االفتراضية هي ‪ ،1‬لذا سنحص ل على ك ل مح رف يق ع بين الفهرس ين‪ .‬لننظ ر م ً‬
‫رة أخ رى إلى المث ال‬
‫السابق الذي يطبع السلسلة النصية الفرعية "‪:"Shark‬‬
‫‪# Shark‬‬
‫)]‪print(ss[6:11‬‬
‫سنحصل على نفس النتائج بتضمين معامل ثالث هو الخطوة وقيمته ‪:1‬‬
‫‪# Shark‬‬
‫)]‪print(ss[6:11:1‬‬
‫ً‬
‫أن ب ايثون ُ‬
‫ستض ِّمن جمي ع المح ارف بين فهرس ين‪ ،‬وإذا‬
‫إذا‪ ،‬إذا ك انت الخط وة ‪ 1‬فه ذا يع ني َّ‬
‫ً‬
‫َ‬
‫أن بعض‬
‫ذفت الخط وة فس تع ُّدها ب ايثون مس‬
‫ح‬
‫اوية للواح د‪ .‬أم ا ل و زدن ا الخط وة‪ ،‬فس نرى َّ‬
‫المحارف ستهمل‪:‬‬
‫‪# SmySak‬‬
‫)]‪print(ss[0:12:2‬‬
‫ألق‬
‫تحديد الخطوة بقيمة ‪ 2‬كما في ]‪ ss[0:12:2‬سيؤدي إلى تجاوز حرف بين كل حرفين‪ِ ،‬‬
‫ً‬
‫نظرة على المحارف المكتوبة بخط عريض‪:‬‬
‫!‪Sammy Shark‬‬
‫ُأ‬
‫ً‬
‫أيض ا عن دما ك انت الخط وة ‪ .2‬إذا وض عنا‬
‫أن الف راغ الموج ود في الفه رس ‪ 5‬ق د همِ ل‬
‫الح ظ َّ‬
‫ً‬
‫قيمة أكبر للخطوة‪ ،‬فسنحصل على سلسلةٍ نصيةٍ فرعيةٍ أصغر بكثير‪:‬‬
‫‪# Sya‬‬
‫)]‪print(ss[0:12:4‬‬
‫حذف الفهرسين وترك النقط تين الرأس يتين س يؤدي إلى إبق اء كام ل السلس لة ض من المج ال‪،‬‬
‫ً‬
‫سي ِّ‬
‫إضافة إلى ذل ك‪،‬‬
‫حدد عدد المحارف التي سيتم تخطيها‪.‬‬
‫لكن إضافة معامل ثالث وهو الخطوة ُ‬
‫ِّ‬
‫ترتيب معك وس إذا‬
‫يمكن ك من كتاب ة السلس لة النص ية ب‬
‫يمكن ك تحدي د رقم س الب كخط وة‪ ،‬مم ا‬
‫ٍ‬
‫‪132‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫َ‬
‫استعملت القيمة ‪:-1‬‬
‫)]‪print(ss[::-1‬‬
‫الناتج‪:‬‬
‫‪!krahS ymmaS‬‬
‫ً‬
‫ِّ‬
‫مرة أخرى لكن إذا كانت الخطوة ‪:-2‬‬
‫لنجرب ذلك‬
‫)]‪print(ss[::-2‬‬
‫الناتج‪:‬‬
‫‪!rh ma‬‬
‫في المث ال الس ابق (]‪ ،)ss[::-2‬س نتعامل م ع كام ل السلس لة النص ية لع دم وج ود أرق ام‬
‫لفهارس البداية والنهاية‪ ،‬وسيتم قلب اتجاه السلسلة النصية الستخدامنا لخطوةٍ س البة‪ .‬باإلض افة‬
‫بترتيب معكوس‪:‬‬
‫أن الخطوة ‪ -2‬ستؤدي إلى تخطي حرف بين كل حرفين‬
‫إلى َّ‬
‫ٍ‬
‫‪!krahS[whitespace]ymmaS‬‬
‫طبع الفراغ في المثال السابق‪.‬‬
‫ُ‬
‫سي َ‬
‫أن تحدي د المعام ل الث الث عن د تقس يم السالس ل النص ية س يؤدي إلى تحدي د‬
‫م ا رأين اه ه و َّ‬
‫الخط وة ال تي ُت ِّ‬
‫مثل ع دد المح ارف ال تي س يتم تخطيه ا عن د الحص ول على السلس لة الفرعي ة من‬
‫السلسلة األصلية‪.‬‬
‫‪133‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫‪ .4‬جمع السالسل النصية‬
‫ً‬
‫بعض ا إلنش اء‬
‫عملي ة الجم ع (‪ )concatenation‬تع ني إض افة سلس لتين نص يتين إلى بعض هما‬
‫أن العام ل ‪+‬‬
‫سلس لة نص ية جدي دة‪ .‬نس تخدم المعام ل ‪ +‬لجم ع السالس ل النص ية؛ أب ِق في ذهن ك َّ‬
‫يع ني عملي ة الجم ع عن د التعام ل م ع األع داد‪ ،‬أم ا عن دما نس تخدمه م ع السالس ل النص ية فيع ني‬
‫إض افتها إلى بعض ها‪ .‬لنجم ع السلس تين النص يتين "‪ "Sammy‬و "‪ "Shark‬م ع بعض ها ثم نطبعهم ا‬
‫باستخدام الدالة )(‪:print‬‬
‫)"‪print("Sammy" + "Shark‬‬
‫‪# SammyShark‬‬
‫َ‬
‫أردت وض ع ف راغ بين السلس لتين النص يتين‪ ،‬فيمكن ك بك ل بس اطة وض عه عن د نهاي ة‬
‫إذا‬
‫السلسلة النصية األولى‪ ،‬أي بعد الكلمة "‪:"Sammy‬‬
‫)"‪print("Sammy " + "Shark‬‬
‫‪# Sammy Shark‬‬
‫َ‬
‫مختلفين من البيان ات‪ ،‬فلن نتمكن من‬
‫لكن اح رص على ع دم اس تعمال العام ل ‪ +‬بين ن وعَ ين‬
‫جمع السالسل النصية واألرقام مع بعضها‪ ،‬فلو حاولنا مثاًل أن نكتب‪:‬‬
‫)‪print("Sammy" + 27‬‬
‫فسنحصل على رسالة الخطأ اآلتية‪:‬‬
‫‪TypeError: Can't convert 'int' object to str implicitly‬‬
‫أمَّ ا إذا أردن ا أن ُن ِ‬
‫نش ئ السلس لة النص ية "‪ "Sammy27‬فعلين ا حينه ا وض ع ال رقم ‪ 27‬بين‬
‫لة نص ً‬
‫عالم َتي اقتباس ("‪ )"27‬مما يجعل ه سلس ً‬
‫ً‬
‫حيحا‪ .‬سنس تفيد من تحوي ل‬
‫ية وليس ت ع د ًدا ص‬
‫األعداد إلى سالسل نصية عندما نتعامل مع أرق ام الهوات ف على س بيل المث ال‪َّ ،‬‬
‫ألنن ا لن نحت اج إلى‬
‫‪134‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫إجراء عملية حسابية على رمز الدولة ورمز المنطق ة في أرق ام الهوات ف‪ ،‬إال َّ‬
‫أنن ا نري دهما أن يظه را‬
‫لة نص ً‬
‫نش ئ سلس ً‬
‫ية جدي ً‬
‫متتابعَ ين‪ .‬عندما نجمع سلسلتين نص يتين أو أك ثر فنحن ُن ِ‬
‫دة ال تي يمكنن ا‬
‫استخدامها في برنامجنا‪.‬‬
‫‪ .5‬تكرار السالسل النصية‬
‫هنال ك أوق ٌ‬
‫ات نحت اج فيه ا إلى اس تخدام ب ايثون ألتمت ة المه ام‪ ،‬وإح دى األم ور ال تي يمكنن ا‬
‫أتمتتها هي تكرار سلسلة نصية ِّ‬
‫لعدة مرات‪ .‬إذ نستطيع فعل ذلك عبر العامل *‪ ،‬وكم ا ه و األم ر م ع‬
‫فإن العام ل * ل ه اس تخدامٌ مختل ف عن دما نتعام ل م ع أرق ام‪ ،‬حيث يُ ِّ‬
‫مثل عملي ة الض رب‪.‬‬
‫العامل ‪+‬‬
‫َّ‬
‫فإن العامل * هو معامل التكرار‪ ،‬فوظيفت ه هي تك رار‬
‫ورقم‬
‫أمَّ ا عندما نستخدمه بين سلسلةٍ نصيةٍ‬
‫ٍ‬
‫َّ‬
‫سلس لة نص ية ألي ع دد م رات تش اء‪ .‬لنح اول طباع ة السلس لة النص ية "‪ "Sammy‬تس ع م رات دون‬
‫تكرارها يدويً ا‪ ،‬وذلك عبر العامل *‪:‬‬
‫)‪print("Sammy" * 9‬‬
‫المخرجات‪:‬‬
‫‪SammySammySammySammySammySammySammySammySammy‬‬
‫ألي عددٍ نشاء من المرات‪.‬‬
‫يمكننا بهذه الطريقة تكرار السلسلة النصية ِّ‬
‫‪ .6‬تخزين السالسل النصية في متغيرات‬
‫أن المتغيِّ رات هي «رموز» يمكننا استعمالها لتخزين البيان ات في‬
‫وجدنا من فصل المتغيِّ رات َّ‬
‫ٌ‬
‫ٌ‬
‫برن امج‪ .‬أي يمكن ك تخي ل المتغيِّ رات على َّ‬
‫ارغ يمكن ك مل ؤه بالبيان ات أو القيم‪.‬‬
‫ندوق ف‬
‫أنه ا ص‬
‫ٌ‬
‫نوع من أنواع البيان ات‪ ،‬ل ذا يمكنن ا اس تعمالها لملء المتغ يرات‪ .‬التص ريح عن‬
‫السالسل النصية هي‬
‫‪135‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫سيس ِّهل علين ا التعام ل معه ا في برامجن ا‪ .‬لتخ زين سلس لة نص ية‬
‫متغ يرات تح وي سالس ل نص ية ُ‬
‫داخل متغير‪ ،‬فكل ما علينا فعله هو إسنادها إليه‪ .‬س ُن ِّ‬
‫صرح في المثال اآلتي عن المتغير ‪:my_str‬‬
‫"‪my_str = "Sammy likes declaring strings.‬‬
‫أص بح المتغ ير ‪ my_str‬اآلن مُ ش يرًا إلى سلس لةٍ نص يةٍ ‪ ،‬وال تي أمس ى بمق دورنا طباعته ا‬
‫كما يلي‪:‬‬
‫)‪print(my_str‬‬
‫وسنحصل على الناتج اآلتي‪:‬‬
‫‪Sammy likes declaring strings.‬‬
‫استخدام المتغيرات الحتواء قيم السالسل النصية سيساعدنا في االستغناء عن إعادة كتابة‬
‫السلسلة النصية في كل مرة نحتاج استخدامها‪ ،‬مما يُ ِّ‬
‫بس ط تعاملن ا معه ا وإجراءن ا للعملي ات عليه ا‬
‫في برامجنا‪.‬‬
‫‪ .7‬دوال السالسل النصية‬
‫ل دى ب ايثون ع َّدة دوال مبني ة فيه ا للتعام ل م ع السالس ل النص ية‪ .‬تس مح ه ذه ال دوال لن ا‬
‫بتع ديل وإج راء عملي ات على السالس ل النص ية بس هولة‪ .‬يمكن ك أن تتخي ل ال دوال على َّ‬
‫أنه ا‬
‫«أفع ال» يمكنن ا تنفي ذها على عناص ر موج ودة في الش يفرة‪ .‬ال دوال المبني ة في اللغ ة هي ال دوال‬
‫المُ عرَّ ف ة داخ ل لغ ة ب ايثون وهي ج اهزة مباش ً‬
‫رة لالس تخدام‪ .‬سنش رح في ه ذا القس م مختل ف‬
‫الدوال التي نستطيع استخدامها للتعامل مع السالسل النصية في بايثون ‪.3‬‬
‫‪136‬‬
‫|‬
‫▲‬
‫السالسل النصية والتعامل معها‬
‫البرمجة بلغة بايثون‬
‫ا‪ .‬جعل السالسل النصية بأحرف كبيرة أو صغيرة‬
‫الدالتان )(‪ str.upper‬و )(‪ُ str.lower‬‬
‫ستعيدان السلسلة النصية بعد تحويل حال ة جمي ع‬
‫لية إلى األح رف الكب يرة أو الص غيرة (على الت والي وب الترتيب)‪ .‬ولع دم ق درتنا على‬
‫أحرفه ا األص َّ‬
‫لة نص ٌ‬
‫تع ديل السلس لة النص ية بع د إنش ائها‪ ،‬فس ُتعاد سلس ٌ‬
‫ية جدي ٌ‬
‫دة‪ .‬لن ُتع َّدل أيَّ ة مح ارف غ ير‬
‫التينية في السلسلة النصية األصلية وستبقى على حالها‪ .‬لنح ِّول السلس لة النص ية ‪Sammy Shark‬‬
‫أحرف كبيرةٍ‪:‬‬
‫ٍ‬
‫إلى‬
‫"‪ss = "Sammy Shark‬‬
‫))(‪print(ss.upper‬‬
‫الناتج‪:‬‬
‫‪SAMMY SHARK‬‬
‫ِّ‬
‫أحرف صغيرة‪:‬‬
‫ٍ‬
‫لنحولها اآلن إلى‬
‫))(‪print(ss.lower‬‬
‫وسينتج‪:‬‬
‫‪sammy shark‬‬
‫ُّ‬
‫ُ‬
‫التحقق من مس اواة سلس لتين‬
‫ستس ِّهل ال دالتان )(‪ str.upper‬و )(‪ str.lower‬عملي ة‬
‫نصيتين لبعضهما أو لموازنتهما وذلك عبر توحيد حالة األحرف‪ .‬فلو كتب المستخدم اسمه ب أحرف‬
‫صغيرة فسنستطيع أن نتأكد إن كان مُ َّ‬
‫سجاًل في قاعدة البيانات بموازنته بعد تحويل حالة أحرفه‪.‬‬
‫ب‪ .‬الدوال المنطقية‬
‫عدة دوال تتحقق من القيم المنطقية (‪ .)Boolean‬هذه الدوال مفي ٌ‬
‫تتوفر في بايثون ِّ‬
‫دة عن د‬
‫‪137‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫إنشائنا للنماذج التي يجب على المستخدمين مألها؛ فمثاًل ‪ ،‬إذا س ألنا المس تخدم عن الرم ز البري دي‬
‫وأردن ا أن نقب ل السالس ل النص ية ال تي تحت وي أرقامً ا فق ط‪ ،‬أو عن دما نس أله عن اس مه فس نقبل‬
‫ً‬
‫ً‬
‫ً‬
‫ً‬
‫منطقية‪:‬‬
‫حروفا فقط‪ .‬هنالك عد ٌد من الدوال التي ُتعيد قيمً ا‬
‫نصية تحوي‬
‫سلسلة‬
‫•‬
‫َّ‬
‫تتحقق إذا احت وت السلس لة النص ية على أرق ام وأح رف فق ط (دون‬
‫)(‪:str.isalnum‬‬
‫•‬
‫َّ‬
‫تتحقق إذا احت وت السلس لة النص ية على أح رف فق ط (دون أرق ام‬
‫)(‪:str.isalpha‬‬
‫َّ‬
‫تحقق ذلك‪.‬‬
‫رموز)‪ ،‬أي تعيد ‪ true‬إن‬
‫أو رموز)‪.‬‬
‫•‬
‫َّ‬
‫تتحقق إذا كانت جميع أحرف السلسلة النصية صغيرة‪.‬‬
‫)(‪:str.islower‬‬
‫•‬
‫َّ‬
‫تتحقق إذا احتوت السلسلة النصية على أرقام فقط‪.‬‬
‫)(‪:str.isnumeric‬‬
‫•‬
‫َّ‬
‫تتحقق إذا لم تحتوي السلسلة النصية إال على الفراغات‪.‬‬
‫)(‪:str.isspace‬‬
‫•‬
‫َّ‬
‫تتحقق إذا ك انت حال ة أح رف السلس لة النص ية كم ا ل و َّ‬
‫أنه ا عن وان‬
‫)(‪:str.istitle‬‬
‫أن أوّ ل حرف من كل كلمة كبير‪ ،‬والبقية صغيرة)‪.‬‬
‫باللغة اإلنجليزية (أي َّ‬
‫•‬
‫َّ‬
‫تتحقق إذا كانت جميع أحرف السلسلة النصية كبيرة‪.‬‬
‫)(‪:str.isupper‬‬
‫عمليا‪:‬‬
‫لنجرب استعمال بعضها‬
‫ً‬
‫"‪number = "5‬‬
‫"‪letters = "abcdef‬‬
‫))(‪print(number.isnumeric‬‬
‫))(‪print(letters.isnumeric‬‬
‫الناتج‪:‬‬
‫‪138‬‬
‫|‬
‫▲‬
‫السالسل النصية والتعامل معها‬
‫البرمجة بلغة بايثون‬
‫‪True‬‬
‫‪False‬‬
‫اس تخدام الدال ة )(‪ str.isnumeric‬على السلس لة النص ية ‪ 5‬س ُيعيد القيم ة ‪ ،True‬بينم ا‬
‫وبشكل مماث ل‪ ،‬يمكنن ا معرف ة‬
‫سيعيد ‪.False‬‬
‫استخدام نفس الدالة على السلسلة النصية ‪ُ abcdef‬‬
‫ٍ‬
‫إن كانت حالة األحرف في سلسلةٍ نصيةٍ كما ل و َّ‬
‫أنه ا عن وان‪ ،‬أو أنه ا كب يرة أو ص غيرة (ه ذه العملي ة‬
‫ً‬
‫تنطبق على اللغات المكتوبة باألحرف الالتينية)‪ .‬ل ُن ِ‬
‫بداية بعض السالسل النصية‪:‬‬
‫نشئ‬
‫"‪movie = "2001: A SAMMY ODYSSEY‬‬
‫"‪book = "A Thousand Splendid Sharks‬‬
‫"‪poem = "sammy lived in a pretty how town‬‬
‫ِّ‬
‫المنطقية لمعرفة الناتج (سنعرض كل دالتين وناتجهما تحتهما)‪:‬‬
‫لنجرب الدوال‬
‫َّ‬
‫))(‪print(movie.islower‬‬
‫))(‪print(movie.isupper‬‬
‫‪# False‬‬
‫‪# True‬‬
‫))(‪print(book.istitle‬‬
‫))(‪print(book.isupper‬‬
‫‪# True‬‬
‫‪# False‬‬
‫))(‪print(poem.istitle‬‬
‫))(‪print(poem.islower‬‬
‫‪# False‬‬
‫‪# True‬‬
‫‪139‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫ستساعدنا معرفة إن كانت أحرف السلسلة النصية بحالة صغيرة أو كبيرة أو َّ‬
‫كأنها عنوان في‬
‫نيفا س ليمً ا‪ ،‬وت ِّ‬
‫تص نيف البيان ات تص ً‬
‫وفر لن ا الفرص ة لتوحي د طريق ة تخ زين البيان ات ب التحقق من‬
‫ٌ‬
‫ً‬
‫ً‬
‫أيضا‬
‫مفيدة‬
‫وفقا لذلك‪ .‬الدوال المنطقية التي تعمل على السالسل النصية‬
‫حالة أحرفها ثم تعديلها‬
‫ً‬
‫التحقق إن َّ‬
‫ُّ‬
‫معينة‪.‬‬
‫شروطا‬
‫حق َقت مدخالت المستخدم‬
‫عندما نريد‬
‫َّ‬
‫ج‪ .‬الدوال )(‪ join‬و )(‪ split‬و )(‪replace‬‬
‫ِّ‬
‫ً‬
‫افية لتع ديل‬
‫إمكانيات إض‬
‫ٍ‬
‫توفر الدوال )(‪ str.join‬و )(‪ str.split‬و )(‪str.replace‬‬
‫السالس ل النص ية في ب ايثون‪ .‬الدال ة )(‪ str.join‬تجم ع سلس لتين نص يتين م ع بعض هما‪ ،‬لكنَّه ا‬
‫ً‬
‫ً‬
‫تفعل ذلك بتمرير إحداها إلى األخرى‪ .‬ل ُن ِ‬
‫نصية‪:‬‬
‫سلسلة‬
‫نشئ‬
‫"‪balloon = "Sammy has a balloon.‬‬
‫لنستخدم اآلن الدالة )(‪ str.join‬إلضافة فراغات إلى تلك السلسلة النصية كاآلتي‪:‬‬
‫)‪" ".join(balloon‬‬
‫إذا طبعنا الناتج‪:‬‬
‫))‪print(" ".join(balloon‬‬
‫أن السلسلة النصية الجديدة هي السلسلة األولى لكن بين كل حرفين فراغ‪:‬‬
‫فسنجد َّ‬
‫‪b a l l o o n .‬‬
‫‪a‬‬
‫‪h a s‬‬
‫‪S a m m y‬‬
‫ً‬
‫أيضا استخدام الدالة )(‪ str.join‬إلنشاء مقلوب سلسلة نصية‪:‬‬
‫يمكننا‬
‫)))‪print("".join(reversed(balloon‬‬
‫‪.noollab a sah ymmaS‬‬
‫لم ن رغب في إض افة أيَّ ة سلس لة نص ية إلى أخ رى‪ ،‬ل ذا أبقين ا على السلس لة النص ية فارغ ًة دون‬
‫‪140‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫محت وى داخله ا‪ .‬الدال ة )(‪ str.join‬مفي ٌ‬
‫ً‬
‫أيض ا لجم ع قائم ة (‪ )list‬من السالس ل النص ية‬
‫دة‬
‫وإخراجها إلى سلسلةٍ وحيدة‪ .‬ل ُن ِ‬
‫فصل بين كلماتها بفاصلة من القائمة اآلتية‪:‬‬
‫نشئ سلسلة نصية يُ َ‬
‫))]"‪print(",".join(["sharks", "crustaceans", "plankton‬‬
‫‪sharks,crustaceans,plankton‬‬
‫َ‬
‫أردت وضع فاصلة ثم فراغ بين القيم في المثال السابق‪ ،‬فيمكنك أن ُتعيد كتاب ة التعليم ة‬
‫إذا‬
‫البرمجية السابقة إلضافة فراغ بعد الفاصلة كما يلي‪:‬‬
‫)]"‪", ".join(["sharks", "crustaceans", "plankton‬‬
‫ً‬
‫ً‬
‫أيض ا تجزئته ا‪ ،‬وذل ك ع بر‬
‫بعض ا‪ ،‬نس تطيع‬
‫وكم ا نس تطيع جم ع السالس ل النص ية م ع بعض ها‬
‫الدالة )(‪:str.split‬‬
‫))(‪print(balloon.split‬‬
‫]'‪['Sammy', 'has', 'a', 'balloon.‬‬
‫ً‬
‫ُ‬
‫مفصولة بالفراغ ات في‬
‫ستعيد الدالة )(‪ str.split‬قائمة (‪ )list‬تحوي سالسل نصية كانت‬
‫ٌ‬
‫ً‬
‫أيض ا اس تخدام الدال ة‬
‫معامل لتحديد مح رف الفص ل‪ .‬يمكن ك‬
‫السلسلة النصية األصلية إذا لم يُ مرَّ ر‬
‫معينة من السلسلة النصية األصلية‪ ،‬فلنحاول مثاًل حذف الحرف ‪:a‬‬
‫)(‪ str.split‬لحذف أجزاء‬
‫َّ‬
‫))"‪print(balloon.split("a‬‬
‫]'‪['S', 'mmy h', 's ', ' b', 'lloon.‬‬
‫ح ذِ َف الح رف ‪ a‬من السلس لة النص ية وأص بح الن اتج مقس ومً ا عن د ك ل ورود للح رف ‪ a‬م ع‬
‫ُ‬
‫ً‬
‫ً‬
‫ً‬
‫نصية ُ‬
‫نسخة مح َّدث ًة منه ا بع د‬
‫وتعيد‬
‫سلسلة‬
‫اإلبقاء على الفراغات‪ .‬تأخذ الدالة )(‪str.replace‬‬
‫أن الب الون ال ذي يملك ه س امي ق د ض اع‪ ،‬ولع دم‬
‫إج راء بعض عملي ات االس تبدال عليه ا‪ .‬لنف ترض َّ‬
‫امتالك سامي للبالون في الوقت الراهن‪ ،‬فس ُن ِّ‬
‫بدل الكلمة "‪ "has‬إلى "‪:"had‬‬
‫‪141‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫))"‪print(balloon.replace("has","had‬‬
‫أوَّ ل سلس لة نص ية داخ ل أق واس الدال ة )(‪ replace‬هي السلس لة النص ية ال تي نري د‬
‫اس تبدالها‪ ،‬والسلس لة النص ية الثاني ة هي السلس لة ال تي نري د وض عها ب داًل من األولى‪ .‬ن اتج تنفي ذ‬
‫السطر السابق هو‪:‬‬
‫‪Sammy had a balloon.‬‬
‫اس‬
‫تخدام دوال تع‬
‫ديل السالس‬
‫ل النص‬
‫ية مث‬
‫ل )(‪ str.join‬و )(‪str.split‬‬
‫و ‪ str.replace‬سيمنحك تحكمً ا كبيرًا بمعالجة السالسل النصية في بايثون‪.‬‬
‫‪ .8‬دوال اإلحصاء‬
‫بع د أن تعرفن ا على آلي ة فهرس ة المح ارف في السالس ل النص ية‪ ،‬ح ان ال وقت لمعاين ة بعض‬
‫الدوال التي ُتحصي السالسل النصية أو تعيد أرقام الفه ارس‪ .‬يمكنن ا أن نس تفيد من ذل ك بتحدي د‬
‫عدد المحارف التي نريد استقبالها من مدخالت المستخدم‪ ،‬أو لموازنة السالسل النصية‪.‬‬
‫عدة دوال ُتستخدم لإلحصاء‪ .‬لننظ ر أواًل‬
‫لدى السالسل النصية –كغيرها من أنواع البيانات– ِّ‬
‫أي ن وع متسلس ل من البيان ات‪ ،‬بم ا في ذل ك األن واع ‪string‬‬
‫إلى الدال ة )(‪ len‬ال تي ُتعي د ط ول َّ‬
‫و ‪ list‬و ‪ tuple‬و ‪ .dictionary‬لنطبع طول السلسلة النصية ‪:ss‬‬
‫))‪print(len(ss‬‬
‫‪# 12‬‬
‫ً‬
‫محرف ا‪ ،‬بم ا في ذل ك الف راغ وعالم ة‬
‫ط ول السلس لة النص ية "!‪ "Sammy Shark‬ه و ‪12‬‬
‫ً‬
‫مباشرة تمرير سلسلة نصية إلى الدالة )(‪:len‬‬
‫التعجب‪ .‬بداًل من استخدام متغيِّ ر‪ ،‬فلنحاول‬
‫‪142‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫))"‪print(len("Let's print the length of this string.‬‬
‫‪# 38‬‬
‫الدالة )(‪ُ len‬تحصي الع دد اإلجم الي من المح ارف في سلس لة نص ية‪ .‬إذا أردن ا إحص اء ع دد‬
‫م رات تك رار مح رف أو مجموع ة من المح ارف في سلس لة نص ية‪ ،‬فيمكنن ا اس تخدام الدال ة‬
‫)(‪ ،str.count‬لنحاول إحصاء الحرف ‪ a‬في السلسلة النصية ‪:ss‬‬
‫))"‪print(ss.count("a‬‬
‫‪# 2‬‬
‫محرف آخر‪:‬‬
‫ٍ‬
‫يمكننا البحث عن‬
‫))"‪print(ss.count("s‬‬
‫‪# 0‬‬
‫أن الح رف ‪ S‬ق د ورد في السلس لة النص ية‪ ،‬إال َّ‬
‫أن‬
‫ٌ‬
‫ص‬
‫أنه من الض روري أن تبقي ب ذهنك َّ‬
‫حيح َّ‬
‫ٌ‬
‫معين ة بغض النظ ر عن حالته ا‪ ،‬فعلين ا‬
‫روف‬
‫ٍ‬
‫حساسة لحالة األحرف‪ ،‬فل و أردن ا البحث عن ح‬
‫بايثون‬
‫َّ‬
‫حروف صغيرة‪.‬‬
‫ٍ‬
‫حينها استخدام الدالة )(‪ str.lower‬لتحويل حروف السلسلة النصية إلى‬
‫لنحاول استخدام الدالة )(‪ str.count‬مع سلسلة من المحارف‪:‬‬
‫‪likes = "Sammy likes to swim in the ocean, likes to spin up‬‬
‫"‪servers, and likes to smile.‬‬
‫))"‪print(likes.count("likes‬‬
‫الن اتج ه و ‪ ،3‬إذ تتواج د مجموع ة المح ارف "‪ "likes‬ثالث م رات في السلس لة النص ية‬
‫ً‬
‫أيض ا معرف ة موق ع الح رف أو مجموع ة الح روف في السلس لة النص ية‪ ،‬وذل ك ع بر‬
‫األصلية‪ .‬يمكنن ا‬
‫اء على رقم فهرس ه‪ .‬يمكنن ا أن نع رف م تى يق ع‬
‫الدال ة )(‪ ،str.find‬وس ُيعاد موض ع المح رف بن ً‬
‫أوَّ ل حرف ‪ m‬في السلسلة النصية ‪ ss‬كاآلتي‪:‬‬
‫‪143‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫السالسل النصية والتعامل معها‬
‫))"‪print(ss.find("m‬‬
‫‪# 2‬‬
‫أوّ ل م رة يق ع فيه ا الح رف ‪ m‬في الفه رس ‪ 2‬من السلس لة "!‪ ،"Sammy Shark‬يمكن ك أن‬
‫تراجع بداية هذا الدرس لرؤية جدول يبيِّ ن ارتباطات المحارف م ع فهارس ها في السلس لة الس ابقة‪.‬‬
‫لنرى اآلن مكان أوَّ ل ظهور لمجموعة المحارف ‪ likes‬في السلسلة "‪:"likes‬‬
‫))"‪print(likes.find("likes‬‬
‫‪# 6‬‬
‫أوَّ ل م رة تظه ر فيه ا السلس لة "‪ "likes‬هي في الفه رس ‪ ،6‬أي مك ان وج ود الح رف ‪l‬‬
‫من ‪ .likes‬م اذا ل و أردن ا أن نع رف موض ع ث اني تك رار للكلم ة ‪likes‬؟ نس تطيع فع ل ذل ك بتمري ر‬
‫ان إلى الدال ة )(‪ str.find‬ال ذي س يجعلها تب دأ بحثه ا من ذاك الفه رس‪ ،‬فب داًل من البحث‬
‫معامل ث ٍ‬
‫ٍ‬
‫ً‬
‫انطالقا من الفهرس ‪:9‬‬
‫من أوَّ ل السلسلة النصية سنبحث‬
‫))‪print(likes.find("likes", 9‬‬
‫‪# 34‬‬
‫بدأ البحث في هذا المثال من الفهرس ‪ ،9‬وكانت أوَّ ل مطابقة للسلسلة النصية "‪ "likes‬عند‬
‫ً‬
‫إضافة إلى ذلك‪ ،‬يمكننا تحديد نهاية إلى مجال البحث بتمرير معامل ثالث‪ .‬وكم ا عن د‬
‫الفهرس ‪.34‬‬
‫عكسيا‪:‬‬
‫تقسيم السالسل النصية‪ ،‬يمكننا استخدام أرقام الفهارس السالبة للعد‬
‫ً‬
‫))‪print(likes.find("likes", 40, -6‬‬
‫‪# 64‬‬
‫يبحث آخ ر مث ال عن موض ع السلس لة النص ية "‪ "likes‬بين الفه رس ‪ 40‬و ‪ ،-6‬ولمَّ ا ك ان‬
‫المعامل األخير هو رقم سالب‪ ،‬فسيبدأ العد من نهاية السلسلة األصلية‪.‬‬
‫‪144‬‬
‫|‬
‫▲‬
‫السالسل النصية والتعامل معها‬
‫البرمجة بلغة بايثون‬
‫دوال اإلحص اء مث ل )(‪ len‬و )(‪ str.count‬و )(‪ str.find‬مفي ٌ‬
‫دة في تحدي د ط ول‬
‫معينة فيها‪.‬‬
‫السلسلة النصية وعدد حروفها وفهارس ورود محارف‬
‫َّ‬
‫‪ .9‬خالصة الفصل‬
‫لقد تعلمنا في هذا الفصل أساس يات التعام ل م ع السالس ل النص ية في لغ ة ب ايثون ‪ .3‬بم ا في‬
‫ً‬
‫إضافة إلى تخزينها في متغيرات‪ ،‬وهذه هي المعلوم ات‬
‫ذلك إنشاءها وطباعتها وجمعها وتكرارها‪،‬‬
‫األساسية التي عليك فهمها لالنطالق في تعاملك مع السالسل النصية في برامج بايثون ‪.3‬‬
‫‪145‬‬
‫|‬
‫▲‬
‫‪8‬‬
‫مدخل إلى تنسيق‬
‫النصوص‬
‫‪146‬‬
‫|‬
‫▲‬
‫مدخل إلى تنسيق النصوص‬
‫البرمجة بلغة بايثون‬
‫ً‬
‫عادة من النص المكتوب‪ ،‬وهنالك ِّ‬
‫تحكم‬
‫عدة حاالت نحت اج فيه ا إلى‬
‫تتألف السالسل النصية‬
‫ٍ‬
‫ً‬
‫قراءة للبشر عبر وضع عالم ات ال ترقيم والس طور الجدي دة‬
‫بكيفية إظهار النص وجعلها أسهل‬
‫أكبر‬
‫َّ‬
‫كيفية التعام ل م ع السالس ل النص ية في ب ايثون لكي يظه ر‬
‫والمح اذاة‪ .‬سنش رح في ه ذا الفص ل‬
‫َّ‬
‫النص الناتج بتنسيق صحيح‪.‬‬
‫‪ .1‬الصياغة المختزلة‬
‫لنف ِّرق أواًل بين الص ياغة المختزل ة للسالس ل النص ية ( ‪ )string literal‬والسالس ل النص ية‬
‫المجرَّ دة نفسها (‪ ،)string value‬فاألولى هي ما نراه في الشيفرة المصدرية للبرن امج‪ ،‬بم ا في ذل ك‬
‫عالمتَي االقتباس‪ .‬أمَّ ا السلسلة النصية نفس ها فهي م ا نراه ا عن دما نس تدعي الدال ة )(‪ print‬عن د‬
‫تش غيل البرن امج‪ .‬ففي برن امج !‪ Hello, World‬التقلي دي‪ ،‬تك ون الص ياغة المختزل ة هي‬
‫"!‪World‬‬
‫‪ "Hello,‬بينم ا السلس لة النص ية المج رَّ دة هي !‪World‬‬
‫‪ Hello,‬دون عالمتَي‬
‫أن السلسلة النصية هي ما نراه في نافذة الطرفية عندما ُنش ِّغل برن امج ب ايثون‪ .‬لكن‬
‫االقتباس‪ .‬أي َّ‬
‫وألن القيم‬
‫بعض السالس ل النص ية ق د تحت وي على عالم ات اقتب اس‪ ،‬مث ل اقتباس نا لمقول ةٍ م ا‪.‬‬
‫َّ‬
‫المُ صنَّفة على َّ‬
‫أنها سالسل نصية بالصياغة المختزلة والقيم الفعلية المجرَّ دة للسالس ل النص ية غ ير‬
‫متساوية‪ ،‬فمن الضروري في أغلب الح االت إض افة تنس يق إلى ص ياغة السلس لة النص ية المختزل ة‬
‫لعرضها كما ينبغي‪.‬‬
‫‪ .2‬عالمات االقتباس‬
‫بس بب إمكانيتن ا اس تخدام عالم ات االقتب اس المف ردة أو المزدوج ة في ب ايثون‪ ،‬فمن الس هل‬
‫تض مين االقتباس ات بوض عها بين عالمتَي اقتب اس مزدوج تين في سلس لةٍ نص يةٍ محاط ةٍ بعالمتَي‬
‫اقتباس مفردتين كما في السلسلة اآلتية‪:‬‬
‫‪147‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫'"!‪'Sammy says, "Hello‬‬
‫أو يمكنن ا اس تخدام عالم ة اقتب اس فردي ة (أو كم ا يس مونها «فاص لة علي ا» [ ‪)]apostrophe‬‬
‫في سلسلةٍ نصيةٍ محاطةٍ بعالمتَي اقتباس مزدوجتين‪:‬‬
‫"‪"Sammy's balloon is red.‬‬
‫ً‬
‫إذا‪ ،‬يمكنن ا التحكم بطريق ة ع رض عالم ات االقتب اس والفواص ل العلي ا في سالس لنا النص ية‬
‫عبر استخدام النوع الصحيح من عالمات االقتباس إلحاطة كامل السلسلة النصية‪.‬‬
‫‪ .3‬كتابة النص على أكثر من سطر‬
‫طباعة السالسل النص ية على أك ثر من س طر س تجعل منه ا واض ً‬
‫حة وس هلة الق راءة‪ .‬إذ يمكن‬
‫ِّ‬
‫بعدة أسطر لزيادة وضوحها‪ ،‬أو لتنسيقها كرس الة‪ ،‬أو للحف اظ على تع ُّدد‬
‫تجميع النصوص المكتوبة‬
‫األس طر في األش عار‪ .‬نس تخدم ثالث عالم ات اقتب اس فردي ة ''' أو ثالث عالم ات اقتب اس‬
‫مزدوجة """ لإلحاطة بالسلسلة النصية التي تمتد على أكثر من سطر‪:‬‬
‫'''‬
‫‪This string is on‬‬
‫‪multiple lines‬‬
‫‪within three single‬‬
‫‪quotes on either side.‬‬
‫'''‬
‫"""‬
‫‪This string is on‬‬
‫‪multiple lines‬‬
‫‪within three double‬‬
‫‪quotes on either side.‬‬
‫"""‬
‫‪148‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫يمكنك اآلن طباعة السالسل النصية في ِّ‬
‫خصوص ا‬
‫ً‬
‫عدة أسطر لجعل النصوص سهلة القراءة –‬
‫الطويلة منها– وذلك عبر استخدام ثالث عالمات اقتباس متتالية‪.‬‬
‫‪ .4‬تهريب المحارف‬
‫طريق ة أخ رى لتنس يق السالس ل النص ية هي اس تخدام «مح رف الته ريب»‬
‫(‪ .)escape character‬فجميع عملي ات ته ريب المح ارف تب دأ بالخ ط المائ ل الخلفي (‪،backslash‬‬
‫رف آخ ر ال ذي ل ه مع نى خ اص يفي د في تنس يق السلس لة النص ية‪ .‬ه ذه قائم ة‬
‫أي \) متبوعً ا بمح ٍ‬
‫بأكثر محارف التهريب شيوعً ا‪:‬‬
‫•‬
‫\‪ :‬سطرٌ جدي ٌد في سلسلةٍ نصيةٍ متألفةٍ من ِّ‬
‫عدة أسطر‪.‬‬
‫•‬
‫\\‪ :‬طباعة رمز الخط المائل الخلفي‪.‬‬
‫•‬
‫'\‪ :‬طباعة عالمة اقتباس فردية‪.‬‬
‫•‬
‫"\‪ :‬طباعة عالمة اقتباس مزدوجة‪.‬‬
‫•‬
‫سطر جديد‪.‬‬
‫‪ :\n‬طباعة محرف االنتقال إلى‬
‫ٍ‬
‫•‬
‫‪ :\t‬طباعة محرف الجدولة (‪.)Tab‬‬
‫لنستخدم محرف التهريب إلضافة عالمات االقتباس إلى سلس لتنا النص ية الس ابقة‪ ،‬لكن ه ذه‬
‫المرة س ُنحيط السلسلة النصية بعالمتَي اقتباس مزدوجتين‪:‬‬
‫)""\!‪print("Sammy says, \"Hello‬‬
‫"!‪# Sammy says, "Hello‬‬
‫‪149‬‬
‫|‬
‫▲‬
‫مدخل إلى تنسيق النصوص‬
‫البرمجة بلغة بايثون‬
‫تمكننا عبر محرف التهريب "\ من استخدام عالمات االقتباس المزدوجة لإلحاط ة بالسلس لة‬
‫ً‬
‫أيض ا‬
‫اط بعالمتَي اقتب اس مزدوج تين‪ .‬نس تطيع‬
‫مقتبس ومح ٍ‬
‫نص‬
‫النص ية ال تي تحت وي على ٍ‬
‫ٍ‬
‫اس تخدام مح رف الته ريب '\ إلض افة عالم ة اقتب اس مف ردة ض من السلس لة النص ية المحاط ة‬
‫بعالمتَي اقتباس مفردتين‪:‬‬
‫)'‪print('Sammy\'s balloon is red.‬‬
‫‪# Sammy's balloon is red.‬‬
‫وألنن ا نس تخدم اآلن مح رف الته ريب فنس تطيع وض ع عالم ات االقتب اس المف ردة ح تى ل و‬
‫ك انت السلس لة النص ية كله ا موج ودة بين عالمتَي اقتب اس مف ردتين‪ .‬عن دما نس تخدم عالم ات‬
‫ً‬
‫فراغ ا في أعلى وأس فل النص عن د طباعت ه‪ .‬نس تطيع‬
‫االقتباس الثالثية –كما فعلن ا أعاله– فس نجد‬
‫حذف تلك الفراغات عبر استخدام محرف التهريب \ في بداية ونهاية السلسلة النصية مع اإلبقاء‬
‫مقروءا بسهولة في الشيفرة‪.‬‬
‫ً‬
‫على النص‬
‫\"""‬
‫‪This multi-line string‬‬
‫‪has no space at the‬‬
‫‪top or the bottom‬‬
‫\‪when it prints.‬‬
‫"""‬
‫كل ش بيهٍ بم ا س بق‪ ،‬يمكنن ا اس تخدام مح رف الته ريب ‪ \n‬لوض ع أس طر جدي دة دون‬
‫وبش ٍ‬
‫الحاجة إلى الضغط على زر ‪ Enter‬أو ‪:Return‬‬
‫‪150‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫)"‪print("This string\nspans multiple\nlines.‬‬
‫‪# This string‬‬
‫‪# spans multiple‬‬
‫‪# lines.‬‬
‫لة نص ً‬
‫يمكننا ال دمج بين مح ارف الته ريب‪ ،‬إذ س نطبع في المث ال اآلتي سلس ً‬
‫ية على أك ثر من‬
‫سطر‪ ،‬ونستعمل فيها مسافة جدولة (‪ )tab‬بين الترقيم ومحتوى السطر‪:‬‬
‫)"‪print("1.\tShark\n2.\tShrimp\n10.\tSquid‬‬
‫‪Shark‬‬
‫‪# 1.‬‬
‫‪Shrimp‬‬
‫‪# 2.‬‬
‫‪Squid‬‬
‫‪# 10.‬‬
‫عالمة الجدولة األفقية ال تي وض عناها ع بر مح رف الته ريب ‪ \t‬س تحاذي الكتاب ة في العم ود‬
‫النص ي الث اني في المث ال أعاله‪ ،‬مم ا يجع ل قراءته ا س ً‬
‫أن مح رف الته ريب ‪\n‬‬
‫ٌ‬
‫هلة ج ًدا‪ .‬وص‬
‫حيح َّ‬
‫ً‬
‫روءة‬
‫يعم ل عماًل جي ًدا في النص وص القص ير‪ ،‬لكن ال ُنغفِ ل أهمي ة أن تك ون الش يفرة المص درية مق‬
‫ً‬
‫أن من األفضل استخدام عالمات االقتباس الثالثية‪.‬‬
‫بسهولةٍ‬
‫أيضا‪ .‬فلو كان النص طوياًل ‪ ،‬فأرى َّ‬
‫أن مح ارف الته ريب ُتس تعمَ ل إلض افة تنس يق إلى السالس ل ال تي ك ان من الص عب (أو‬
‫رأين ا َّ‬
‫ً‬
‫عرض ا س ليمً ا دونه ا‪ .‬فه ل تس تطيع مثاًل أن تطب ع السلس لة النص ية اآلتي ة‬
‫حتى المستحيل) عرضها‬
‫دون استخدام محارف التهريب؟‬
‫"‪Sammy says, "The balloon's color is red.‬‬
‫‪ .5‬السالسل النصية الخام‬
‫ماذا لو أردنا تجاهل كل محارف التنسيق الخاص ة في سالس لنا النص ية؟ فلربم ا أردن ا موازن ة‬
‫ُّ‬
‫التحقق من صحة بعض الشيفرات الحاسوبية التي تستخدم الخ ط المائ ل الخلفي‪ ،‬وال نري د من‬
‫أو‬
‫‪151‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫بايثون تفسيره على َّ‬
‫أنه محرف تهريب‪ .‬أتت «السالسل النصية الخام» ( ‪ )raw strings‬في بايثون‬
‫لتح ل ه ذه المش كلة‪ ،‬وتتجاه ل جمي ع مح ارف التنس يق داخ ل سلس لة نص ية‪ ،‬بم ا في ذلك‬
‫محارف التهريب‪.‬‬
‫يمكنن ا إنش اء سلس لة نص ية خ ام بوض ع الح رف ‪ r‬في بداي ة السلس لة النص ية‪ ،‬قب ل عالم ة‬
‫ً‬
‫مباشرة‪:‬‬
‫االقتباس األولى‬
‫)""\‪print(r"Sammy says,\"The balloon\'s color is red.‬‬
‫"\‪# Sammy says,\"The balloon\'s color is red.‬‬
‫سنستطيع اإلبقاء على محارف التهريب كما هي في السالسل النصية إن أسبقناها بالحرف ‪r‬‬
‫لتحويلها إلى سالسل نصية خام‪.‬‬
‫نسقات‬
‫الم ِّ‬
‫‪ .6‬استخدام ُ‬
‫الدالة )(‪ str.format‬المتوافرة للسالسل النص ية تس مح ل ك باس تبدال المتغ يرات وتنس يق‬
‫القيم‪ .‬مما يمنحك القدرة على تجميع العناصر مع بعض ها ع بر إدخاله ا في مواض ع معين ة‪ .‬سيش رح‬
‫ل ك ه ذا القس م أش هر االس تخدامات آللي ة تنس يق السالس ل النص ية في ب ايثون‪ ،‬وال تي ستس اعدك‬
‫ً‬
‫قراءة واستخدامً ا‪.‬‬
‫في جعل شيفرتك وبرنامجك أسهل‬
‫تعم ل المُ ِّ‬
‫نس قات (‪ )formatters‬بوض ع حق ول قابل ة لالس تبدال ُتع رَّ ف ع بر وض ع قوس ين‬
‫معق وفين {} في السلس لة النص ية ثم اس تدعاء الدال ة )(‪ ،str.format‬إذ س ُتمرَّ ر القيم ة ال تي‬
‫تري د وض عها ض من السلس لة النص ية إلى الدال ة )(‪ format‬وستوض ع ه ذه القيم ة في نفس مك ان‬
‫الحق ل القاب ل لالس تبدال الموج ود في السلس لة األص لية عن دما ُتش ِّغل برنامج ك‪ .‬لنطب ع سلس ً‬
‫لة‬
‫ً‬
‫نصية تستخدم « ِّ‬
‫منس ًقا» (‪:)formatter‬‬
‫‪152‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫))‪print("Sammy has {} balloons.".format(5‬‬
‫الناتج‪:‬‬
‫‪Sammy has 5 balloons.‬‬
‫ً‬
‫ً‬
‫نصية تحتوي على قوسين معقوصين {}‪:‬‬
‫سلسلة‬
‫أنشأنا في المثال السابق‬
‫"‪"Sammy has {} balloons.‬‬
‫أن القيم ة ‪5‬‬
‫ثم أض فنا الدال ة )(‪ str.format‬ومرَّ رن ا إليه ا القيم ة الرقمي ة ‪ 5‬وه ذا يع ني َّ‬
‫ستوضع مكان القوسين المعقوصين‪:‬‬
‫‪Sammy has 5 balloons.‬‬
‫ً‬
‫أيضا إسناد السلسلة النصية األصلية التي تحوي مُ ِّ‬
‫نس ًقا إلى متغير‪:‬‬
‫يمكننا‬
‫"‪open_string = "Sammy loves {}.‬‬
‫))"‪print(open_string.format("open source‬‬
‫الناتج‪:‬‬
‫‪Sammy loves open source.‬‬
‫أض فنا في المث ال الس ابق السلس لة النص ية "‪ "open source‬إلى سلس لةٍ نص يةٍ أك بر‬
‫باستبدالها للقوسين المعقوفين الموجو َدين في السلسلة األصلية‪ .‬تسمح ل ك المُ ِّ‬
‫نس قات في ب ايثون‬
‫باس تخدام األق واس المعقوف ة لحج ز أم اكن للقيم ال تي س تمررها مس تقباًل ع بر‬
‫الدالة )(‪.str.format‬‬
‫ا‪ .‬استخدام المُ ِّ‬
‫نسقات لحجز أكثر من مكان‬
‫يمكنك استخدام أكثر من زوج من األقواس المعقوصة عن د اس تعمال المُ ِّ‬
‫نس قات؛ فيمكن ك أن‬
‫‪153‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫لة نص ً‬
‫تض يف سلس ً‬
‫ية أخ رى إلى المث ال الس ابق وذل ك بإض افة زوج آخ ر من األق واس المعقوص ة‬
‫وتمرير قيمة ثانية إلى الدالة كما يلي‪:‬‬
‫مكانين محجوزين عبر }{ ‪#‬‬
‫"‪new_open_string = "Sammy loves {} {}.‬‬
‫ٌ‬
‫مفصول بينهما بفاصلة ‪#‬‬
‫تمرير قيمتين إلى الدالة‬
‫))"‪print(new_open_string.format("open-source", "software‬‬
‫الناتج‪:‬‬
‫‪Sammy loves open-source software.‬‬
‫ً‬
‫زوجا آخر من األقواس المعقوصة إلى السلس لة النص ية للس ماح بوض ع قيم ة ثاني ة‪ ،‬ثم‬
‫أضفنا‬
‫مررن ا سلس لتين نص يتين إلى الدال ة )(‪ str.format‬مفص ٌ‬
‫ول بينهم ا بفاص لة‪ .‬سنض يف عملي ات‬
‫استبدال أخرى عبر اتباع نفس اآللية التي شرحناها أعاله‪:‬‬
‫"‪sammy_string = "Sammy loves {} {}, and has {} {}.‬‬
‫‪print(sammy_string.format("open-source", "software", 5,‬‬
‫))"‪"balloons‬‬
‫الناتج‪:‬‬
‫‪Sammy loves open-source software, and has 5 balloons.‬‬
‫ب‪ .‬إعادة ترتيب المنسقات عبر المعامالت الموضعية‬
‫عندما نترك األقواس المعقوص ة دون مع امالت (‪ )parameters‬مم ررة إليه ا‪ ،‬فستض ع ب ايثون‬
‫القيم المُ مرَّ رة إلى الدالة )(‪ str.format‬بالترتيب‪ .‬هذا تعبيرٌ فيه زوجين من األقواس المعقوصة‬
‫ً‬
‫ٌ‬
‫سابقا في هذا الفصل‪:‬‬
‫شبيه بما رأيناه‬
‫يوضع مكانهما سلسلتان نصيتان‬
‫‪154‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫‪print("Sammy the {} has a pet {}!".format("shark", "pilot‬‬
‫))"‪fish‬‬
‫الناتج‪:‬‬
‫!‪Sammy the shark has a pet pilot fish‬‬
‫زوج من األقواس المعقوصة ووضعت مكانه القيمة "‪ ،"shark‬ووضعت القيمة‬
‫ُاستبدِ ل أوَّ ل‬
‫ٍ‬
‫"‪ "pilot fish‬مكان الزوج الثاني من األقواس‪ .‬القيم التي مرَّ رناها إلى الدال ة )(‪str.format‬‬
‫كانت بهذا الترتيب‪:‬‬
‫)"‪("shark", "pilot fish‬‬
‫أن القيم ة الس ابقة هي من الن وع ‪( tuple‬ص ف)‪ ،‬ويمكن الوص ول إلى ك ل قيم ة‬
‫الح ظ َّ‬
‫ابع له ا‪ ،‬وال ذي يب دأ من الفه رس ‪ .0‬يمكنن ا تمري ر أرق ام الفه ارس‬
‫رس‬
‫موجودة فيه ا ع بر فه ٍ‬
‫رقمي ت ٍ‬
‫ٍ‬
‫إلى داخل القوسين المعقوفين‪:‬‬
‫‪print("Sammy the {0} has a pet {1}!".format("shark", "pilot‬‬
‫))"‪fish‬‬
‫سنحص ل بع د تنفي ذ المث ال الس ابق على نفس الن اتج ال تي ظه ر دون تحدي د أرق ام الفه ارس‬
‫يدويًّ ا‪ ،‬وذلك َّ‬
‫ألننا استدعينا القيم بالترتيب‪:‬‬
‫!‪Sammy the shark has a pet pilot fish‬‬
‫لكن إن عكس نا أرق ام الفه ارس في مع امالت األق واس المعقوف ة فس نتمكن من عكس ت رتيب‬
‫القيم المُ مرَّ رة إلى السلسلة النصية األصلية‪:‬‬
‫‪print("Sammy the {1} has a pet {0}!".format("shark", "pilot‬‬
‫))"‪fish‬‬
‫‪155‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫الناتج‪:‬‬
‫!‪Sammy the pilot fish has a pet shark‬‬
‫لكن إن ح اولت اس تخدام الفه رس ذي ال رقم ‪ 2‬ولم تكن ل ديك إال قيم تين موج ودتين في‬
‫ً‬
‫قيمة خارج المجال المسموح‪ ،‬ولهذا السبب ستظهر رسالة خطأ‪:‬‬
‫الفهرسين ‪ 0‬و ‪ ،1‬فأنت تستدعي‬
‫‪print("Sammy the {2} has a pet {1}!".format("shark", "pilot‬‬
‫))"‪fish‬‬
‫الناتج‪:‬‬
‫‪IndexError: tuple index out of range‬‬
‫ط‬
‫ُتش ِير رسالة الخطأ إلى وجود قيمتين فقط ومكانهما هو ‪ 0‬و‪ ،1‬لذا كان الفهرس ‪ 2‬غير مرتب ٍ‬
‫بقيمةٍ وك ان خ ارج المج ال المس موح‪ .‬لنض ف اآلن مك انين محج وزين إلى السلس لة النص ية ولنم ِّرر‬
‫بض ع قيم إلى الدال ة )(‪ str.format‬لكي نفهم آلي ة إع ادة ال ترتيب فهمً ا تامً ا‪ .‬ه ذه هي السلس لة‬
‫النصية الجديدة التي فيها أربعة أزواج من األقواس المعقوصة‪:‬‬
‫‪print("Sammy is a {}, {}, and {} {}!".format("happy",‬‬
‫))"‪"smiling", "blue", "shark‬‬
‫الناتج‪:‬‬
‫!‪Sammy is a happy, smiling and blue shark‬‬
‫ستوض ع القيم المُ م رَّ رة إلى الدال ة )(‪ str.format‬بنفس ت رتيب وروده ا في ح ال لم‬
‫نس تعمل المع امالت داخ ل األق واس المعقوص ة‪ .‬تمل ك السالس ل النص ية المُ م رَّ رة إلى الدالة‬
‫)(‪ str.format‬الفهارس اآلتية المرتبطة بها؛ لنستخدم اآلن أرقام الفه ارس لتغي ير ت رتيب ظه ور‬
‫القيم المرتبطة بها في السلسلة النصية‪:‬‬
‫‪156‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫‪print("Sammy is a {3}, {2}, and {1} {0}!".format("happy",‬‬
‫))"‪"smiling", "blue", "shark‬‬
‫الناتج‪:‬‬
‫!‪Sammy is a shark, blue, and smiling happy‬‬
‫أن وض ع رقم‬
‫ولمّ ا ك ّن ا ق د ب دأنا ب الفهرس ذي ال رقم ‪ ،3‬فس تظهر القيم ة "‪ "shark‬أواًل‪ .‬أي َّ‬
‫الفهرس بين القوسين كمعامل سيؤدي إلى تغيير ترتيب ظهور القيم في السلسلة النصية األص لية‪.‬‬
‫نس تطيع ‪-‬باإلض افة إلى المع امالت الموض عية الرقمي ة‪ -‬أن نرب ط بين القيم وبين كلم ات محج وزة‬
‫مخصصة ومن ثم نستدعيها عبر وضع الكلمة المحجوزة بين القوسين المعقوصين كما يلي‪:‬‬
‫= ‪print("Sammy the {0} {1} a {pr}.".format("shark", "made", pr‬‬
‫))"‪"pull request‬‬
‫الناتج‪:‬‬
‫‪Sammy the shark made a pull request.‬‬
‫أظه ر المث ال الس ابق اس تخدام كلم ة محج وزة وس ً‬
‫عية‪،‬‬
‫يطا باإلض افة إلى المع امالت الموض َّ‬
‫ً‬
‫أيض ا‬
‫يمكن ك اس تخدام الكلم ة المحج وزة ‪ pr‬كوس يط باإلض افة إلى أرق ام الفه ارس‪ ،‬وتس تطيع‬
‫إعادة ترتيب تلك الوسائط كيفما شئت‪:‬‬
‫= ‪print("Sammy the {pr} {1} a {0}.".format("shark", "made", pr‬‬
‫))"‪"pull request‬‬
‫الناتج‪:‬‬
‫‪Sammy the pull request made a shark.‬‬
‫‪157‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫بكيفية معالج ة‬
‫عية والكلم ات المحج وزة س يمنحنا تحكمً ا أك بر‬
‫َّ‬
‫اس تخدام المع امالت الموض َّ‬
‫السلسلة النصية األصلية عبر إعادة ترتيب القيم المُ مرَّ رة إليها‪.‬‬
‫ج‪ .‬استخدام المُ ِّ‬
‫نسقات لتنظيم البيانات‬
‫يس طع نجم آلي ة التنس يق ال تي نش رحها في ه ذا الفص ل عن دما ُتس تخ َدم لتنظيم البيان ات‬
‫بصريً ا‪ ،‬فلو أردنا إظهار نتائج قاعدة البيانات إلى المستخدمين‪ ،‬فيمكننا استعمال المُ ِّ‬
‫نسقات لزي ادة‬
‫ً‬
‫راءة‪ .‬لننظ ر إلى حلق ة تك رار تقليدي ة في‬
‫حجم الحق ل وتع ديل المح اذاة لجع ل الن اتج أس هل ق‬
‫لمجال من األعداد من ‪ 3‬إلى ‪:13‬‬
‫بايثون التي تطبع ‪ i‬و ‪ i*i‬و ‪i*i*i‬‬
‫ٍ‬
‫‪for i in range(3,13):‬‬
‫)‪print(i, i*i, i*i*i‬‬
‫الناتج‪:‬‬
‫‪3 9 27‬‬
‫‪4 16 64‬‬
‫‪5 25 125‬‬
‫‪6 36 216‬‬
‫‪7 49 343‬‬
‫‪8 64 512‬‬
‫‪9 81 729‬‬
‫‪10 100 1000‬‬
‫‪11 121 1331‬‬
‫‪12 144 1728‬‬
‫أن الن اتج مُ َّ‬
‫أن األع داد تت داخل م ع بعض ها بص ريً ا مم ا يُ ص ِّعب ق راءة‬
‫ٌ‬
‫ص‬
‫نظمٌ قلياًل ‪ ،‬إال َّ‬
‫حيح َّ‬
‫َ‬
‫كنت تتعام ل م ع مجموع ة أك بر من البيان ات ال تي يتواج د فيه ا‬
‫األس طر األخ يرة من الن اتج‪ ،‬وإذا‬
‫أعداد أكبر (أو أصغر) مما عرضناه في مثالن ا‪ ،‬فق د تب دو ل ك المش كلة جلي ًة حينه ا‪ .‬لنح اول تنس يق‬
‫‪158‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫الناتج السابق إلعطاء مساحة أكبر إلظهار األعداد عبر المثال التالي‪:‬‬
‫‪for i in range(3,13):‬‬
‫))‪print("{:3d} {:4d} {:5d}".format(i, i*i, i*i*i‬‬
‫ً‬
‫لم ُن ِّ‬
‫مباشرة بكتابة النقط تين الرأس يتين متبوع ًة‬
‫حدد في المثال السابق ترتيب الحقل وبدأنا‬
‫بحجم الحقل ورمز التحويل ‪َّ ( d‬‬
‫ألننا نتعامل مع أعداد صحيحة)‪ .‬أعطينا في المث ال الس ابق حجمً ا‬
‫للحقل مساويً ا لعدد أرق ام الع دد ال ذي نتوق ع طباعت ه في الحق ل المع ني مض ً‬
‫افا إلي ه ‪ ،2‬ل ذا س يبدو‬
‫الناتج كاآلتي‪:‬‬
‫‪27‬‬
‫‪9‬‬
‫‪3‬‬
‫‪64‬‬
‫‪16‬‬
‫‪4‬‬
‫‪125‬‬
‫‪25‬‬
‫‪5‬‬
‫‪216‬‬
‫‪36‬‬
‫‪6‬‬
‫‪343‬‬
‫‪49‬‬
‫‪7‬‬
‫‪512‬‬
‫‪64‬‬
‫‪8‬‬
‫‪729‬‬
‫‪81‬‬
‫‪9‬‬
‫‪1000‬‬
‫‪100‬‬
‫‪10‬‬
‫‪1331‬‬
‫‪121‬‬
‫‪11‬‬
‫‪1728‬‬
‫‪144‬‬
‫‪12‬‬
‫ً‬
‫أيض ا تحدي د حجم ث ابت للحق ل لنحص ل على أعم دة متس اوية الع رض‪ ،‬مم ا يض من‬
‫يمكنن ا‬
‫إظهار األعداد الكبيرة بصورة صحيحة‪:‬‬
‫‪for i in range(3,13):‬‬
‫))‪print("{:6d} {:6d} {:6d}".format(i, i*i, i*i*i‬‬
‫الناتج‪:‬‬
‫‪27‬‬
‫‪9‬‬
‫‪3‬‬
‫‪64‬‬
‫‪16‬‬
‫‪4‬‬
‫‪159‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫‪125‬‬
‫‪25‬‬
‫‪5‬‬
‫‪216‬‬
‫‪36‬‬
‫‪6‬‬
‫‪343‬‬
‫‪49‬‬
‫‪7‬‬
‫‪512‬‬
‫‪64‬‬
‫‪8‬‬
‫‪729‬‬
‫‪81‬‬
‫‪9‬‬
‫‪1000‬‬
‫‪100‬‬
‫‪10‬‬
‫‪1331‬‬
‫‪121‬‬
‫‪11‬‬
‫‪1728‬‬
‫‪144‬‬
‫‪12‬‬
‫ً‬
‫أيضا تعديل محاذاة النص الموجود في األعمدة باستخدام الرموز > و ^ و <‪ ،‬وتبديل‬
‫يمكننا‬
‫‪ d‬إلى ‪ f‬إلظه ار من ازل عش رية‪ ،‬وغ ير ذل ك مم ا تعلمن اه في ه ذا ال درس إلظه ار البيان ات الناتج ة‬
‫كما نرغب‪.‬‬
‫‪ .7‬تحديد نوع القيمة‬
‫يمكن ك وض ع مع امالت أخ رى ض من القوس ين المعقوص ين‪ ،‬سنس تخدم الص يغة اآلتي ة‬
‫{‪ }field_name:conversion‬إذ ‪ field_name‬ه و الفه رس ال رقمي للوس يط المُ م رَّ ر إلى‬
‫يليا في القس م الس ابق‪ ،‬و ‪ conversion‬ه و الرم ز‬
‫الدال ة )(‪ str.format‬وال ذي ش رحناه تفص ً‬
‫رف وحي د‬
‫المس تعمل للتحوي ل إلى ن وع البيان ات ال ذي تري ده‪« .‬رم ز التحوي ل» يع ني رم ًزا من ح ٍ‬
‫الذي تستخدمه بايثون لمعرفة نوع القيمة المُ راد «تنسيقها»‪ .‬الرموز التي سنستخدمها في أمثلتنا‬
‫هي ‪ s‬للسالس ل النص ية و ‪ d‬إلظه ار األرق ام بنظ ام الع د العش ري (ذي األس اس ‪ )10‬و ‪ f‬إلظه ار‬
‫األعداد ذات الفاصلة‪.‬‬
‫يمكنك قراءة المزيد من التفاصيل عن رموز التنسيق في بايثون ‪( 3‬وغير ذل ك من المواض يع‬
‫ً‬
‫حيحا ع بر‬
‫ال ُنم ِّرر في ه رقمً ا ص‬
‫المرتبط ة به ذا المج ال) في التوثي ق الرس مي‪ .‬لننظ ر إلى مث ٍ‬
‫الدالة )(‪ format‬لكننا نريد إظهاره كعددٍ ذي فاصلة عبر رمز التحويل ‪:f‬‬
‫‪160‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫))"‪print("Sammy ate {0:f} percent of a {1}!".format(75, "pizza‬‬
‫الناتج‪:‬‬
‫!‪Sammy ate 75.000000 percent of a pizza‬‬
‫وضعت القيمة ‪-‬مك ان أوَّ ل ورود للص يغة {‪ -}field_name:conversion‬كع ددٍ ذي فاص لة‪،‬‬
‫أمَّ ا ث اني ورود للقوس ين المعقوص ين فك ان بالص يغة {‪ .}field_name‬الح ظ في المث ال الس ابق‬
‫وجود ع دد كب ير من األرق ام الظ اهرة بع د الفاص لة العش رية‪ ،‬لكن ك تس تطيع تقلي ل ع ددها‪ .‬فعن دما‬
‫ً‬
‫أيض ا تحدي د دق ة القيم ة الناتج ة بتض مين رم ز‬
‫نس تخدم الرم ز ‪ f‬للقيم ذات الفاص لة نس تطيع‬
‫النقطة ‪ .‬متبوعً ا بعدد األرقام بعد الفاصلة التي نود عرضها‪ .‬حتى لو أكل سامي ‪ %75.765367‬من‬
‫قطع ة البي تزا فلن نحت اج إلى ه ذا الق در الكب ير من الدق ة‪ ،‬إذ يمكنن ا مثاًل أن نجع ل ع دد المن ازل‬
‫العشرية ثالث منازل بعد الفاصلة بوضعنا ‪ .3‬قبل رمز التحويل ‪:f‬‬
‫‪print("Sammy ate {0:.3f} percent of a‬‬
‫))‪pizza!".format(75.765367‬‬
‫الناتج‪:‬‬
‫!‪Sammy ate 75.765 percent of a pizza‬‬
‫أما إذا أردنا عرض منزلة عشرية وحيدة‪ ،‬فيمكننا إعادة كتابة السلسلة السابقة كاآلتي‪:‬‬
‫‪print("Sammy ate {0:.1f} percent of a‬‬
‫))‪pizza!".format(75.765367‬‬
‫الناتج‪:‬‬
‫!‪Sammy ate 75.8 percent of a pizza‬‬
‫‪161‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫الح ظ كي ف أدى تع ديل دق ة األرق ام العش رية إلى تق ريب ال رقم (وف ق قواع د التق ريب‬
‫حيح أنن ا عرض نا رقمً ا دون من ازل عش رية كع ددٍ ذي فاص لة‪ ،‬إال أنن ا إذا حاولن ا‬
‫ٌ‬
‫االعتيادي ة)‪ .‬وص‬
‫تحويل عدد عشري إلى عدد صحيح باستخدام رمز التحويل ‪ d‬فسنحصل على خطأ‪:‬‬
‫))‪print("Sammy ate {0:.d} percent of a pizza!".format(75.765367‬‬
‫الناتج‪:‬‬
‫'‪ValueError: Unknown format code 'd' for object of type 'float‬‬
‫إذا لم ترغب بعرض أيَّ ة منازل عشرية‪ ،‬فيمكنك كتابة تعبير كاآلتي‪:‬‬
‫‪print("Sammy ate {0:.0f} percent of a‬‬
‫))‪pizza!".format(75.765367‬‬
‫الناتج‪:‬‬
‫!‪Sammy ate 76 percent of a pizza‬‬
‫ِّ‬
‫يؤدي ما سبق إلى تحوي ل الع دد العش ري إلى ع ددٍ ص حيح‪َّ ،‬‬
‫وإنم ا س يؤدي إلى تقلي ل ع دد‬
‫لن‬
‫المنازل العشرية الظاهرة بعد الفاصلة‪.‬‬
‫‪ .8‬إضافة حواشي‬
‫لمَّ ا ك انت األم اكن المحج وزة ع بر القوس ين المعقوص ين {} هي حق ول قابل ة لالس تبدال (أي‬
‫ً‬
‫فعلية) فيمكنك إضافة حاش ية (‪ )padding‬أو إض افة ف راغ ح ول العنص ر بزي ادة حجم‬
‫ليست قيمً ا‬
‫الحقل عبر معامالت إضافية‪ ،‬ق د تس تفيد من ه ذا األم ر عن دما تحت اج إلى تنظيم البيان ات بص ريً ا‪.‬‬
‫قاس ا بع دد المح ارف) بتحدي د ذاك الحجم بع د النقط تين‬
‫بحجم‬
‫يمكنن ا إض افة حق ٍل‬
‫ٍ‬
‫معين (مُ ً‬
‫َّ‬
‫الرأسيتين ‪ :‬كما في المثال اآلتي‪:‬‬
‫‪162‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫))"‪print("Sammy has {0:4} red {1:16}!".format(5, "balloons‬‬
‫الناتج‪:‬‬
‫!‬
‫‪5 red balloons‬‬
‫‪Sammy has‬‬
‫ً‬
‫محرف ا‬
‫أعطين ا في المث ال الس ابق حقاًل بحجم ‪ 4‬مح ارف للع دد ‪ ،5‬وأعطين ا حقاًل بحجم ‪16‬‬
‫بيا)‪ .‬وكم ا رأين ا من ن اتج المث ال الس ابق‪ ،‬يتم‬
‫للسلسلة النصية ‪( balloons‬ألنه ا سلس لة طويل ة نس ً‬
‫افتراضيا إلى اليسار واألعداد إلى اليمين‪ ،‬يمكن ك أن ُتغيِّ ر من ه ذا بوض ع‬
‫محاذاة السالسل النصية‬
‫ً‬
‫رم ز خ اص للمح اذاة بع د النقط تين الرأس يتين مباش ً‬
‫رة‪ .‬إذ س يؤدي الرم ز > إلى مح اذاة النص إلى‬
‫ِّ‬
‫فسيوس ط النص في الحق ل‪ ،‬والرم ز < س يؤدي إلى محاذات ه إلى اليمين‪.‬‬
‫يس ار الحق ل‪ ،‬أم ا الرم ز ^‬
‫ِّ‬
‫ونوسط السلسلة النصية‪:‬‬
‫لنجعل محاذاة العدد إلى اليسار‬
‫))"‪print("Sammy has {0:<4} red {1:^16}!".format(5, "balloons‬‬
‫الناتج‪:‬‬
‫!‬
‫‪balloons‬‬
‫‪red‬‬
‫‪Sammy has 5‬‬
‫أن مح اذاة الع دد ‪ 5‬إلى اليس ار‪ ،‬مم ا يعطي مس احة فارغ ًة في الحق ل قب ل‬
‫نالح ظ اآلن َّ‬
‫الكلمة ‪ ،red‬وستظهر السلس لة النص ية ‪ balloons‬في منتص ف الحق ل وتوج د مس افة فارغ ة على‬
‫يمينه ا ويس ارها‪ .‬عن دما ُن ِّ‬
‫نس ق الحق ل لنجعل ه أك بر من حجم ه الط بيعي فس تمأل ب ايثون الحق ل‬
‫رف آخ ر بوض عه مباش ً‬
‫افتراض ًيا بالفراغ ات‪ ،‬إال َّ‬
‫رة بع د‬
‫أنن ا نس تطيع تغي ير مح رف الملء إلى مح ٍ‬
‫النقطتين الرأسيتين‪:‬‬
‫))"‪print("{:*^20s}".format("Sammy‬‬
‫الناتج‪:‬‬
‫‪163‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫********‪*******Sammy‬‬
‫ستض ع ب ايثون السلس لة النص ية المُ م رَّ رة إلى الدال ة )(‪ str.format‬ذات الفه رس ‪ 0‬مك ان‬
‫القوس ين المعقوص ين َّ‬
‫ألنن ا لم نطلب منه ا عكس ذل ك‪ ،‬ومن ثم سنض ع النقط تين الرأس يتين ثم‬
‫س ُن ِّ‬
‫ِّ‬
‫سنوسط السلسلة النصية عبر‬
‫حدد أننا سنستعمل المحرف * بداًل من الفراغات لملء الحقل‪ ،‬ثم‬
‫أن‬
‫أن حجم الحق ل ه و ‪ 20‬مح رف‪ ،‬ومُ ش يرين في نفس ال وقت إلى َّ‬
‫اس تعمال الرم ز ^ مُ ح ِّددين َّ‬
‫ٌ‬
‫ي ع بر وض ع الرم ز ‪ .s‬يمكنن ا اس تخدام ه ذه المع امالت م ع المع امالت ال تي‬
‫الحق ل ه و حق ل نص ٌ‬
‫استخدمناها وشرحناها في األقسام السابقة‪:‬‬
‫‪print("Sammy ate {0:5.0f} percent of a‬‬
‫))‪pizza!".format(75.765367‬‬
‫الناتج‪:‬‬
‫!‪76 percent of a pizza‬‬
‫‪Sammy ate‬‬
‫ِّ‬
‫حد دنا داخل القوسين المعقوصين رقم فهرس القيمة العددية ثم وضعنا النقطتين الرأسيتين‬
‫ثم اخترن ا حجم الحق ل ثم وض عنا نقط ًة‪ .‬لنض بط ع دد المن ازل العش رية الظ اهرة‪ ،‬ثم نخت ار ن وع‬
‫الحقل عبر رمز التحويل ‪.f‬‬
‫‪ .9‬استخدام المتغيرات‬
‫مرَّ رنا منذ بداية هذا الفصل وإلى اآلن األعداد والسالسل النص ية إلى الدال ة )(‪str.format‬‬
‫ً‬
‫ً‬
‫أيضا‪ ،‬وذلك بنفس اآللية المعتادة‪:‬‬
‫مباشرة‪ ،‬لكنَّنا نستطيع تمرير المتغيرات‬
‫‪nBalloons = 8‬‬
‫))‪print("Sammy has {} balloons today!".format(nBalloons‬‬
‫‪164‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مدخل إلى تنسيق النصوص‬
‫الناتج‪:‬‬
‫!‪Sammy has 8 balloons today‬‬
‫ً‬
‫أيضا استخدام المتغيِّ رات لتخ زين السلس لة النص ية األص لية باإلض افة إلى القيم ال تي‬
‫يمكننا‬
‫ُ‬
‫ستمرَّ ر إلى الدالة‪:‬‬
‫"!‪sammy = "Sammy has {} balloons today‬‬
‫‪nBalloons = 8‬‬
‫))‪print(sammy.format(nBalloons‬‬
‫الناتج‪:‬‬
‫!‪Sammy has 8 balloons today‬‬
‫ستس ِّهل المتغ يرات من التعام ل م ع تعب يرات التنس يق ُ‬
‫ُ‬
‫وت ِّ‬
‫بس ط عملي ة إس ناد م دخالت‬
‫نس ً‬
‫قة في السلسلة النصية النهائية‪.‬‬
‫المستخدم وإظهارها مُ َّ‬
‫‪ .10‬خالصة الفصل‬
‫ش رحنا في ه ذا الفص ل ع ِّدة طرائ ق لتنس يق النص وص والسالس ل النص ية في ب ايثون ‪3‬؛‬
‫ظه ر السالس ل النص ية كم ا نري د ع بر اس تخدامنا لمح ارف الته ريب أو السالس ل‬
‫وعرفن ا كي ف ُن ِ‬
‫النصية الخام والمُ ِّ‬
‫نسقات‪ ،‬لكي يستفيد المستخدم من النص الناتج ويقرأه بسهولة‪.‬‬
‫‪165‬‬
‫|‬
‫▲‬
‫‪9‬‬
‫العمليات الحسابية‬
‫‪166‬‬
‫|‬
‫▲‬
‫العمليات الحسابية‬
‫البرمجة بلغة بايثون‬
‫ٌ‬
‫شائعة ج ًدا في البرمجة‪ ،‬إذ ُتستخدم لتمثيل مختلف القيم‪ ،‬مثل أبعاد حجم الشاش ة‪،‬‬
‫األعداد‬
‫والمواقع الجغرافية‪ ،‬والمبالغ المالية‪ ،‬ومقدار الوقت الذي مر منذ بداية فيديو‪ ،‬واأللوان وغير ذلك‪.‬‬
‫تع د الق درة على تنفي ذ العملي ات الرياض ية بفعالي ة في البرمج ة مه ارة مهم ة‪َّ ،‬‬
‫ألنك األع داد‬
‫س تكون في متن اول األي دي دومً ا‪ .‬الفهم الجي د للرياض يات يمكن أن يس اعدك على أن تص بح‬
‫أنه ليس ش ً‬
‫مبرمج ا أفض ل‪ ،‬إال َّ‬
‫ً‬
‫رطا أساس ًيا‪ .‬فالرياض يات أداة لتحقي ق م ا ت رغب في تحقيق ه‪،‬‬
‫وطريقة لتحسين آلية التنفيذ‪.‬‬
‫س نعمل م ع أك ثر ن وعي البيان ات اس تخدامً ا في ب ايثون‪ ،‬وهم ا األع داد الص حيحة‬
‫واألعداد العشرية‪:‬‬
‫•‬
‫األعداد الصحيحة هي أعداد كاملة يمكن أن تكون موجبة أو سالبة أو معدومة مثل‬
‫(‪.)... ،1 ، 0 ، 1- ،...‬‬
‫•‬
‫األع داد العش رية هي أع داد حقيقي ة تحت وي على فاص لة عش رية (كم ا في ‪9.0‬‬
‫أو ‪.)-2.25‬‬
‫س نلقي في ه ذا الفص ل نظ ً‬
‫رة على العوام ل (‪ )operators‬ال تي يمكن اس تخدامها م ع أن واع‬
‫البيانات العددية في بايثون‪.‬‬
‫‪ .1‬العامالت‬
‫عملية حس ابية‪ ،‬إذ ج اءت تس مية عام ل من عملي ة‪،‬‬
‫العامل (‪ )operator‬هو رمز أو دالة تمث ل‬
‫َّ‬
‫عملية‪ .‬على س بيل المث ال‪ ،‬في الرياض يات‪ ،‬عالم ة الجم ع أو ‪ +‬هي العام ل‬
‫أي العام ل ال ذي يج ري‬
‫َّ‬
‫الذي يجري عملية الجمع‪.‬‬
‫‪167‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫في ب ايثون‪ ،‬س نرى بعض الع امالت المألوف ة‪ ،‬وال تي اس ُتعيرَ ت من الرياض يات‪ ،‬لكن هن اك‬
‫عامالت أخرى خاصة بمجال البرمجة‪.‬‬
‫الجدول التالي مرجعٌ سريعٌ للعامالت الحسابية في بايثون‪ .‬سنغطي جميع هذه العملي ات في‬
‫هذا الفصل‪.‬‬
‫العملية‬
‫الناتج‬
‫‪x + y‬‬
‫مجموع ‪ x‬و ‪y‬‬
‫‪x - y‬‬
‫طرح‪ x‬من ‪y‬‬
‫‪-x‬‬
‫عكس إشارة ‪x‬‬
‫‪+x‬‬
‫نفس قيمة ‪x‬‬
‫‪x * y‬‬
‫ضرب‪ x‬بـ ‪y‬‬
‫‪x / y‬‬
‫قسمة ‪ x‬على ‪y‬‬
‫‪x // y‬‬
‫حاصل القسمة التحتية لـ ‪ x‬على ‪y‬‬
‫‪x % y‬‬
‫باقي قسمة ‪ x‬على ‪y‬‬
‫‪x ** y‬‬
‫‪ x‬أس ‪y‬‬
‫ً‬
‫أيض ا عن ع امالت اإلس ناد المركب ة (‪ ،)compound assignment operators‬بم ا‬
‫س نتحدث‬
‫في ذلك =‪ +‬و =*‪ ،‬التي تجمع عاماًل‬
‫حسابيا مع العامل =‪.‬‬
‫ً‬
‫‪168‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪ .2‬الجمع والطرح‬
‫في ب ايثون‪ ،‬يعم ل مع امال الجم ع والط رح مث ل م ا ه و مع روف في الرياض يات‪ .‬في الواق ع‪،‬‬
‫ً‬
‫يمكنك استخدام لغة بايثون ً‬
‫حاسبة‪.‬‬
‫آلة‬
‫بدءا من األعداد الصحيحة‪:‬‬
‫ً‬
‫لنلق نظرة على بعض األمثلة‪،‬‬
‫ِ‬
‫)‪print(1 + 5‬‬
‫والناتج‪:‬‬
‫‪6‬‬
‫ب داًل من تمري ر أع داد ص حيحة مباش رة إلى الدال ة ‪ ،print‬يمكنن ا تهيئ ة المتغ يرات‬
‫بأعداد صحيحة‪:‬‬
‫‪a = 88‬‬
‫‪b = 103‬‬
‫)‪print(a + b‬‬
‫وسينتج لنا‪:‬‬
‫‪191‬‬
‫ً‬
‫أيض ا)‪ ،‬ل ذلك يمكنن ا إض افة‬
‫األع داد الص حيحة يمكن أن تك ون موجب ة أو س البة (أو معدوم ة‬
‫عدد سالب إلى عدد موجب‪:‬‬
‫‪c = -36‬‬
‫‪d = 25‬‬
‫‪-11‬‬
‫‪#‬‬
‫)‪print(c + d‬‬
‫‪169‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫ً‬
‫مشابها مع األعداد العشرية‪:‬‬
‫الجمع سيكون‬
‫‪e = 5.5‬‬
‫‪f = 2.5‬‬
‫‪8.0‬‬
‫‪#‬‬
‫)‪print(e + f‬‬
‫إذا جمعنا عددين عشريين معً ا‪ ،‬ستعيد بايثون عد ًدا عشريًّ ا‪.‬‬
‫ص ياغة الط رح تش به ص ياغة الجم ع‪ ،‬م ا ع دا أن ك ستس تبدل بعام ل الط رح (‪)-‬‬
‫عامل الجمع (‪:)+‬‬
‫‪g = 75.67‬‬
‫‪h = 32‬‬
‫‪#‬‬
‫‪43.67‬‬
‫)‪print(g - h‬‬
‫ً‬
‫صحيحا من عدد عش ري‪ .‬س تعيد ب ايثون ع د ًدا عش ريًّ ا إذا ك ان أح د األع داد‬
‫هنا‪ ،‬طرحنا عد ًدا‬
‫المتضمنة في المعادلة عشريًّ ا‪.‬‬
‫‪ .3‬العمليات الحسابية األحادية‬
‫يتكون التعبير الرياضي األحادي ( ‪ )unary mathematical expression‬من مك ِّون أو عنص ر‬
‫واح د فق ط‪ ،‬ويمكن في ب ايثون اس تخدام العالم تين ‪ +‬و ‪ -‬بمفردهم ا ع بر قرنهم ا بقيم ة إلع ادة‬
‫القيمة نفسها (عبر العامل ‪ ،)+‬أو تغيير إشارة القيمة (عبر العامل ‪. )-‬‬
‫تشير عالمة الجمع ‪ -‬رغم َّ‬
‫أنها ال ُتستخدم كثيرًا ‪ -‬إلى هوية القيمة ( ‪،)identity of the value‬‬
‫أي تعيد القيمة نفسها‪ .‬يمكننا استخدام عالمة الجمع مع القيم الموجبة‪:‬‬
‫‪i = 3.3‬‬
‫‪3.3‬‬
‫‪#‬‬
‫)‪print(+i‬‬
‫‪170‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫ُ‬
‫فستعاد القيمة نفسها‪ ،‬وفي هذه الحالة ستكون‬
‫عندما نستخدم عالمة الجمع مع قيمة سالبة‪،‬‬
‫ً‬
‫أيضا‪:‬‬
‫قيمة سالبة‬
‫‪j = -19‬‬
‫‪-19‬‬
‫)‪print(+j‬‬
‫‪#‬‬
‫عالم ة الط رح‪ ،‬على خالف عالم ة الجم ع‪ ،‬تغيِّ ر إش ارة القيم ة‪ .‬ل ذلك‪ ،‬عن دما نض عها م ع قيم ة‬
‫موجبة‪ُ ،‬‬
‫ستعاد القيمة السالبة منها‪:‬‬
‫‪i = 3.3‬‬
‫‪-3.3‬‬
‫‪#‬‬
‫)‪print(-i‬‬
‫بالمقاب ل‪ ،‬عن دما نس تخدم عام ل الط رح األح ادي ( ‪ )minus sign unary operator‬م ع قيم ة‬
‫ُ‬
‫فستعاد القيمة الموجبة منها‪:‬‬
‫سالبة‪،‬‬
‫‪j = -19‬‬
‫‪# 19‬‬
‫)‪print(-j‬‬
‫ُ‬
‫ستع ِيد العمليتان الحسابيتان األحاديتان ‪ +‬و ‪ -‬إمَّ ا هوية القيمة المعطاة‪ ،‬أو القيمة المعاكس ة‬
‫في اإلشارة للقيمة المعطاة على التوالي‪.‬‬
‫‪ .4‬الضرب والقسمة‬
‫مث ل الجم ع والط رح‪ ،‬الض رب والقس مة في ب ايثون مش ابهان لم ا ه و مع روف في الرياض يات‪.‬‬
‫عالمة الضرب في بايثون هي *‪ ،‬وعالمة القسمة هي ‪./‬‬
‫فيما يلي مثال على ضرب عددين عشريين في بايثون‪:‬‬
‫‪k = 100.1‬‬
‫‪171‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪l = 10.1‬‬
‫‪1011.0099999999999‬‬
‫‪#‬‬
‫)‪print(k * l‬‬
‫عن دما ُتج رَ ى عملي ة القس مة في ب ايثون ‪ ،3‬فس يكون الع دد المُ ع اد دائمً ا عش ريًّ ا‪ ،‬ح تى ل و‬
‫استخدمت عددين صحيحين‪:‬‬
‫‪m = 80‬‬
‫‪n = 5‬‬
‫‪16.0‬‬
‫‪#‬‬
‫)‪print(m / n‬‬
‫هذا أحد االختالفات الرئيسية بين بايثون ‪ 2‬و بايثون ‪ .3‬اإلجابة في بايثون ‪ 3‬تك ون كس رية‪،‬‬
‫ُ‬
‫فستعاد القيمة ‪ .5.5‬أمَّ ا في بايثون ‪ ،2‬فحاصل التعبير‬
‫فعند استخدام ‪ /‬لتقسيم ‪ 11‬على ‪ 2‬مثاًل ‪،‬‬
‫‪ 11/2‬هو ‪.5‬‬
‫يُ ج ِري العامل ‪ /‬في بايثون ‪ 2‬قسمة عملية القسمة مع تقريب الن اتج إلى أص غر ع دد ص حيح‬
‫له (ه ذه العملي ة ت دعى القس مة التقريبي ة [‪ ،)]floor division‬إذ َّ‬
‫أنه إن ك ان حاص ل القس مة‬
‫يساوي ‪ ،x‬فسيكون ناتج عملية القس مة في ب ايثون ‪ 2‬أك بر ع دد من األع داد الص حيحة األص غر من‬
‫أو تس اوي ‪ .x‬إذا َّ‬
‫نفذت المث ال )‪ print(80 / 5‬أعاله في ب ايثون ‪ 2‬ب داًل من ب ايثون ‪ ،3‬فس يكون‬
‫الناتج هو ‪ ،16‬دون الجزء العشري‪.‬‬
‫في ب ايثون ‪ ،3‬يمكن ك اس تخدام العام ل ‪ //‬إلج راء القس مة التقريبي ة‪ .‬التعب ير ‪100 // 40‬‬
‫س يعيد القيم ة ‪ .2‬القس مة التحتي ة مفي دة في ح ال كنت تري د أن يك ون حاص ل القس مة‬
‫ً‬
‫صحيحا‪.‬‬
‫عد ًدا‬
‫‪172‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪ .5‬عامل باقي القسمة (‪)Modulo‬‬
‫العام ل ‪ %‬ه و ب اقي القس مة (‪ ،)modulo‬وال ذي يُ رج ع ب اقي عملي ة القس مة‪ .‬ه ذا مفي د للعث ور‬
‫على األعداد التي هي مضاعفات لنفس العدد‪ .‬المثال التالي يوضح كيفية استخدام عامل الباقي‪:‬‬
‫‪o = 85‬‬
‫‪p = 15‬‬
‫‪#‬‬
‫‪10‬‬
‫)‪print(o % p‬‬
‫ألن عام ل‬
‫حاص ل قس مة ‪ 85‬على ‪ 15‬ه و ‪ ،5‬والب اقي ‪ .10‬القيم ة ‪ 10‬هي ال تي س ُتعاد هن ا َّ‬
‫الباقي يعيد باقي عملية القسمة‪.‬‬
‫فسيعاد عدد عشري‪:‬‬
‫إذا استخدمنا عددين عشريين مع عامل الباقي‪،‬‬
‫ُ‬
‫‪q = 36.0‬‬
‫‪r = 6.0‬‬
‫‪0.0‬‬
‫‪#‬‬
‫)‪print(o % p‬‬
‫باق‪ ،‬لذلك تعاد القيمة ‪.0.0‬‬
‫في حال قسمة ‪ 36.0‬على ‪ ،6.0‬فلن يكون هناك ٍ‬
‫‪ .6‬القوة (‪)Power‬‬
‫ً‬
‫أحيانا «األس») في بايثون لرفع الع دد األيس ر لق وة األس‬
‫يُ ستخدم عامل القوة ** (يقال له‬
‫للع دد األيمن‪ .‬وه ذا يع ني أن ه في التعب ير ‪ ،5 ** 3‬الع دد ‪ 5‬س ُي َ‬
‫رفع إلى الق وة ‪ .3‬في الرياض يات‪،‬‬
‫غالبا ما نرى ه ذا التعب ير يُ كتب على الش كل ‪ ،5³‬إذ يُ ض رب الع دد ‪ 5‬في نفس ه ‪ 3‬م رات‪ .‬في ب ايثون‪،‬‬
‫ً‬
‫التعبيران ‪ 5 ** 3‬و ‪ 5 * 5 * 5‬سيعطيان النتيجة نفسها‪.‬‬
‫سنستخدم في المثال التالي المتغيرات‪:‬‬
‫‪173‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪s = 52.25‬‬
‫‪t = 7‬‬
‫‪1063173305051.292‬‬
‫)‪print(s ** t‬‬
‫‪#‬‬
‫األس ** سينتج عنه عدد عشري كبير‪.‬‬
‫رفع العدد العشري ‪ 52.25‬إلى القوة ‪ 7‬عبر عامل‬
‫ّ‬
‫‪ .7‬أسبقية العمليات الحسابية‬
‫قيم‬
‫أن المع امالت س ُت َّ‬
‫في بايثون‪ ،‬كما هو الح ال في الرياض يات‪ ،‬علين ا أن نض ع في حس اباتنا َّ‬
‫ً‬
‫وفقا لنظام األسبقية‪ ،‬وليس من اليسار إلى اليمين‪ ،‬أو من اليمين إلى اليسار‪.‬‬
‫إذا نظرنا إلى التعبير التالي‪:‬‬
‫‪u = 10 + 10 * 5‬‬
‫قد نقرأه من اليس ار إلى اليمين‪ ،‬ولكن ت َّ‬
‫أن عملي ة الض رب س ُتجرَ ى أواًل ‪ ،‬ل ذا إن اس تدعينا‬
‫ذكر َّ‬
‫)‪ ،print(u‬فسنحصل على القيمة التالية‪:‬‬
‫‪60‬‬
‫قيم أواًل ‪ ،‬وس ينتج عنه ا الع دد ‪ ،50‬ثم يض اف إليه ا الع دد ‪ 10‬لنحص ل‬
‫ألن ‪ 5 * 10‬س ُت َّ‬
‫ه ذا َّ‬
‫على ‪ 60‬في النهاية‪.‬‬
‫إذا أردنا بداًل من ذلك إضافة القيمة ‪ 10‬إلى ‪ ،10‬ثم ضرب المجموع في ‪ ،5‬فيمكننا استخدام‬
‫األقواس كما نفعل في الرياضيات تمامً ا‪:‬‬
‫‪u = (10 + 10) * 5‬‬
‫‪100‬‬
‫‪#‬‬
‫)‪print(u‬‬
‫‪174‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫إحدى الطرق البسيطة لتذكر األسبقيات هي حفظ البيتين التاليين لتذكر أوائل كلماتهما‪:‬‬
‫ً‬
‫ً‬
‫طريقا‬
‫ضيقا ‪ ...‬قم جد‬
‫قم أبعد‬
‫األسبقية‬
‫العملية‬
‫الحرف‬
‫‪1‬‬
‫القوس‬
‫قم‬
‫‪2‬‬
‫األس‬
‫أبعد‬
‫‪3‬‬
‫الضرب‬
‫ً‬
‫ضيقا‬
‫‪4‬‬
‫القسمة‬
‫قم‬
‫‪5‬‬
‫الجمع‬
‫جد‬
‫‪6‬‬
‫الطرح‬
‫ً‬
‫طريقا‬
‫‪ .8‬عامل اإلسناد (‪)Assignment Operators‬‬
‫أكثر عامل اإلسناد استخدامً ا هو إشارة التساوي =‪ .‬يُ سنِد عامل اإلسناد (أو عامل التعيين) =‬
‫القيم ة الموج ودة على يمين ه إلى المتغ ير الموض وع على يس اره‪ .‬على س بيل المث ال‪ُ ،‬تس نِد‬
‫التعليمة ‪ v = 23‬العدد الصحيح ‪ 23‬للمتغير ‪.v‬‬
‫من الشائع استخدام عامالت اإلس ناد المركب ة ال تي تج ري عملي ة رياض ية على قيم ة المتغ ير‪،‬‬
‫ثم ُتسنِد القيمة الجديدة الناتجة إلى ذلك المتغير‪ .‬تجمع عوامل اإلسناد المركبة بين عامل رياضي‬
‫والعام ل =؛ ففي ح ال الجم ع‪ ،‬نس تخدم ‪ +‬م ع = للحص ول على عام ل اإلس ناد الم ركب =‪ .+‬لنطبِّ ق‬
‫ذلك في مثال عملي‪:‬‬
‫‪175‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪w = 5‬‬
‫‪w += 1‬‬
‫‪6‬‬
‫‪#‬‬
‫)‪print(w‬‬
‫أوالً‪ُ ،‬نس نِد القيم ة ‪ 5‬إلى المتغ ير ‪ ،w‬ثم نس تخدم معام ل اإلس ناد الم ركب =‪ +‬إلض افة الع دد‬
‫الصحيح إلى قيمة المتغير األيسر‪ ،‬ثم ُنسنِد النتيجة إلى المتغير ‪.w‬‬
‫ُتس تخدم مع امالت اإلس ناد المركب ة اس تخدامً ا متك ررًا م ع حلق ات ‪ for‬التكرارية‪ ،‬وال تي‬
‫ستستخدمها عندما تريد تكرار عمليةٍ عدة مرات‪:‬‬
‫‪for x in range (0, 7):‬‬
‫‪x *= 2‬‬
‫)‪print(x‬‬
‫والناتج سيكون‪:‬‬
‫‪0‬‬
‫‪2‬‬
‫‪4‬‬
‫‪6‬‬
‫‪8‬‬
‫‪10‬‬
‫‪12‬‬
‫تمكن ا باس تخدام الحلق ة ‪ for‬من أتمت ة العملي ة =* ال تي تض رب قيم ة المتغ ير ‪ w‬بالع دد ‪ ،2‬ثم‬
‫ُتسنِد النتيجة إلى المتغير ‪ w‬ألجل استخدامها في التكرار التالي من الحلقة‪.‬‬
‫ل دى ب ايثون معام ل إس ناد م ركب مقاب ل لك ل من المع امالت الحس ابية ال تي تطرقن ا ً‬
‫آنف ا‬
‫إليها وهي‪:‬‬
‫‪176‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫إضافة القيمة ثم إسنادها ‪#‬‬
‫‪y += 1‬‬
‫طرح القيمة ثم إسنادها ‪#‬‬
‫‪y -= 1‬‬
‫ضرب القيمة ثم إسنادها ‪#‬‬
‫‪y *= 2‬‬
‫تقسيم القيمة ثم إسنادها ‪#‬‬
‫‪y /= 3‬‬
‫تقسيم سفلي القيمة ثم إسنادها ‪#‬‬
‫‪y // = 5‬‬
‫تنفيذ عامل األس على القيمة ثم إسنادها ‪#‬‬
‫‪y **= 2‬‬
‫إعادة باقي قسمة القيمة ثم إسناده ‪#‬‬
‫‪y %= 3‬‬
‫يمكن أن يكون عامل اإلسناد المركب مفي ًدا عندما تحتاج إلى الزيادة أو اإلنق اص الت دريجي‪،‬‬
‫أو عندما تحتاج إلى أتمتة عمليات معينة في برنامجك‪.‬‬
‫‪ .9‬إجراء العمليات الرياضية عبر الدوال‬
‫بع د أن تعرفن ا كيفي ة إج راء العملي ات الرياض ية ع بر العوام ل (‪ ،)opreators‬سنس تعرض في‬
‫هذا القسم بعض الدوال الرياضية المُ ضمَّ نة ال تي يمكن اس تخدامها م ع أن واع البيان ات العددي ة في‬
‫ب ايثون ‪ .3‬فتتض مّ ن ب ايثون ‪ 3‬العدي د من ال دوال ال تي يمكن ك اس تخدامها بس هولة في أي برن امج‪.‬‬
‫ت تيح ل ك بعض تل ك ال دوال تحوي ل أن واع البيان ات‪ ،‬والبعض اآلخ ر خ اص بن وع معين‪ ،‬مث ل‬
‫السالسل النصية‪.‬‬
‫سنلقي نظرة على الدوال التالية‪:‬‬
‫•‬
‫)(‪ :abs‬للحصول على القيمة المطلقة‬
‫•‬
‫)(‪ :divmod‬للحصول على الحاصل والباقي في وقت واحد‬
‫•‬
‫)(‪ :pow‬لرفع عدد لقوة معينة‬
‫•‬
‫)(‪ :round‬لتقريب عدد بمنازل عشرية محددة‬
‫•‬
‫قابل للتكرار (‪)iterable‬‬
‫)(‪ :sum‬لحساب مجموع العناصر في كائن‬
‫ٍ‬
‫‪177‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫فهم ه ذه ال دوال س يمنحك مرون ة أك بر في التعام ل م ع البيان ات العددي ة‪ ،‬ويس اعدك على‬
‫اتخاذ قرارات مدروسة عند تحديد العوامل والدوال التي عليك استخدامها‪.‬‬
‫ا‪ .‬القيمة المطلقة‬
‫تعي د الدال ة المض مّ نة )(‪ abs‬القيم ة المطلق ة للع دد ال ذي يُ م رر إليه ا‪ .‬في الرياض يات‪ ،‬تش ير‬
‫القيمة المطلقة إلى العدد نفسه إن كانت القيمة موجبة‪ ،‬أو القيمة المعاكسة إن كانت القيمة سالبة‪.‬‬
‫مثاًل ‪ ،‬القيمة المطلقة للعدد ‪ 15‬هي ‪ ،15‬والقيمة المطلقة للعدد ‪ -74‬هي ‪ ،74‬والقيمة المطلق ة‬
‫للعدد ‪ 0‬هي ‪.0‬‬
‫القيم ة المطلق ة مفه وم مهم في الحس اب والتحلي ل‪ ،‬كم ا َّ‬
‫أنه ا مفي دة ك ذلك في المواق ف‬
‫اليومي ة‪ ،‬مث ل حس اب المس افة المقطوع ة‪ .‬على س بيل المث ال‪ ،‬إذا كنت تح اول الوص ول إلى مك ان‬
‫إن حس بت ع دد الفراس خ ال تي‬
‫يبعد ‪ 58‬مياًل ‪ ،‬ولكنَّك تجاوزت ذلك المك ان‪ ،‬وس افرت ‪ 93‬فرس ًخا‪ .‬ف َّ‬
‫ينبغي أن تقطعها اآلن للوصول إلى الوجهة المقصودة‪ ،‬فسوف ينتهي بك المطاف بعدد سالب‪ ،‬لكن‬
‫سالبا من الفراسخ!‬
‫ال يمكنك السفر عد ًدا‬
‫ً‬
‫سنستخدم الدالة )(‪ abs‬لحل هذه المشكلة‪:‬‬
‫منطلق ‪#‬‬
‫عدد الفراسخ التي تفصلنا عن الوجهة انطالقًا من الُ‬
‫‪miles_from_origin = 58‬‬
‫ُنطَلق إلى الوجهة ‪#‬‬
‫الفراسخ المقطوعة من الم‬
‫‪miles_travelled = 93‬‬
‫حساب عدد الفراسخ من الموقع الحالي ‪#‬‬
‫‪miles_to_go = miles_from_origin - miles_travelled‬‬
‫طباعة عدد الفراسخ المتبقية بعدد سالب ‪#‬‬
‫‪178‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫)‪print(miles_to_go‬‬
‫حساب القيمة المطلقة للعدد السالب ‪#‬‬
‫))‪print(abs(miles_to_go‬‬
‫المخرجات ستكون‪:‬‬
‫‪-35‬‬
‫‪35‬‬
‫أن ‪miles_travelled‬‬
‫لوال استخدام الدالة )(‪ ،abs‬لحصلنا على ع دد س الب‪ ،‬أي ‪ .-35‬ورغم َّ‬
‫فإن الدالة )(‪ abs‬تحل إشكالية العدد السالب‪.‬‬
‫أصغر من ‪،miles_from_origin‬‬
‫َّ‬
‫عندما ِّ‬
‫ألن القيم ة المطلق ة دائمً ا تعي د‬
‫سالبا‪ ،‬ستعيد الدالة )(‪ abs‬ع د ًدا‬
‫نمرر لها عد ًدا‬
‫موجب ا‪َّ ،‬‬
‫ً‬
‫ً‬
‫أعدا ًدا موجبة أو معدومة‪.‬‬
‫موجبا‪ ،‬وكذلك الصفر‪:‬‬
‫في المثال التالي‪ ،‬سنمرر للدالة )(‪ abs‬عد ًدا‬
‫ً‬
‫‪#‬‬
‫))‪print(abs(89.9‬‬
‫‪89.9‬‬
‫‪# 0‬‬
‫))‪print(abs(0‬‬
‫ب‪ .‬العثور على الحاصل والباقي بدالة واحدة‬
‫القس مة التقريبي ة (‪ ،floor division‬ال تي ُتعي د حاص ل القس مة [‪ ]quotient‬م ع تقريب ه)‪،‬‬
‫ً‬
‫ارتباط ا‬
‫وقس مة الب اقي (‪ ،modulo division‬ال تي تعي د ب اقي القس مة [‪ ،)]remainder‬مرتبط ان‬
‫ً‬
‫وثيقا‪ ،‬وقد يكون من المفيد استخدام دالة تجمع بين العمليتين معً ا‪.‬‬
‫تجم ع الدال ة المض مَّ نة )(‪ divmod‬بين العملي تين‪ ،‬إذ تعي د أواًل حاص ل عملي ة القس مة‬
‫التقريبية‪ ،‬ثم الباقي‪ .‬ينبغي تمرير عددين إلى الدالة )(‪ ،divmod‬على النحو التالي‪:‬‬
‫)‪divmod(a,b‬‬
‫‪179‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫تكافئ هذه الدالة العمليتين التاليتين‪:‬‬
‫‪a // b‬‬
‫‪a & b‬‬
‫لنفترض َّ‬
‫أننا كتبنا كتابًا يحتوي ‪ 80‬ألف كلمة‪ .‬يري د الناش ر أن تحت وي ك ل ص فحة من الكت اب‬
‫ما بين ‪ 300‬و ‪ 250‬كلمة‪ ،‬ونود أن نعرف ع دد الص فحات ال تي ستش كل الكت اب بحس ب ع دد كلم ات‬
‫الص فحة ال ذي اخترن اه‪ .‬باس تخدام الدال ة )(‪ ،divmod‬يمكنن ا أن نع رف على الف ور ع دد الص فحات‬
‫في الكتاب‪ ،‬وعدد الكلمات المتبقية التي ُ‬
‫ستنقل إلى صفحة إضافية‪.‬‬
‫كم عدد الكلمات في كتابنا ‪#‬‬
‫‪words = 80000‬‬
‫الخيار ‪ :A‬عدد كلمات الصفحة هو ‪# 300‬‬
‫‪per_page_A = 300‬‬
‫الخيار ‪ :B‬عدد كلمات الصفحة هو ‪# 250‬‬
‫‪per_page_B = 250‬‬
‫حساب الخيار ‪print(divmod(words,per_page_A)) # A‬‬
‫حساب الخيار ‪print(divmod(words,per_page_B)) # B‬‬
‫وسينتج عن هذه الشيفرة‪:‬‬
‫)‪(266, 200‬‬
‫)‪(320, 0‬‬
‫في الخيار ‪ ،A‬سنحص ل على ‪ 266‬ص فحة مليئ ة بالكلم ات‪ ،‬و ‪ 200‬كلم ة متبقي ة (ثلث ا ص فحة)‪،‬‬
‫والمجموع هو ‪ 267‬صفحة‪ ،‬وفي الخيار ‪ ،B‬سنحص ل على كت اب من ‪ 320‬ص فحة‪ .‬إن أردن ا الحف اظ‬
‫‪180‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫على البيئة‪ ،‬فالخيار ‪ A‬قد يكون أفضل‪ ،‬ولكن إذا أردن ا تص ميمً ا ج ذابًا‪ ،‬أو الكتاب ة بحجم خ ط كب ير‪،‬‬
‫فقد نختار الخيار "‪."B‬‬
‫تقبل الدالة )(‪ divmod‬األع داد الص حيحة واألع داد العش رية‪ ،‬في المث ال الت الي س ُن ِّ‬
‫مرر ع د ًدا‬
‫عشريًّ ا إلى الدالة )(‪:divmod‬‬
‫‪a = 985.5‬‬
‫‪b = 115.25‬‬
‫)‪(8.0, 63.5‬‬
‫‪#‬‬
‫))‪print(divmod(a,b‬‬
‫في هذا المثال‪ ،‬العدد ‪ 8.0‬ه و حاص ل القس مة التحتي ة للع دد ‪ 985.5‬مقس ومً ا على ‪،115.25‬‬
‫و ‪ 63.5‬هو الباقي‪.‬‬
‫ُّ‬
‫للتحقق من نتيجة )(‪:divmod‬‬
‫يمكنك استخدام عامل القسمة التحتية ‪ //‬و عامل الباقي ‪%‬‬
‫‪8.0‬‬
‫‪#‬‬
‫‪# 63.5‬‬
‫)‪print(a//b‬‬
‫)‪print(a%b‬‬
‫ج‪ .‬القوة (‪)Power‬‬
‫في بايثون‪ ،‬يمكنك استخدام عامل القوة ** (أو األس) لرفع عدد إلى ق وة معين ة‪ ،‬أو يمكن ك‬
‫استخدام الدالة )(‪ pow‬المضمَّ نة التي تأخذ عددين وتجري العملية نفسها‪.‬‬
‫ً‬
‫كيفية عمل الدالة )(‪ ،pow‬لنقل َّ‬
‫أبحاثا على البكتيريا‪ ،‬ونريد أن نق َّدر ع دد‬
‫أننا نجري‬
‫لتوضيح‬
‫َّ‬
‫البكتيريا التي سنحصل عليها في نهاية اليوم إذا بدأنا ببكتيريا واحدة‪.‬‬
‫أن البكتيريا التي نعمل عليها تتضاعف في كل ساعة‪ ،‬لذلك النتيجة النهائية ستكون‬
‫لنفترض َّ‬
‫‪ 2‬قوة العدد الكلي لعدد الساعات التي مرت (‪ 24‬في حالتنا)‪.‬‬
‫‪181‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫‪hours = 24‬‬
‫)‪total_bacteria = pow(2,hours‬‬
‫‪# 16777216‬‬
‫)‪print(total_bacteria‬‬
‫لق د مرَّ رن ا ع ددين ص حيحين للدال ة )(‪ ،pow‬والنتيج ة ال تي حص لنا عليه ا‪ ،‬وال تي ِّ‬
‫تمثل ع دد‬
‫البكتيريا بحلول نهاية اليوم‪ ،‬هي أكثر من ‪ 16‬مليون بكتيريا‪.‬‬
‫أس ‪ "3‬بش كل ع ام على بالش كل ‪ 3³‬وال تي تك افئ ‪،3 × 3 × 3‬‬
‫في الرياض يات‪ ،‬نكتب "‪ّ 3‬‬
‫أي ‪ .27‬ولحس اب ‪ 3³‬في ب ايثون‪ ،‬نكتب )‪ ،pow(3,3‬إذ تقب ل الدال ة )(‪ pow‬األع داد الص حيحة‬
‫ِّ‬
‫وتوفر بدياًل لعامل األس **‪.‬‬
‫واألعداد العشرية‪،‬‬
‫د‪ .‬تقريب األعداد‬
‫تقريب األعداد ( ‪ )Rounding Numbers‬ضروري عند العمل مع األعداد العشرية التي تحتوي‬
‫على الكث ير من المن ازل (األج زاء) العش رية‪ .‬تقب ل الدال ة المض منة )(‪ round‬ع ددين‪ :‬أح دها ِّ‬
‫يمثل‬
‫ِّ‬
‫يحدد عدد المنازل العشرية المراد اإلبقاء عليها (أي قيمة التقريب)‪.‬‬
‫العدد المراد تقريبه واآلخر‬
‫سنستخدم هذه الدالة لتقريب عدد عشري له أكثر من ‪ 10‬منازل عشرية والحص ول على ع دد‬
‫بأربعة منازل عشرية فقط‪:‬‬
‫‪i = 17.34989436516001‬‬
‫‪# 17.3499‬‬
‫))‪print(round(i,4‬‬
‫في المث ال أعاله‪ ،‬تم تق ريب الع دد ‪ 17.34989436516001‬إلى ‪َّ 17.3499‬‬
‫ألنن ا ح َّددنا‬
‫عدد المنازل العشرية التي ينبغي االقتصار عليها بأربعة‪.‬‬
‫‪182‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫ً‬
‫أن الدال ة )(‪ round‬تق ِّرب األع داد إلى األعلى‪ ،‬ل ذا ب داًل من إع ادة ‪،17.3498‬‬
‫الح ظ‬
‫أيض ا َّ‬
‫ألن ال رقم ال ذي يلي الم نزل العش ري ‪ 8‬ه و ال رقم ‪ .9‬وس يقرَّ ب أي ع دد‬
‫فق د أع ادت ‪َّ ،17.3499‬‬
‫متبوع بالعدد ‪ 5‬أو أكبر إلى العدد الصحيح التالي‪.‬‬
‫المالية؛ فال يمكنن ا‬
‫في الحياة اليومي ة‪ُ ،‬نق ِّرب األع داد ألس باب كث يرة‪ ،‬وخاص ة في التع امالت‬
‫َّ‬
‫تقسيم فلس واحد بالتساوي بين عدة أصدقاء مثال‪.‬‬
‫ِّ‬
‫نحدد في ه قيم‬
‫س نكتب في المث ال الت الي برنامج ا بس يطا يمكن ه حس اب البقش يش‪ ،‬إذ س‬
‫المتغ يرات‪ ،‬ولكن يمكن ك إع ادة كتاب ة البرن امج لجع ل المس تخدمين ي دخلون القيم بأنفس هم‪ .‬في‬
‫ه ذا المث ال‪ ،‬ذهب ‪ 3‬أص دقاء إلى مطعم‪ ،‬وأرادوا تقس يم الف اتورة‪ ،‬وال تي تبل غ ‪ 87.93‬دوال ًرا‬
‫بالتساوي‪ ،‬باإلضافة إلى إكرامية (بقشيش) بنسبة ‪:٪20‬‬
‫إجمالي الفاتورة ‪#‬‬
‫‪bill = 87.93‬‬
‫بقشيش ‪# ٪ 20‬‬
‫‪tip = 0.2‬‬
‫عدد الناس الذين سيتشاركون الفاتورة ‪#‬‬
‫‪split = 3‬‬
‫حساب الفاتورة اإلجمالية ‪#‬‬
‫)‪total = bill + (bill * tip‬‬
‫حساب ما ينبغي أن يدفعه كل شخص ‪#‬‬
‫‪each_pay = total / split‬‬
‫ما ينبغي أن يدفعه كل شخص قبل التقريب ‪#‬‬
‫)‪print(each_pay‬‬
‫تقريب العدد فال يمكننا تقسيم الفلسات ‪#‬‬
‫))‪print(round(each_pay,2‬‬
‫والمخرجات ستكون‪:‬‬
‫‪35.172000000000004‬‬
‫‪35.17‬‬
‫‪183‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫في هذا البرنامج‪ ،‬نطلب أواًل إخراج العدد بعد حساب إجمالي الف اتورة واإلكرامي ات مقس ومً ا‬
‫على ‪ ،3‬النتيجة ستكون عد ًدا يتض مَّ ن الكث ير من المن ازل العش رية‪.35.172000000000004 :‬‬
‫ألن ه ذا الع دد ال ِّ‬
‫ً‬
‫واقعيا‪َّ ،‬‬
‫فإنن ا نس تخدم الدال ة )(‪ ،round‬ونق ِّرب المن ازل‬
‫مالي ا‬
‫مبلغ ا‬
‫يمثل‬
‫ًّ‬
‫نظ رًا َّ‬
‫ً‬
‫َّ‬
‫نتمكن من توفير ناتج يمكن لألصدقاء الثالثة أن يدفعوه‪.35.17 :‬‬
‫العشرية على ‪ ،2‬حتى‬
‫إذا كنت تفض ل التق ريب إلى ع دد بال من ازل عش رية‪ ،‬يمكن ك تمري ر ‪ 0‬كمعام ل ث ان إلى‬
‫الدالة )(‪:round‬‬
‫)‪round(345.9874590348545304636,0‬‬
‫القيمة الناتجة ستكون ‪.346.0‬‬
‫ً‬
‫أيضا تمرير األعداد الصحيحة إلى )(‪ round‬دون الخ وف من تلقي خط أ‪ ،‬وه ذا مفي د‬
‫يمكنك‬
‫ً‬
‫حيحا ب داًل من ع دد عش ري‪ .‬وفي ه ذه الحال ة‪ ،‬س ُيعاد‬
‫في ح ال تلقيت من المس تخدم ع د ًدا ص‬
‫عدد صحيح‪.‬‬
‫ه‪ .‬حساب المجموع‬
‫ُتس‬
‫تخ َدم الدال‬
‫ة )(‪ sum‬لحس‬
‫اب مج‬
‫اميع أن‬
‫واع البيان‬
‫َّ‬
‫المركب‬
‫ات العدديَّ ة‬
‫ة‬
‫(‪ ،)numeric compound data types‬بما في ذلك القوائم‪ ،‬والصفوف‪ ،‬والقواميس‪.‬‬
‫يمكننا تمرير قائمة إلى الدالة )(‪ sum‬لجمع كل عناصرها بالترتيب من اليسار إلى اليمين‪:‬‬
‫]‪some_floats = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9‬‬
‫‪49.5‬‬
‫‪#‬‬
‫))‪print(sum(some_floats‬‬
‫‪184‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات الحسابية‬
‫نفس النتيجة سنحصل عليها إن استخدمنا الصفوف والقواميس‪:‬‬
‫حساب مجموع األعداد في الصف ‪#‬‬
‫)))‪print(sum((8,16,64,512‬‬
‫حساب مجموع األعداد في القاموس ‪#‬‬
‫))}'‪print(sum({-10: 'x', -20: 'y', -30: 'z‬‬
‫المخرجات‪:‬‬
‫‪60‬‬
‫‪-60‬‬
‫سيضاف إلى المجموع الناتج‪:‬‬
‫يمكن أن تأخذ الدالة )(‪ sum‬وسيطين‪ ،‬الوسيط الثاني ُ‬
‫]‪some_floats = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9‬‬
‫‪# 50.0‬‬
‫‪# 0‬‬
‫))‪print(sum(some_floats, 0.5‬‬
‫))‪print(sum({-10: 'x', -20: 'y', -30: 'z'},60‬‬
‫القيمة االفتراضية للوسيط الثاني هي ‪.0‬‬
‫‪ .10‬خالصة الفصل‬
‫َّ‬
‫غطينا في هذا الفصل العديد من العوام ل وال دوال ال تي ستس تخدمها م ع األع داد الص حيحة‬
‫والعش رية إلج راء أهم العملي ات الرياض ية وال زال هنال ك الكث ير منه ا‪ ،‬فننص حك بزي ارة توثي ق‬
‫العملي ات العددي ة في ب ايثون وتوثي ق األن واع العددي ة في ب ايثون في موس وعة حس وب لمزي د‬
‫من التفاصيل‪.‬‬
‫‪185‬‬
‫|‬
‫▲‬
‫‪10‬‬
‫العمليات المنطقية‬
‫(البوليانية)‬
‫‪186‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫هن اك قيمت ان فق ط لن وع البيان ات المنطقية‪ ،‬وهم ا ‪ True‬و ‪ُ .False‬تس تخ َدم الحس ابات‬
‫المنطقية في البرمجة إلجراء الموازنات‪ ،‬والتحكم في مسار البرنامج‪.‬‬
‫ِّ‬
‫تمثل القيم المنطقي ة قيم الحقيق ة ( ‪ )truth values‬في علم المنط ق في الرياض يات‪ٌ ،‬‬
‫وتكتَب‬
‫القيمت ان ‪ True‬و ‪ False‬دائمً ا ب الحرفين الكب يرين ‪ T‬و ‪ F‬على الت والي‪ ،‬أل َّنهم ا قيمت ان خاص تان‬
‫المنطقية في ب ايثون‪ ،‬بم ا في ذل ك الموازن ة‬
‫في ب ايثون‪ .‬س نتعرف في ه ذا الفص ل على العملي ات‬
‫َّ‬
‫المنطقية‪ ،‬وجداول الحقيقة‪.‬‬
‫المنطقية‪ ،‬والعوامل‬
‫َّ‬
‫َّ‬
‫‪ .1‬عامل الموازنة‬
‫في البرمج ة‪ُ ،‬تس تخ َدم ع امالت الموازن ة ( ‪ )comparison operators‬للموازن ة بين القيم‪،‬‬
‫وتعي د إح دى القيم تين المنطق تين ‪ True‬و ‪ .False‬يوض ح الج دول أدن اه ع امالت‬
‫الموازنة المنطقية‪:‬‬
‫العامل‬
‫الشرح‬
‫==‬
‫يساوي‬
‫!=‬
‫يخالف‬
‫<‬
‫أصغر من‬
‫>‬
‫أكبر من‬
‫<=‬
‫أصغر من أو يساوي‬
‫>=‬
‫أكبر من أو يساوي‬
‫‪187‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫لفهم كيفية عمل هذه العامالت‪ ،‬سنستخدم المتغيرين التاليين‪:‬‬
‫‪x = 5‬‬
‫‪y = 8‬‬
‫في هذا المثال‪ ،‬لمَّ ا كان ‪ x‬يساوي ‪ ،5‬فهو أصغر من ‪ y‬ذي القيمة ‪.8‬‬
‫ِّ‬
‫سنجرب أحد الع امالت من الج دول أعاله‪.‬‬
‫باستخدام هذين المتغيرين والقيم المرتبطة بهما‪،‬‬
‫س نطلب من ب ايثون أن تطب ع ن اتج عملي ة الموازن ة‪ ،‬إمَّ ا ‪ True‬أو ‪ .False‬لتوض يح المث ال أك ثر‪،‬‬
‫سنطبع سلسلة نصية لتوضيح ما جرى تقييمه‪.‬‬
‫‪x = 5‬‬
‫‪y = 8‬‬
‫)‪print("x == y:", x == y‬‬
‫)‪print("x != y:", x != y‬‬
‫)‪print("x < y:", x < y‬‬
‫)‪print("x > y:", x > y‬‬
‫)‪print("x <= y:", x <= y‬‬
‫)‪print("x >= y:", x >= y‬‬
‫والمخرجات هي‪:‬‬
‫‪x == y: False‬‬
‫‪x != y: True‬‬
‫‪x < y: True‬‬
‫‪x > y: False‬‬
‫‪x <= y: True‬‬
‫‪x >= y: False‬‬
‫باتباع المنطق الرياضي‪ ،‬في كل من التعبيرات المذكورة أعاله‪ ،‬هذه نتيجة الموازنات‪:‬‬
‫•‬
‫‪( 5‬قيمة ‪ )x‬تساوي ‪( 8‬قيمة ‪)y‬؟ ‪ ،False‬خطأ‬
‫‪188‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫•‬
‫‪ 5‬تخالف ‪8‬؟ ‪ ،True‬صحيح‬
‫•‬
‫‪ 5‬أصغر من ‪8‬؟ ‪ ،True‬صحيح‬
‫•‬
‫‪ 5‬أكبر من ‪8‬؟ ‪ ،False‬خطأ‬
‫•‬
‫‪ 5‬أصغر من أو يساوي ‪8‬؟ ‪ ،True‬صحيح‬
‫•‬
‫‪ 5‬ليس أصغر من أو يساوي ‪8‬؟ ‪ ،False‬خطأ‬
‫رغم استخدامنا لألعداد الصحيحة هنا‪ ،‬إال َّ‬
‫أن ه بإمكاننا استبدال األعداد العشرية بها‪.‬‬
‫ً‬
‫أيضا استخدام السالسل النصية مع المعامالت المنطقية‪ .‬وهي حساسة لحالة األحرف‪،‬‬
‫يمكن‬
‫افيا للسالس ل النص ية‪ ،‬ويوض ح المث ال الت الي كيفي ة موازن ة‬
‫م ا لم تس تخدم تابعً ا إض‬
‫ً‬
‫السالسل النصية‪:‬‬
‫"‪Sammy = "Sammy‬‬
‫"‪sammy = "sammy‬‬
‫‪# Sammy == sammy:‬‬
‫)‪print("Sammy == sammy: ", Sammy == sammy‬‬
‫‪False‬‬
‫السلس لة "‪ "Sammy‬أعاله ال تس اوي السلس لة النص ية "‪َّ ،"sammy‬‬
‫ألنهم ا ليس تا متم اثلتين‬
‫تمامً ا؛ فإح داهما تب دأ بح رف كب ير ‪ ،S‬واألخ رى بح رف ص غير ‪ .s‬ولكن ل و أض فنا متغ يرًا آخ ر‬
‫قيمته "‪ ،"Sammy‬فستكونان متساويتين‪:‬‬
‫"‪Sammy = "Sammy‬‬
‫"‪sammy = "sammy‬‬
‫"‪also_Sammy = "Sammy‬‬
‫‪189‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫)‪print("Sammy == sammy: ", Sammy == sammy‬‬
‫‪False‬‬
‫‪# Sammy == sammy:‬‬
‫)‪print("Sammy == also_Sammy", Sammy == also_Sammy‬‬
‫‪True‬‬
‫‪# Sammy == also_Sammy:‬‬
‫ً‬
‫أيض ا اس تخدام ع امالت الموازن ة األخ رى‪ ،‬بم ا في ذل ك > و < لموازن ة سلس لتين‬
‫يمكن ك‬
‫نص يتين‪ .‬س توازن ب ايثون ه ذه السالس ل النص ية بحس ب ال ترتيب المعجمي في نظ ام‬
‫ً‬
‫أيضا تقييم القيم المنطقية باستخدام عامالت الموازنة‪:‬‬
‫محارف ‪ .ASCII‬ويمكنك‬
‫‪t = True‬‬
‫‪f = False‬‬
‫‪True‬‬
‫‪t != f:‬‬
‫‪#‬‬
‫)‪print("t != f: ", t != f‬‬
‫أن ‪ True‬ال تساوي ‪.False‬‬
‫تبيِّ ن الشيفرة البرمجية أعاله َّ‬
‫الحظ الفرق بين العاملين = و ==‪.‬‬
‫إسناد قيمة ‪ y‬إلى ‪# x‬‬
‫‪x = y‬‬
‫و ‪ x‬متساويين ‪#‬‬
‫‪x == y‬‬
‫تتحقق مما إذا كان ‪y‬‬
‫ِّ‬
‫يحدد قيم ة أح د المتغ يرين‪،‬‬
‫األول =‪ ،‬هو عام ل اإلس ناد (‪ ،)assignment operator‬وال ذي س‬
‫ِّ‬
‫يحدد م ا إذا ك انت‬
‫ويجعله ا مس اوية لقيم ة اآلخ ر‪ .‬الث اني ==‪ ،‬وه و عام ل الموازن ة ال ذي س‬
‫القيمتان متساويتين‪.‬‬
‫‪ .2‬العامالت المنطقية‬
‫هن اك ثالث ة ع امالت منطقي ة (‪ُ )Boolean operators‬تس تخدم لموازن ة القيم‪ .‬وتعي د إمَّ ا‬
‫‪ True‬أو ‪ .False‬ه ذه الع امالت هي‪( and ،‬و)‪ ،‬و ‪( or‬أو)‪ ،‬و ‪( not‬النفي)‪ ،‬وق د عرَّ فناه ا في‬
‫الجدول أدناه‪.‬‬
‫‪190‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫العامل‬
‫الشرح‬
‫الصياغة‬
‫‪and‬‬
‫إن كان كال التعبيرين صحيحين‬
‫‪x and y‬‬
‫‪True‬‬
‫إن كان أحد التعبيرين على األقل‬
‫‪or‬‬
‫‪x or y‬‬
‫ً‬
‫صحيحا ‪True‬‬
‫إن كان التعبير خطأ ‪True‬‬
‫‪not‬‬
‫‪not x‬‬
‫ع ً‬
‫ادة م ا ُتس تخ َدم الع امالت المنطقي ة لتق ييم م ا إذا ك ان تعب يران منطقي ان ص حيحين أم ال‪.‬‬
‫على سبيل المثال‪ ،‬يمكن استخدامها لتحديد ما إذا كان الط الب ق د نجح‪َّ ،‬‬
‫وأنه مُ س جل في الفص ل‪،‬‬
‫فسي َ‬
‫ضاف الطالب إلى سجل النظام‪ .‬مثال آخ ر ه و تحدي د م ا‬
‫وإذا كانت كلتا الحالتان صحيحتين‪،‬‬
‫ُ‬
‫إذا كان المستخدم عمياًل‬
‫ً‬
‫نشطا لمتجر إلكتروني استنا ًدا إلى ما إذا ك ان لدي ه رص يد في المتج ر‪ ،‬أو‬
‫َّ‬
‫أنه اشترى خالل األشهر الستة الماضية‪.‬‬
‫كيفية عمل العامالت المنطقية‪ ،‬دعنا نقيِّ م التعابير الثالث التالية‪:‬‬
‫لفهم‬
‫َّ‬
‫كال التعبيرين صحيحان ‪#‬‬
‫))‪print((9 > 7) and (2 < 4‬‬
‫أحد التعبيرين صحيح ‪#‬‬
‫))‪print((8 == 8) or (6 != 6‬‬
‫التعبير األصلي خطأ ‪#‬‬
‫))‪print(not(3 <= 1‬‬
‫والمخرجات هي‪:‬‬
‫‪True‬‬
‫‪True‬‬
‫‪True‬‬
‫‪191‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫في الحال ة األولى‪ ،print((9 > 7) and (2 < 4)) ،‬ينبغي أن يك ون كال التعب يرين‬
‫ألن المعامل ‪ and‬مُ ستخ َدم‪.‬‬
‫‪ 9 > 7‬و ‪ 2 < 4‬صحيحين لتكون النتيجة ‪َّ True‬‬
‫أن قيم ة ‪ُ 8 == 8‬قيِّ مت‬
‫في الحال ة الثاني ة‪ ،print((8 == 8) or (6 != 6)) ،‬بم ا َّ‬
‫يقيم إليه التعب ير ‪ .6 != 6‬لكن ل و اس تخدمنا العام ل ‪ٌ ،and‬‬
‫لقيِّ م التعب ير إلى‬
‫إلى ‪ ،True‬فال يهم ما َّ‬
‫القيمة ‪.False‬‬
‫في الحال ة الثالث ة‪ ،print(not(3 <= 1)) ،‬ينفي العام ل ‪ not‬القيم ة ‪ False‬ال تي تعي دها‬
‫ناتج العملية المنطقية ‪.1 =< 3‬‬
‫في المثال التالي‪ ،‬سنستبدل باألعداد العشرية أعدا ًدا صحيحة‪:‬‬
‫أحد التعبيرين خطأ ‪#‬‬
‫))‪print((-0.2 > 1.4) and (0.8 < 3.1‬‬
‫كال التعبيرين خطأ ‪#‬‬
‫))‪print((7.5 == 8.9) or (9.2 != 9.2‬‬
‫التعبير األصلي صحيح ‪#‬‬
‫))‪print(not(-5.7 <= 0.3‬‬
‫في المثال أعاله‪:‬‬
‫•‬
‫‪ :and‬يجب أن يكون واحد على األقل من التعبيرين خطأ ليعيد القيمة ‪،False‬‬
‫•‬
‫‪ :or‬يجب أن يكون كال التعبيرين خطأ لتعيد القيمة ‪،False‬‬
‫•‬
‫ً‬
‫صحيحا حتى يعيد القيمة ‪.False‬‬
‫‪ :not‬يجب أن يكون التعبير المرافق له‬
‫إذا لم تكن النت ائج أعاله واض حة‪ ،‬فس نعرض بعض ج داول الحقيق ة أدن اه لتفهم األم ر‬
‫فهمً ا أفضل‪.‬‬
‫أيضا كتابة عبارات مُ َّ‬
‫ً‬
‫ركبة باستخدام ‪ ،and‬و ‪ ،or‬و ‪:not‬‬
‫يمكنك‬
‫)))‪not((-0.2 > 1.4) and ((0.8 < 3.1) or (0.1 == 0.1‬‬
‫‪192‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫ألن كال‬
‫التعب ير ال داخلي‪ )0.1 == 0.1( or )3.1 < 0.8( :‬يعي د القيم ة ‪َّ ،True‬‬
‫َّ‬
‫محققان‪ ،‬أي يعيدان ‪.True‬‬
‫التعبيرين الرياضيين‬
‫اآلن‪ ،‬نأخذ القيمة المُ عادة ‪ True‬ونجمعها مع التعبير المنطقي التالي‪:‬‬
‫)‪(-0.2> 1.4) and (True‬‬
‫ألن التعب ير ‪1.4‬‬
‫ه ذا المث ال يعي د ‪َّ ،False‬‬
‫>‬
‫يقيم إلى القيم ة ‪،False‬‬
‫‪َّ -0.2‬‬
‫و )‪ (False) and (True‬ينتج عنه القيمة ‪.False‬‬
‫أخيرًا‪ ،‬يعيد التعبير الخارجي‪ not (False) :‬القيمة ‪ ،True‬وبالتالي ستكون القيمة النهائي ة‬
‫المعادة هي‪:‬‬
‫‪True‬‬
‫‪ .3‬جداول الحقيقة (‪)Truth Tables‬‬
‫المنطق مجال واسع‪ ،‬وسنكتفي في هذا الفصل ببعض األفك ار المهمَّ ة ال تي يمكن أن تس اعدك‬
‫على تحسين طريقة تفكيرك وخوارزمياتك‪.‬‬
‫فيما يلي جداول الحقيقة لمعامل الموازنة ==‪ ،‬والمع امالت المنطقي ة ‪ ,and‬و ‪ ,or‬و ‪ .not‬من‬
‫كيفية عمله ا‪ ،‬ف ذلك س يجعلك أس رع في اتخ اذ الق رارات أثن اء كتاب ة‬
‫المفي د أن تحف ظ‬
‫َّ‬
‫الشيفرات البرمجية‪.‬‬
‫‪193‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
)‫العمليات المنطقية (البوليانية‬
== ‫ جدول الحقيقة الخاص بالعامل‬.‫ا‬
‫القيمة المُ عادة‬
y
==
x
True
True
==
True
False
False
==
True
False
True
==
False
True
False
==
False
AND ‫ جدول الحقيقة الخاص بالعامل‬.‫ب‬
‫القيمة المُ عادة‬
y
and
x
True
True
and
True
False
False
and
True
False
True
and
False
False
False
and
False
OR ‫ جدول الحقيقة الخاص بالعامل‬.‫ج‬
▲
|
‫القيمة المُ عادة‬
y
or
x
True
True
or
True
True
False
or
True
True
True
or
False
False
False
or
False
194
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫د‪ .‬جدول الحقيقة الخاص بالعامل ‪NOT‬‬
‫‪x‬‬
‫‪not‬‬
‫القيمة المُ عادة‬
‫‪True‬‬
‫‪not‬‬
‫‪False‬‬
‫‪False‬‬
‫‪not‬‬
‫‪True‬‬
‫ُتس تخ َدم ج داول الحقيق ة في المنط ق الرياض ياتي كث يرًا‪ ،‬وهي مفي دة‪ ،‬ويجب حفظه ا‬
‫ووضعها في الحسبان عند إنشاء الخوارزميات البرمجية‪.‬‬
‫‪ .4‬استعمال المنطق للتحكم في مسار البرنامج‬
‫رطية (‪،)flow control statements‬‬
‫للتحكم في مس ار ونت ائج البرن امج ع بر التعليم ات الش‬
‫َّ‬
‫يمكننا استخدام «شرط» (‪ )condition‬متبوعً ا «بعبارة برمجية» (‪.)clause‬‬
‫قيم الش رط بإح دى القيم تين ‪ True‬أو ‪ ،False‬و ُتس تخ َدم تل ك القيم ة في اتخ اذ ق رار في‬
‫يُ َّ‬
‫البرن امج‪ .‬أمَّ ا العب ارة (‪ )clause‬فهي الكتل ة البرمجي ة ال تي تعقب الش رط وتح ِّدد نتيج ة البرن امج‬
‫وما ينبغي فعله في حال تحقق الشرط أو عدمه‪.‬‬
‫ُتظه ر الش يفرة أدن اه مث ااًل على مع امالت الموازن ة ال تي تعم ل م ع العب ارات الش رطية للتحكم‬
‫في مسار البرنامج‪:‬‬
‫شرط ‪#‬‬
‫بند ‪#‬‬
‫‪if grade >= 65:‬‬
‫)"‪print("Passing grade‬‬
‫‪else:‬‬
‫)"‪print("Failing grade‬‬
‫‪195‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫العمليات المنطقية (البوليانية)‬
‫ِّ‬
‫يحدد ه ذا البرن امج م ا إذا ك ان الط الب س ينجح أم يرس ب‪ .‬في ح ال ك انت الدرج ة ال تي‬
‫س‬
‫طبع النص‬
‫حص ل عليه ا الط الب تس اوي ‪ 83‬مثاًل ‪ ،‬تق ييم العب ارة األولى س يكون ‪ ،True‬وس ُي َ‬
‫"‪ ."Passing grade‬أمَّ ا إن كانت درجة الطالب هي ‪ ،59‬فتق ييم العب ارة األولى س يكون ‪،False‬‬
‫وبالت‬
‫الي س‬
‫ينتقل البرن‬
‫امج لتنفي‬
‫ذ التعليم‬
‫ة المرتبط‬
‫ةب‬
‫الفرع ‪ ،else‬أي‬
‫سيطبع "‪."Failing grade‬‬
‫يمكن تقييم كل كائنات بايثون بإحدى القيمتين ‪ True‬أو ‪ ،False‬لذلك يوصي الدليل ‪PEP 8‬‬
‫ألن ذلك قد يؤدي إلى إعادة قيم منطقية غير‬
‫بعدم موازنة كائن بإحدى القيمتين ‪ True‬أو ‪ّ ،False‬‬
‫َّ‬
‫متوقع ة‪ .‬على س بيل المث ال‪ ،‬علي ك تجنب اس تخدام مث ل ه ذا التعب ير ‪sammy == True‬‬
‫في برامجك‪.‬‬
‫المنطقية على ص ياغة ش روط يمكن اس تخدامها لتحدي د النتيج ة النهائي ة‬
‫تس اعد الع امالت‬
‫َّ‬
‫للبرنامج من خالل التحكم في مسار التنفيذ‪.‬‬
‫‪ .5‬خالصة الفصل‬
‫ألقين ا في ه ذا الفص ل نظ رة على الموازن ات والع امالت المنطقي ة‪ ،‬باإلض افة إلى ج داول‬
‫الحقيقة‪ ،‬وكيفية استخدام القيم المنطقية للتحكم في مسار البرنامج‪.‬‬
‫‪196‬‬
‫|‬
‫▲‬
‫‪11‬‬
‫النوع ‪ :List‬مدخل‬
‫إلى القوائم‬
‫‪197‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫الن وع ‪( list‬القائمة) هي بني ة بيان ات في ب ايثون‪ ،‬وهي عب ارة عن تسلس ل مُ َّ‬
‫رتب قاب ل‬
‫وكيفية استخدامها‪.‬‬
‫للتغيير من تجميعة عناصر‪ .‬سنتعرف في هذا الفصل على القوائم وتوابعها‬
‫َّ‬
‫ِّ‬
‫تمكنك من تجمي ع البيان ات المتش ابهة‪ ،‬أو ال تي‬
‫القوائم مناسبة لتجميع العناصر المترابطة‪ ،‬إذ‬
‫ً‬
‫معين ا معً ا‪ ،‬وت رتيب الش يفرة البرمجي ة‪ ،‬وتنفي ذ التواب ع والعملي ات على ع دة قيم في‬
‫غرض ا‬
‫تخدم‬
‫َّ‬
‫وقت واحد‪.‬‬
‫تساعد القوائم في بايثون وغيره ا من هياك ل البيان ات المركب ة على تمثي ل التجميع ات‪ ،‬مث ل‬
‫تجميع ة ملف ات في مجل د على حاس وبك‪ ،‬أو ق وائم التش غيل‪ ،‬أو رس ائل البري د اإللك تروني‬
‫وغير ذلك‪.‬‬
‫ً‬
‫قائمة تحتوي على عناصر من نوع السالسل النصية‪:‬‬
‫في المثال التالي‪ ،‬سننشئ‬
‫‪sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis‬‬
‫]'‪shrimp', 'anemone‬‬
‫عندما نطبع القائمة‪ ،‬فستشبه المخرجات القائمة التي أنشأناها‪:‬‬
‫)‪print(sea_creatures‬‬
‫الناتج‪:‬‬
‫]'‪['shark', 'cuttlefish', 'squid', 'mantis shrimp', 'anemone‬‬
‫بوص فها تسلس اًل‬
‫أي عنص ر من القائم ة ع بر الفهرس ة‪.‬‬
‫مرتب ا من العناص ر‪ ،‬يمكن اس تدعاء ِّ‬
‫ً‬
‫َّ‬
‫مركب ة تت ألف من أج زاء أص غر‪ ،‬وتتم يز بالمرون ة‪ ،‬إذ يمكن إض افة عناص ر إليه ا‪،‬‬
‫القوائم هي بيانات‬
‫وإزالته ا‪ ،‬وتغييره ا‪ .‬عن دما تحت اج إلى تخ زين الكث ير من القيم‪ ،‬أو التك رار ( ‪ )iterate‬عليه ا‪ ،‬وتري د‬
‫أن تملك القدرة على تعديل تلك القيم بسهولة‪ ،‬فالقوائم هي خيارك األفضل‪.‬‬
‫‪198‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫‪ .1‬فهرسة القوائم (‪)Indexing Lists‬‬
‫رس ذل ك العنص ر‪ ،‬وال ذي ه و ع دد ص حيح‪ ،‬فه رس‬
‫كل عنصر في القائمة يقابل ه رقم يمث ل فه َ‬
‫العنصر األول في القائمة هو ‪.0‬‬
‫إليك تمثيل لفهارس القائمة ‪:sea_creatures‬‬
‫‪anemone‬‬
‫‪shrimp‬‬
‫‪squid‬‬
‫‪shark‬‬
‫‪shark‬‬
‫‪4‬‬
‫‪3‬‬
‫‪2‬‬
‫‪1‬‬
‫‪0‬‬
‫يب دأ العنص ر األول‪ ،‬أي السلس لة النص ية ‪ ،shark‬عن د الفه رس ‪ ،0‬وتنتهي القائم ة عن د‬
‫الفهرس ‪ 4‬الذي يقابل العنصر ‪.anemone‬‬
‫ألن كل عنصر في قوائم بايثون يقابل ه رقم فه رس‪ ،‬يمكنن ا الوص ول إلى عناص ر الق وائم‬
‫نظرًا َّ‬
‫ومعالجتها كما نفعل مع أنواع البيانات المتسلسلة األخرى‪.‬‬
‫يمكننا اآلن استدعاء عنصر من القائمة من خالل رقم فهرسه‪:‬‬
‫‪cuttlefish‬‬
‫‪#‬‬
‫)]‪print(sea_creatures[1‬‬
‫َّ‬
‫موضح في الجدول أعاله‪ .‬المث ال‬
‫تتراوح أرقام الفهارس في هذه القائمة بين ‪ 0‬و ‪ ،4‬كما هو‬
‫ِّ‬
‫يوضح ذلك‪:‬‬
‫التالي‬
‫'‪sea_creatures[0] = 'shark‬‬
‫'‪sea_creatures[1] = 'cuttlefish‬‬
‫'‪sea_creatures[2] = 'squid‬‬
‫'‪sea_creatures[3] = 'mantis shrimp‬‬
‫'‪sea_creatures[4] = 'anemone‬‬
‫‪199‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫إذا اس تدعينا القائم ة ‪ sea_creatures‬ب رقم فه رس أك بر من ‪ ،4‬فس يكون الفه رس خ ارج‬
‫وسي َ‬
‫طلق الخطأ ‪:IndexError‬‬
‫النطاق‪،‬‬
‫ُ‬
‫)]‪print(sea_creatures[18‬‬
‫والمخرجات ستكون‪:‬‬
‫‪IndexError: list index out of range‬‬
‫ً‬
‫حس ب من نهاي ة القائم ة‪،‬‬
‫يمكنن ا‬
‫أيض ا الوص ول إلى عناص ر القائم ة بفه ارس س البة‪ ،‬وال تي ُت َ‬
‫بدءا من ‪ .-1‬هذا مفيد في حال كانت لدينا قائمة طويلة‪ ،‬وأردنا تحديد عنصر في نهايته‪.‬‬
‫ً‬
‫بالنسبة للقائمة ‪ ،sea_creatures‬تبدو الفهارس السالبة كما يلي‪:‬‬
‫‪shark‬‬
‫‪cuttlefish‬‬
‫‪squid‬‬
‫‪shrimp‬‬
‫‪anemone‬‬
‫‪-5‬‬
‫‪-4‬‬
‫‪-3‬‬
‫‪-2‬‬
‫‪-1‬‬
‫في المثال التالي‪ ،‬سنطبع العنصر ‪ squid‬باستخدام فهرس سالب‪:‬‬
‫‪squid‬‬
‫‪#‬‬
‫)]‪print(sea_creatures[-3‬‬
‫يمكننا ضم (‪ )concatenate‬سلسلة نصية مع سلسلة نصية أخرى باستخدام العامل ‪:+‬‬
‫‪# Sammy is a shark‬‬
‫)]‪print('Sammy is a ' + sea_creatures[0‬‬
‫ً‬
‫أيض ا اس تخدام‬
‫لقد ضممنا السلسلة النصية ‪ Sammy is a‬مع العنص ر ذي الفه رس ‪ .0‬يمكنن ا‬
‫ِّ‬
‫لضم قائمتين أو أكثر معً ا (انظر الفقرة أدناه)‪.‬‬
‫المعامل ‪+‬‬
‫أي عنصر من عناصر القائمة والعمل عليه‪.‬‬
‫تساعدنا الفهارس على الوصول إلى ِّ‬
‫‪200‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫‪ .2‬تعديل عناصر القائمة‬
‫يمكنن ا اس تخدام الفهرس ة لتغي ير عناص ر القائم ة‪ ،‬عن طري ق إس ناد قيم ة إلى عُ نص ر مُ فه رس‬
‫ّ‬
‫ويسهل تعديل وتحديث عناصرها‪.‬‬
‫من القائمة‪ .‬هذا يجعل القوائم أكثر مرونة‪،‬‬
‫إذا أردن ا تغي ير قيم ة السلس لة النص ية للعنص ر الموج ود عن د الفه رس ‪ ،1‬من القيم ة‬
‫‪ cuttlefish‬إلى ‪ ،octopus‬فيمكننا القيام بذلك على النحو التالي‪:‬‬
‫'‪sea_creatures[1] = 'octopus‬‬
‫اآلن‪ ،‬عندما نطبع ‪ ،sea_creatures‬ستكون النتيجة‪:‬‬
‫‪# ['shark', 'octopus', 'squid', 'mantis‬‬
‫)‪print(sea_creatures‬‬
‫]'‪shrimp', 'anemone‬‬
‫ً‬
‫أيضا تغيير قيمة عنصر باستخدام فهرس سالب‪:‬‬
‫يمكننا‬
‫'‪sea_creatures[-3] = 'blobfish‬‬
‫‪['shark', 'octopus', 'blobfish',‬‬
‫‪#‬‬
‫)‪print(sea_creatures‬‬
‫]'‪'mantis shrimp', 'anemone‬‬
‫اآلن اس تبدلنا بالسلس لة ‪ squid‬السلس لة النص ية ‪ blobfish‬الموج ودة عن د الفه رس‬
‫السالب ‪( -3‬والذي يقابل الفهرس الموجب ‪.)2‬‬
‫‪ .3‬تقطيع القوائم (‪)Slicing Lists‬‬
‫يمكنن ا أيض ا اس تدعاء ع دة عناص ر من القائم ة‪ .‬لنف ترض َّ‬
‫أنن ا ن رغب في طباع ة العناص ر‬
‫الموج ودة في وس ط القائم ة ‪ ،sea_creatures‬يمكنن ا القي ام ب ذلك عن طري ق اقتط اع ش ريحة‬
‫(جزء) من القائمة‪.‬‬
‫‪201‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫يمكننا باستخدام الشرائح استدعاء عدة قيم عن طري ق إنش اء مج ال من الفه ارس مفص ولة‬
‫بنقطتين [‪:]x: y‬‬
‫)]‪print(sea_creatures[1:4‬‬
‫‪# ['octopus', 'blobfish', 'mantis‬‬
‫]'‪shrimp‬‬
‫عند إنشاء شريحة‪ ،‬كما في [‪ ،]1: 4‬يبدأ االقتطاع من العنصر ذي الفهرس األول (مشموال)‪،‬‬
‫وينتهي عن د العنص ر ذي الفه رس الث اني (غ ير مش مول)‪ ،‬له ذا ُطبعَ ت في مثالن ا أعاله العناص ر‬
‫الموجودة في المواضع‪ ،1 ،‬و ‪ ،2‬و ‪.3‬‬
‫الفهرسين في التعبير [‪ .]x: y‬على‬
‫إذا أردنا تضمين أحد طرفي القائمة‪ ،‬فيمكننا حذف أحد‬
‫َ‬
‫س بيل المث ال‪ ،‬إذا أردن ا طباع ة العناص ر الثالث ة األولى من القائم ة ‪ ،sea_creatures‬يمكنن ا فع ل‬
‫ذلك عن طريق كتابة‪:‬‬
‫‪['shark', 'octopus',‬‬
‫‪#‬‬
‫)]‪print(sea_creatures[:3‬‬
‫]'‪'blobfish‬‬
‫لق د ُطبعَ ت العناص ر من بداي ة القائم ة ّ‬
‫حتى العنص ر ذي الفه رس ‪ .3‬لتض مين جمي ع العناص ر‬
‫الموجودة في نهاية القائمة‪ ،‬سنعكس الصياغة‪:‬‬
‫‪['blobfish', 'mantis shrimp',‬‬
‫‪#‬‬
‫)]‪print(sea_creatures[2:‬‬
‫]'‪'anemone‬‬
‫ً‬
‫أيض ا اس تخدام الفه ارس الس البة عن د اقتط اع الق وائم‪ ،‬تمامً ا كم ا ه و الح ال م ع‬
‫يمكنن ا‬
‫الفهارس الموجبة‪:‬‬
‫]'‪['octopus', 'blobfish‬‬
‫‪['blobfish', 'mantis‬‬
‫‪#‬‬
‫‪#‬‬
‫)]‪print(sea_creatures[-4:-2‬‬
‫)]‪print(sea_creatures[-3:‬‬
‫]'‪shrimp', 'anemone‬‬
‫‪202‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫هن اك معام ل آخ ر يمكنن ا اس تخدامه في االقتط اع‪ ،‬ويش ير إلى ع دد العناص ر ال تي يجب أن‬
‫تخطيها (الخطوة) بعد استرداد العنصر األول من القائم ة‪ .‬ح تى اآلن‪ ،‬لق د أغفلن ا المعام ل ‪،stride‬‬
‫وس تعطيه ب ايثون القيم ة االفتراض ية ‪ ،1‬م ا يع ني َّ‬
‫أنه س يتم اس ترداد ك ل العناص ر الموج ودة بين‬
‫الفهرسين المحددين‪.‬‬
‫َ‬
‫س تكون الص ياغة على الش كل الت الي [‪ ،]x: y: z‬إذ يش ير ‪ z‬إلى الخط وة (‪ .)stride‬في‬
‫المثال التالي‪ ،‬سننشئ قائمة كبيرة‪ ،‬ثم نقتطعها‪ ،‬مع خطوة اقتطاع تساوي ‪:2‬‬
‫]‪numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12‬‬
‫]‪[1, 3, 5, 7, 9‬‬
‫)]‪print(numbers[1:11:2‬‬
‫‪#‬‬
‫س يطبع التعب ير ]‪ numbers[1: 11: 2‬القيم ذات الفه ارس المحص ورة بين ‪( 1‬مش مولة)‬
‫و ‪( 11‬غير مشمولة)‪ ،‬وسيقفز البرنامج بخطوتين كل مرة‪ ،‬ويطبع العناصر المقابلة‪.‬‬
‫يمكنن ا ح ذف المُ ع املين األوَّ ل يين‪ ،‬واس تخدام الخط وة وح دها بع ِّدها مع اماًل وف ق الص ياغة‬
‫التالية‪:]::z[ :‬‬
‫]‪[0, 3, 6, 9, 12‬‬
‫‪#‬‬
‫)]‪print(numbers[::3‬‬
‫طب ع إال العناص ر ال تي‬
‫عن د طباع ة القائم ة ‪ numbers‬م ع تع يين الخط وة عن د القيم ة ‪ ،3‬فلن ُت َ‬
‫فهارس ها من مض اعفات ‪ .3‬يجع ل اس تخدام الفه ارس الموجب ة والس البة ومعام ل الخط وة في‬
‫اقتطاع القوائم التحكم في القوائم ومعالجتها أسهل وأكثر مرونة‪.‬‬
‫‪203‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫‪ .4‬تعديل القوائم بالعوامل‬
‫يمكن استخدام العوامل إلجراء تعديالت على القوائم‪ .‬س ننظر في اس تخدام الع املين ‪ +‬و *‬
‫ومقابليهما المركبين =‪ +‬و=*‪.‬‬
‫ِّ‬
‫لضم (‪ )concatenate‬قائمتين أو أكثر معً ا‪:‬‬
‫يمكن استخدام العامل ‪+‬‬
‫‪sea_creatures = ['shark', 'octopus', 'blobfish', 'mantis‬‬
‫]'‪shrimp', 'anemone‬‬
‫‪oceans = ['Pacific', 'Atlantic', 'Indian', 'Southern',‬‬
‫]'‪'Arctic‬‬
‫)‪print(sea_creatures + oceans‬‬
‫والمخرجات هي‪:‬‬
‫‪['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone',‬‬
‫]'‪'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic‬‬
‫يمكن اس تخدام العام ل ‪ +‬إلض افة عنص ر (أو ع دة عناص ر) إلى نهاي ة القائم ة‪ ،‬لكن ت ذكر أن‬
‫تضع العنصر بين قوسين مربعين‪:‬‬
‫]'‪sea_creatures = sea_creatures + ['yeti crab‬‬
‫‪['shark', 'octopus', 'blobfish',‬‬
‫‪#‬‬
‫)‪print (sea_creatures‬‬
‫]'‪'mantis shrimp', 'anemone', 'yeti crab‬‬
‫ُ‬
‫خ‬
‫يمكن اس تخدام العام ل * لمض اعفة الق وائم (‪ .)multiply lists‬ربم ا تحت اج إلى عم ل ن ِس ٍ‬
‫لجميع الملفات الموجودة في مجلد على خادم‪ ،‬أو مشاركة قائمة أفالم مع األصدقاء؛ ستحتاج في‬
‫هذه الحاالت إلى مضاعفة مجموعات البيانات‪.‬‬
‫سنضاعف القائمة ‪ sea_creatures‬مرتين‪ ،‬والقائمة ‪ oceans‬ثالث مرات‪:‬‬
‫‪204‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫)‪print(sea_creatures * 2‬‬
‫)‪print(oceans * 3‬‬
‫والنتيجة ستكون‪:‬‬
‫‪['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone',‬‬
‫‪'yeti crab', 'shark', 'octopus', 'blobfish', 'mantis shrimp',‬‬
‫]'‪'anemone', 'yeti crab‬‬
‫‪['Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic',‬‬
‫‪'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic',‬‬
‫]'‪'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic‬‬
‫يمكننا باستخدام العامل * نسخ القوائم عدة مرات‪.‬‬
‫ً‬
‫أيضا استخدام الشكلين المركبين للعاملين ‪ +‬و * مع عامل اإلسناد =‪ .‬يمكن اس تخدام‬
‫يمكننا‬
‫الع املين المرك بين =‪ +‬و =* لملء الق وائم بطريق ة س ريعة ومُ ؤتمت ة‪ .‬يمكن ك اس تخدام ه ذين‬
‫الع املين لملء الق وائم بعناص ر نائب ة (‪ )placeholders‬يمكن ك تع ديلها في وقت الح ق بالم دخالت‬
‫المقدمة من المستخدم على سبيل المثال‪.‬‬
‫في المثال الت الي‪ ،‬سنض يف عنص رًا إلى القائم ة ‪ .sea_creatures‬س يعمل ه ذا العنص ر مث ل‬
‫عمل العنصر النائب‪ ،‬ونود إضافة هذا العنصر النائب ع دة م رات‪ .‬لفع ل ذل ك‪ ،‬سنس تخدم العام ل =‪+‬‬
‫مع الحلقة ‪.for‬‬
‫‪for x in range(1,4):‬‬
‫]'‪sea_creatures += ['fish‬‬
‫)‪print(sea_creatures‬‬
‫والمخرجات ستكون‪:‬‬
‫‪205‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫ مدخل إلى القوائم‬:List ‫النوع‬
['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone',
'yeti crab', 'fish']
['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone',
'yeti crab', 'fish', 'fish']
['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone',
'yeti crab', 'fish', 'fish', 'fish']
.sea_creatures ‫ إلى القائمة‬fish ‫ عنصر‬for ‫سيضاف لكل تكرار في الحلقة‬
ُ
:‫يتصرف العامل =* بطريقة مماثلة‬
sharks = ['shark']
for x in range(1,4):
sharks *= 2
print(sharks)
:‫الناتج سيكون‬
['shark', 'shark']
['shark', 'shark', 'shark', 'shark']
['shark', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark',
'shark']
‫ إزالة عنصر من قائمة‬.5
‫ سيؤدي ذلك إلى حذف العنصر الموجود عن د‬.del ‫يمكن إزالة العناصر من القوائم باستخدام‬
.‫الفهرس المحدد‬
.1 ‫ هذا العنصر موجود عن د الفه رس‬.octopus ‫ العنصر‬sea_creatures ‫سنزيل من القائمة‬
:‫ ثم نستدعي متغير القائمة وفهرس ذلك العنصر‬del ‫ سنستخدم‬،‫إلزالة هذا العنصر‬
▲
|
206
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫‪sea_creatures =['shark', 'octopus', 'blobfish', 'mantis‬‬
‫]'‪shrimp', 'anemone', 'yeti crab‬‬
‫]‪del sea_creatures[1‬‬
‫‪['shark', 'blobfish', 'mantis‬‬
‫‪#‬‬
‫)‪print(sea_creatures‬‬
‫]'‪shrimp', 'anemone', 'yeti crab‬‬
‫اآلن‪ ،‬العنصر ذو الفهرس ‪ ،1‬أي السلسلة النصية ‪ ،octopus‬لم يعد موجو ًدا في قائمتنا‪.‬‬
‫أيض ا تحدي د مج ال م ع العب ارة ‪ .del‬لنق ل َّ‬
‫ً‬
‫أنن ا نري د إزال ة العناص ر ‪،octopus‬‬
‫يمكنن ا‬
‫و ‪ blobfish‬و ‪ mantis shrimp‬معً ا‪ .‬يمكننا فعل ذلك على النحو التالي‪:‬‬
‫‪sea_creatures =['shark', 'octopus', 'blobfish', 'mantis‬‬
‫]'‪shrimp', 'anemone', 'yeti crab‬‬
‫]‪del sea_creatures[1:4‬‬
‫]'‪['shark', 'anemone', 'yeti crab‬‬
‫‪#‬‬
‫)‪print(sea_creatures‬‬
‫َّ‬
‫الفهرس ين ‪( 1‬مش مول) و ‪4‬‬
‫تمكنا من إزالة العناص ر الموج ودة بين‬
‫باستخدام مجال مع ‪،del‬‬
‫َ‬
‫(غير مشمول)‪ ،‬والقائمة أضحت مكوَّ نة من ‪ 3‬عناصر فقط بعد إزالة ‪ 3‬عناصر منها‪.‬‬
‫‪ .6‬بناء قوائم من قوائم أخرى موجودة‬
‫يمكن أن تتض مَّ ن عناص ر الق وائم ق وائم أخ رى‪ ،‬م ع إدراج ك ل قائم ة بين قوس ين معق وفين‬
‫داخل األقواس المعقوفة الخارجية التابعة لقائمة األصلية‪:‬‬
‫‪sea_names = [['shark', 'octopus', 'squid', 'mantis shrimp'],‬‬
‫]]'‪['Sammy', 'Jesse', 'Drew', 'Jamie‬‬
‫تسمى القوائم المُ تضمّ نة داخل قوائم أخرى بالقوائم المتشعبة (‪.)nested lists‬‬
‫يتعين علين ا اس تخدام فه ارس متع ددة تقاب ل‬
‫للوص ول إلى عنص ر ض من ه ذه القائم ة‪ ،‬س‬
‫َّ‬
‫‪207‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫مستوى التشعُّ ب‪:‬‬
‫‪Sammy‬‬
‫‪#‬‬
‫)]‪print(sea_names[1][0‬‬
‫‪shark‬‬
‫‪#‬‬
‫)]‪print(sea_names[0][0‬‬
‫فهرسها ‪ .1‬ضمن كل قائمة متش ِّعبة داخلي ة‪،‬‬
‫فهرس القائمة األولى يساوي ‪ ،0‬والقائمة الثانية‬
‫ُ‬
‫سيكون هناك فهارس منفصلة‪ ،‬والتي سنسميها فهارس ثانوية‪:‬‬
‫'‪sea_names[0][0] = 'shark‬‬
‫'‪sea_names[0][1] = 'octopus‬‬
‫'‪sea_names[0][2] = 'squid‬‬
‫'‪sea_names[0][3] = 'mantis shrimp‬‬
‫'‪sea_names[1][0] = 'Sammy‬‬
‫'‪sea_names[1][1] = 'Jesse‬‬
‫'‪sea_names[1][2] = 'Drew‬‬
‫'‪sea_names[1][3] = 'Jamie‬‬
‫َّ‬
‫مؤلفة من قوائم‪ ،‬من المهم أن تعي َّ‬
‫أنك ستحتاج إلى اس تخدام أك ثر من‬
‫عند العمل مع قوائم‬
‫فهرس واحد للوصول إلى عناصر القوائم المتشعبة‪.‬‬
‫‪ .7‬استخدام توابع القوائم‬
‫َّ‬
‫كيفية إض افة‬
‫ونتعلم‬
‫سنَتعرَّ ف اآلن على التوابع المُ ضمَّ نة التي يمكن استخدامها م ع الق وائم‪.‬‬
‫َّ‬
‫وكيفية إزالتها‪ ،‬وتوسيع القوائم وترتيبها‪ ،‬وغير ذلك‪.‬‬
‫عناصر إلى القائمة‬
‫َّ‬
‫القوائم أن ٌ‬
‫واع قابل ٌة للتغي ير (‪ )mutable‬على عكس السالس ل النص ية ال تي ال يمكن تغييره ا‪،‬‬
‫فعندما تستخدم تابعً ا على قائمة ما‪ ،‬ستؤثر في القائمة نفسها‪ ،‬وليس في نسخة منها‪.‬‬
‫س نعمل في ه ذا القس م على قائم ة ِّ‬
‫تمثل ح وض س مك‪ ،‬إذ س تحوي القائم ة أس ماء أن واع‬
‫ً‬
‫أسماكا أو أزلناها من الحوض‪.‬‬
‫األسماك الموجودة في الحوض‪ ،‬وسنعدلها كلمَّ ا أضفنا‬
‫‪208‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫ا‪ .‬التابع )(‪list.append‬‬
‫َر ) إلى نهاية القائمة ‪.list‬‬
‫يضيف التابع )‪ list.append(x‬عنصرًا (العنصر ‪ x‬الممر‬
‫ّ‬
‫ً‬
‫يُ ِّ‬
‫قائمة تمثل األسماك الموجودة في حوض السمك‪.‬‬
‫عرف المثال التالي‬
‫]'‪fish = ['barracuda','cod','devil ray','eel‬‬
‫تتألف هذه القائمة من ‪ 4‬سالسل نصية‪ ،‬وتتراوح فهارسها من ‪ 0‬إلى ‪.3‬‬
‫سنض يف س مكة جدي دة إلى الح وض‪ ،‬ون ود بالمقاب ل أن نض يف تل ك الس مكة إلى قائمتن ا‪.‬‬
‫سنمرر السلسلة النصية ‪ flounder‬التي ِّ‬
‫ِّ‬
‫تمثل نوع الس مكة الجدي دة إلى الت ابع )(‪،list.append‬‬
‫ثم نطبع قائمتنا المعدلة لتأكيد إضافة العنصر‪:‬‬
‫)'‪fish.append('flounder‬‬
‫)‪print(fish‬‬
‫]'‪['barracuda', 'cod', 'devil ray', 'eel', 'flounder‬‬
‫‪#‬‬
‫اآلن‪ ،‬ص ارت ل دينا قائم ة من ‪ 5‬عناص ر‪ ،‬تنتهي بالعنص ر ال ذي أض فناه للت و ع بر‬
‫التابع )(‪.append‬‬
‫ب‪ .‬التابع )(‪list.insert‬‬
‫يأخذ التابع )‪ list.insert (i,x‬وسيطين‪ :‬األول ‪ِّ i‬‬
‫يمثل الفهرس الذي ترغب في إضافة‬
‫العنصر عنده‪ ،‬و ‪ x‬يمثل العنصر نفسه‪.‬‬
‫أن قائم ة‬
‫لق د أض فنا إلى ح وض الس مك س مكة جدي دة من ن وع ‪ .anchovy‬ربم ا الحظت َّ‬
‫ترتيبا أبج ديًا ح تى اآلن‪ ،‬له ذا الس بب ال نري د إفس اد ال ترتيب‪ ،‬ولن نض يف السلس لة‬
‫األسماك مرتبة‬
‫ً‬
‫النصية ‪ anchovy‬إلى نهاية القائمة باستخدام الدالة )(‪list.append‬؛ بداًل من ذلك‪ ،‬سنس تخدم‬
‫التابع )(‪ list.insert‬إلضافة ‪ anchovy‬إلى بداية القائمة‪ ،‬أي عند الفهرس ‪:0‬‬
‫‪209‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫)'‪fish.insert(0,'anchovy‬‬
‫)‪print(fish‬‬
‫‪['anchovy', 'barracuda', 'cod', 'devil ray', 'eel',‬‬
‫‪#‬‬
‫]'‪'flounder‬‬
‫في هذه الحالة‪ ،‬أضفنا العنصر إلى بداية القائمة‪.‬‬
‫وة واح ً‬
‫س تتقدم فه ارس العناص ر التالي ة خط ً‬
‫دة إلى األم ام‪ .‬ل ذلك‪ ،‬سيص بح العنص ر‬
‫‪ barracuda‬عن د الفه رس ‪ ،1‬والعنص ر ‪ cod‬عن د الفه رس ‪ ،2‬والعنص ر ‪ - flounder‬األخ ير ‪ -‬عن د‬
‫الفهرس ‪.5‬‬
‫سنحض ر اآلن س مكة من ن وع ‪ damselfish‬إلى الح وض‪ ،‬ون رغب في الحف اظ على ال ترتيب‬
‫األبج‬
‫دي لعناص‬
‫ر القائم‬
‫ة أعاله‪ ،‬ل‬
‫ذلك سنض‬
‫عه‬
‫ذا العنص‬
‫ر عن‬
‫د الفه‬
‫رس ‪:3‬‬
‫)'‪.fish.insert(3,'damselfish‬‬
‫ج‪ .‬التابع )(‪list.extend‬‬
‫ِّ‬
‫توسع قائمة بعناصر قائم ة أخ رى‪ ،‬فيمكن ك اس تخدام الت ابع )‪،list.extend(L‬‬
‫إذا أردت أن‬
‫والذي يأخذ قائمة (المعامل ‪ )L‬ويضيف عناصرها إلى القائمة ‪.list‬‬
‫سنض ع في الح وض أربع ة أس ماك جدي دة‪ .‬أن واع ه ذه األس ماك مجموع ة معً ا في‬
‫القائمة ‪:more_fish‬‬
‫]'‪more_fish = ['goby','herring','ide','kissing gourami‬‬
‫أن‬
‫سنض يف اآلن عناص ر القائم ة ‪ more_fish‬إلى قائم ة األس ماك‪ ،‬ونطب ع القائم ة لنتأك د من َّ‬
‫عناصر القائمة الثانية قد أضيفت إليها‪:‬‬
‫)‪fish.extend(more_fish‬‬
‫‪210‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫)‪print(fish‬‬
‫ستطبع بايثون القائمة التالية‪:‬‬
‫‪['anchovy', 'barracuda', 'cod', 'devil ray', 'eel', 'flounder',‬‬
‫]'‪'goby', 'herring', 'ide', 'kissing gourami‬‬
‫في هذه المرحلة‪ ،‬صارت القائمة ‪ fish‬تتألف من ‪ 10‬عناصر‪.‬‬
‫د‪ .‬التابع )(‪list.remove‬‬
‫إلزال ة عنص ر من قائم ة‪ ،‬اس تخدم الت ابع )‪ ،list.remove(x‬وال ذي يزي ل أول عنص ر من‬
‫القائمة له القيمة المُ مرَّ رة ‪.x‬‬
‫ً‬
‫أبحاث ا عن‬
‫ج اءت مجموع ة من العلم اء المحل يين لزي ارة الح وض‪ ،‬وس يجرون‬
‫النوع ‪ ،kissing gourami‬وطلبوا استعارة السمكة ‪ ،kissing gourami‬لذلك نود إزالة العنص ر‬
‫‪ kissing gourami‬من القائمة لنعكس هذا التغيير‪:‬‬
‫)'‪fish.remove('kissing gourami‬‬
‫)‪print(fish‬‬
‫والمخرجات ستكون‪:‬‬
‫‪['anchovy', 'barracuda', 'cod', 'devil ray', 'eel', 'flounder',‬‬
‫]'‪'goby', 'herring', 'ide‬‬
‫بع د اس تخدام الت ابع )(‪ ،list.remove‬لم يع د العنص ر ‪ kissing gourami‬موج و ًدا‬
‫في القائمة‪.‬‬
‫في ح ال اخ ترت عنص رًا ‪ x‬غ ير موج ود في القائم ة ومرَّ رت ه إلى الت ابع )(‪،list.remove‬‬
‫فسيطلق الخطأ التالي‪:‬‬
‫ُ‬
‫‪211‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫‪ValueError: list.remove(x): x not in list‬‬
‫لن يزي ل الت ابع )(‪ list.remove‬إال أوَّ ل عنص ر تس اوي قيمت ه قيم ة العنص ر المُ م رَّ ر إلى‬
‫التابع‪ ،‬لذلك إن ك انت ل دينا س مكتان من الن وع ‪ kissing gourami‬في الح وض‪ ،‬وأعرن ا إح داهما‬
‫إن التعب ير )'‪ fish.remove('kissing gourami‬لن يمح و إال العنص ر األول‬
‫فق ط للعلم اء‪ ،‬ف َّ‬
‫المطابق فقط‪.‬‬
‫ه‪ .‬التابع )(‪list.pop‬‬
‫يعي د الت ابع )]‪ list.pop ([i‬العنص ر الموج ود عن د الفه رس المح دد من القائم ة‪ ،‬ثم يزي ل‬
‫فهرس ا‬
‫أن هذا المعامل اختي اري‪ ،‬ل ذا‪ ،‬إذا لم تح دد‬
‫ً‬
‫ذلك العنصر‪ .‬تشير األقواس المربعة حول ‪ i‬إلى َّ‬
‫فسيعاد العنصر األخير ثم يُ زال‪.‬‬
‫(كما في )(‪،)fish.pop‬‬
‫ُ‬
‫أن‬
‫لقد أصبح حجم السمكة ‪ devil ray‬كبي ًرا ج ًدا‪ ،‬ولم يعد الحوض يس عها‪ ،‬ولحس ن الح ظ َّ‬
‫هناك حوض سمك في بلدة مجاورة يمكنه استيعابها‪ .‬سنستخدم التابع )(‪ ،.pop‬ونمرر إلي ه الع دد‬
‫‪ ،3‬الذي يساوي فهرس العنص ر ‪ ،devil ray‬بقص د إزالت ه من القائم ة‪ .‬بع د إع ادة العنص ر‪ ،‬س نتأكد‬
‫من أننا أزلنا العنصر الصحيح‪.‬‬
‫‪print(fish.pop(3)) # devil ray‬‬
‫)‪print(fish‬‬
‫‪# ['anchovy', 'barracuda', 'cod', 'eel', 'flounder', 'goby',‬‬
‫]'‪'herring', 'ide‬‬
‫َّ‬
‫تمكنا من إزالة السمكة ‪ ray devil‬من قائمة األسماك‪ .‬إذا لم ُن ِّ‬
‫مرر‬
‫باستخدام التابع )(‪.pop‬‬
‫أي معام ل إلى ه ذا الت ابع‪َّ ،‬‬
‫ونفذنا االس تدعاء )(‪ ،fish.pop‬فس ُيعاد العنص ر األخ ير ‪ ide‬ثم يُ َزال‬
‫َّ‬
‫من القائمة‪.‬‬
‫‪212‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫و‪ .‬التابع )(‪list.index‬‬
‫يص عب في الق وائم الكب يرة تحدي د فه ارس العناص ر ال تي تحم ل قيم ة معين ة‪ .‬ألج ل ذل ك‪،‬‬
‫يمكنن ا اس تخدام الت ابع )‪ ،list.index(x‬إذ يمث ل الوس يط‪ x‬قيم ة العنص ر المبح وث عن ه‪ ،‬وال ذي‬
‫نري د معرف ة فهرس ه‪ .‬إذا ك ان هن اك أك ثر من عنص ر واح د يحم ل القيم ة ‪ ،x‬فس ُيعَ اد فه رس‬
‫العنصر األول‪.‬‬
‫‪# ['anchovy', 'barracuda', 'cod', 'eel',‬‬
‫)‪print(fish‬‬
‫]'‪'flounder', 'goby', 'herring', 'ide‬‬
‫‪# 6‬‬
‫))'‪print(fish.index('herring‬‬
‫سوف يُ َ‬
‫طل ق خطأ في حال مرَّ رنا قيمة غير موجودة في القائمة إلى التابع )(‪..index‬‬
‫ز‪ .‬التابع )(‪list.copy‬‬
‫ُ‬
‫أحيان ا نرغب في تعديل عناصر قائمةٍ والتجريب عليها‪ ،‬مع الحفاظ على القائمة األصلية دون‬
‫تغيير؛ يمكننا في هذه الحالة استخدام التابع )(‪ list.copy‬إلنشاء نسخة من القائمة األصلية‪.‬‬
‫في المث ال الت الي‪ ،‬س ِّ‬
‫نمرر القيم ة المع ادة من )(‪ fish.copy‬إلى المتغ ير ‪ ،fish_2‬ثم نطب ع‬
‫قيمة ‪ fish_2‬للتأكد من َّ‬
‫أنها تحتوي على نفس عناصر القائمة ‪.fish‬‬
‫)(‪fish_2 = fish.copy‬‬
‫)‪print(fish_2‬‬
‫‪['anchovy', 'barracuda', 'cod', 'eel', 'flounder', 'goby',‬‬
‫‪#‬‬
‫]'‪'herring', 'ide‬‬
‫في هذه المرحلة‪ ،‬القائمتان ‪ fish‬و ‪ fish_2‬متساويتان‪.‬‬
‫‪213‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫ح‪ .‬التابع )(‪list.reverse‬‬
‫يمكنن ا عكس ت رتيب عناص ر قائم ة باس تخدام الت ابع )(‪ .list.reverse‬في المث ال الت الي‬
‫سنستخدم التابع )(‪ .reverse‬مع القائمة ‪ fish‬لعكس ترتيب عناصرها‪.‬‬
‫)(‪fish.reverse‬‬
‫‪['ide', 'herring', 'goby', 'flounder', 'eel',‬‬
‫‪#‬‬
‫)‪print(fish‬‬
‫]'‪'cod', 'barracuda', 'anchovy‬‬
‫بع د اس تخدام الت ابع )(‪ ،.reverse‬ص ارت القائم ة تب دأ بالعنص ر ‪ ،ide‬وال ذي ك ان في نهاي ة‬
‫القائمة من قبل‪ ،‬كما ستنتهي القائمة بالعنصر ‪ ،anchovy‬والذي كان في بداية القائمة من قبل‪.‬‬
‫ط‪ .‬التابع )(‪list.count‬‬
‫يعي د الت ابع )‪ list.count(x‬ع دد م رات ظه ور القيم ة ‪ x‬في القائم ة‪ .‬ه ذا الت ابع مفي د في‬
‫حال كنا نعمل على قائمة طويلة بها الكثير من القيم المتطابقة‪.‬‬
‫إذا ك ان ح وض الس مك كب يرًا‪ ،‬على س بيل المث ال‪ ،‬وك انت عن دنا ع دة أس ماك من الن وع‬
‫‪ ،neon tetra‬فيمكننا استخدام التابع )(‪ .count‬لتحديد العدد اإلجمالي ألسماك هذا النوع‪.‬‬
‫في المثال التالي‪ ،‬سنحسب عدد مرات ظهور العنصر ‪:goby‬‬
‫‪1‬‬
‫‪#‬‬
‫))'‪print(fish.count('goby‬‬
‫رة واح ً‬
‫تظه ر السلس لة النص ية ‪ goby‬م ً‬
‫دة فق ط في القائم ة‪ ،‬ل ذا س ُيعيد الت ابع )(‪.count‬‬
‫ً‬
‫أيض ا م ع قائم ة مكوَّ ن ة من أع داد ص حيحة‪ ،‬ويوض ح المث ال‬
‫الع دد ‪ .1‬يمكنن ا اس تخدام ه ذا الت ابع‬
‫التالي ذلك‪.‬‬
‫أن وجباته ا الغذائي ة‬
‫يتتبع المشرفون على الح وض أعم ار األس ماك الموج ودة في ه للتأك د من َّ‬
‫مناس بة ألعماره ا‪ .‬ه ذه القائم ة الثاني ة المُ س ماة ‪ fish_ages‬تتواف ق م ع أن واع الس مك في‬
‫‪214‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫ألن األسماك ال تي ال يتج اوز عمره ا عامً ا واح ًدا له ا احتياج ات غذائي ة خاص ة‪،‬‬
‫القائمة ‪ .fish‬نظ ًرا ّ‬
‫فسنحسب عدد األسماك التي عمرها عامً ا واح ًدا‪:‬‬
‫]‪fish_ages = [1,2,4,3,2,1,1,2‬‬
‫‪3‬‬
‫‪#‬‬
‫))‪print(fish_ages.count(1‬‬
‫يظه ر الع دد الص حيح ‪ 1‬في القائم ة ‪ fish_ages‬ثالث م رات‪ ،‬ل ذلك يعي د الت ابع )(‪.count‬‬
‫العدد ‪.3‬‬
‫ي‪ .‬التابع )(‪list.sort‬‬
‫ُ‬
‫استدعِ ي معها‪ .‬سنستخدم قائم ة‬
‫يُ ستخدم التابع )(‪ list.sort‬لترتيب عناصر القائمة التي‬
‫األعداد الصحيحة ‪ fish_ages‬لتجريب التابع )(‪:.sort‬‬
‫)(‪fish_ages.sort‬‬
‫]‪[1, 1, 1, 2, 2, 2, 3, 4‬‬
‫‪#‬‬
‫)‪print(fish_ages‬‬
‫مرت ً‬
‫َّ‬
‫ُ‬
‫بة‪.‬‬
‫فستعاد تلك القائمة‬
‫باستدعاء التابع )(‪ .sort‬مع القائمة ‪، fish_ages‬‬
‫ك‪ .‬التابع )(‪list.clear‬‬
‫بعد االنتهاء من العمل على قائمة م ا‪ ،‬يمكن ك إزال ة جمي ع العناص ر الموج ودة فيه ا باس تخدام‬
‫التابع )(‪.list.clear‬‬
‫ق ررت الحكوم ة المحلي ة االس تيالء على ح وض الس مك الخ اص بن ا‪ ،‬وجعل ه مس احة عامة‬
‫يس تمتع به ا س كان م دينتنا‪ .‬نظ رً ا ألنن ا لم نع د نعم ل على الح وض‪ ،‬فلم نع د بحاج ة إلى االحتف اظ‬
‫بقائمة األسماك‪ ،‬لذلك سنزيل عناصر القائمة ‪:fish‬‬
‫‪215‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫)(‪fish.clear‬‬
‫][‬
‫‪#‬‬
‫)‪print(fish‬‬
‫أقواس ا معقوف ة نتيج ة اس تدعاء الت ابع )(‪ .clear‬على القائم ة ‪،fish‬‬
‫ن رى في المخرج ات‬
‫ً‬
‫وهذا تأكيد على َّّ‬
‫أن القائمة أصبحت خالية من جميع العناصر‪.‬‬
‫‪ .8‬فهم كيفية استعمال ‪List Comprehensions‬‬
‫ت وفر ‪ List Comprehensions‬طريق ًة مختص ً‬
‫اء على ق وائم موج ودة‬
‫رة إلنش اء الق وائم بن ً‬
‫ً‬
‫أي ن وع من البيان ات‬
‫مسبقا‪ .‬فيمكن عند استخدام ‪ list comprehensions‬بناء الق وائم باس تخدام ِّ‬
‫المتسلس لة ال تي يمكن ال دوران على عناص رها ع بر حلق ات التك رار‪ ،‬بم ا في ذل ك السالس ل النص ية‬
‫والص فوف‪ .‬من ناحي ة ال تركيب اللغ وي‪ ،‬تحت وي ‪ list comprehensions‬على عنص ر يمكن الم رور‬
‫تب ع م ا س بق بتع ابير ‪ for‬أو ‪ if‬إض افية‪ ،‬ل ذا‬
‫وع بحلق ة ‪ .for‬ويمكن أن يُ َ‬
‫علي ه ض من تعب ٍ‬
‫ير متب ٍ‬
‫سيساعدك الفهم العميق لحلقات ‪ for‬والعبارات الشرطية في التعامل مع ‪.list comprehensions‬‬
‫ت ِّ‬
‫وفر ‪ list comprehensions‬طريق ًة مختلف ًة إلنش اء الق وائم وغيره ا من أن واع البيان ات‬
‫المتسلسلة‪ .‬وعلى الرغم من إمكانية استخدام الطرائق األخرى لل دوران‪ ،‬مث ل حلق ات ‪ ،for‬إلنش اء‬
‫المفض ل اس تعمال ‪ list comprehensions‬ألنه ا ِّ‬
‫َّ‬
‫تقلل ع دد األس طر الموج ودة‬
‫الق وائم‪ ،‬لكن من‬
‫في برنامجك‪.‬‬
‫يمكن بناء ‪ list comprehensions‬في بايثون كاآلتي‪:‬‬
‫]‪list_variable = [x for x in iterable‬‬
‫ُ‬
‫ستس نَد القائم ة‪ ،‬أو أي ن وع من البيان ات يمكن الم رور على عناص ره‪ ،‬إلى متغ ير‪ .‬المتغ يرات‬
‫اإلض افية –ال تي ُتش ير إلى عناص ر موج ودة ض من ن وع البيان ات ال ذي يمكن الم رور على عناص ره–‬
‫‪216‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫ُتب نى ح ول عب ارة ‪ .for‬والكلم ة المحج وزة ‪ in‬تس تعمل بنفس اس تعمالها في حلق ات ‪ for‬وذل ك‬
‫ً‬
‫ً‬
‫مثال يُ ِ‬
‫مبنية على سلسلةٍ نصية‪:‬‬
‫قائمة‬
‫نشئ‬
‫لمرور على عناصر ‪ .iterable‬لننظر إلى‬
‫ٍ‬
‫]'‪shark_letters = [letter for letter in 'shark‬‬
‫)‪print(shark_letters‬‬
‫ً‬
‫دة إلى المتغ ير ‪ ،shark_letters‬واس تعملنا‬
‫أس ندنا في المث ال الس ابق قائم ًة جدي‬
‫المتغ ير ‪ letter‬لإلش ارة إلى العناص ر الموج ودة ض من السلس لة النص ية '‪ .'shark‬اس تعملنا بع د‬
‫ذل ك الدال ة )(‪ print‬لكي نتأك د من القائم ة الناتج ة والمُ س نَدة إلى المتغ ير ‪،shark_letters‬‬
‫وحصلنا على الناتج اآلتي‪:‬‬
‫]'‪['s', 'h', 'a', 'r', 'k‬‬
‫تت ألف القائم ة ال تي أنش أناها باس تخدام ‪ list comprehensions‬من العناص ر ال تي تك ِّون‬
‫السلس لة النص ية '‪ ،'shark‬وهي ك ل ح رف في الكلم ة ‪ .shark‬يمكن إع ادة كتاب ة‬
‫تع ابير ‪ list comprehensions‬بش كل حلق ات ‪ ،for‬لكن الح ظ َّ‬
‫أنك ال تس تطيع إع ادة كتاب ة ك ل‬
‫حلق ة ‪ for‬بص يغة ‪ .list comprehensions‬لنع د كتاب ة المث ال الس ابق ال ذي أنش أنا في ه القائم ة‬
‫‪ shark_letters‬باس‬
‫تخدام حلق‬
‫ة ‪ ،for‬وه‬
‫ذا سيس‬
‫ف‬
‫اعدنا في فهم كي‬
‫تعمل ‪ list comprehensions‬عملها‪:‬‬
‫][ = ‪shark_letters‬‬
‫‪for letter in 'shark':‬‬
‫)‪shark_letters.append(letter‬‬
‫)‪print(shark_letters‬‬
‫عن د إنش ائنا للقائم ة ع بر اس تخدام الحلق ة ‪ ،for‬فيجب تهيئ ة المتغ ير ال ذي س ُنس نِد العناص ر‬
‫‪217‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫إلي ه كقائم ة فارغ ة‪ ،‬وه ذا م ا فعلن اه في أوّ ل س طر من الش يفرة الس ابقة‪ .‬ثم ب دأت حلق ة ‪for‬‬
‫ً‬
‫تعملة المتغ ير ‪ letter‬لإلش ارة إلى قيم ة‬
‫بال دوران على عناص ر السلس لة النص ية '‪ 'shark‬مس‬
‫العنصر الح الي‪ ،‬ومن ثم أض فنا ك ل عنص ر في السلس لة النص ية إلى القائم ة ض من حلق ة ‪ for‬وذل ك‬
‫باس‬
‫تخدام الدال‬
‫ة )‪ .list.append(x‬الن‬
‫اتج من حلق‬
‫ة ‪ for‬الس‬
‫ل‬
‫ابقة يماث‬
‫ناتج ‪ list comprehension‬في المثال أعاله‪:‬‬
‫]'‪['s', 'h', 'a', 'r', 'k‬‬
‫يمكن إعادة كتابة ‪ List comprehensions‬كحلقات ‪ ،for‬لكن بعض حلقات ‪ for‬يمكن إع ادة‬
‫كتابتها لتصبح ‪ List comprehensions‬لتقليل كمية الشيفرات المكتوبة‪.‬‬
‫ا‪ .‬استخدام التعابير الشرطية مع ‪List Comprehensions‬‬
‫يمكن اس تخدام التع ابير الش رطية في ‪ list comprehension‬لتع ديل الق وائم أو أن واع‬
‫ال عن اس تخدام العب ارة‬
‫البيان ات المتسلس لة األخ رى عن د إنش اء ق وائم جدي دة‪ .‬لننظ ر إلى مث ٍ‬
‫الشرطية ‪ if‬في تعبير ‪:list comprehension‬‬
‫)'‪fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus‬‬
‫]'‪fish_list = [fish for fish in fish_tuple if fish != 'octopus‬‬
‫)‪print(fish_list‬‬
‫أساس ا للقائم ة الجدي دة ال تي‬
‫اس تعملنا المتغ ير ‪ fish_tuple‬ال ذي من ن وع البيان ات ‪tuple‬‬
‫ً‬
‫س ُن ِ‬
‫نش ئها ال تي تس مى ‪ .fish_list‬اس تعملنا ‪ for‬و ‪ in‬كم ا في القس م الس ابق‪ ،‬لكنن ا أض فنا هن ا‬
‫التعليم ة الش رطية ‪ .if‬س تؤدي التعليم ة الش رطية ‪ if‬إلى إض افة العناص ر غ ير المس اوية للسلس لة‬
‫النص ية '‪ ،'octopus‬ل ذا س تحتوي القائم ة الجدي دة على العناص ر الموج ودة في بني ة ص ف‬
‫‪218‬‬
‫|‬
‫▲‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫البرمجة بلغة بايثون‬
‫أن القائم ة‬
‫(‪ )tuple‬وال تي ال ُتط ا ِبق الكلم ة '‪ .'octopus‬عن د تش غيل البرن امج الس ابق فس نالحظ َّ‬
‫‪ fish_list‬تحت وي على نفس العناص ر ال تي ك انت موج ودة في ‪ fish_tuple‬لكن م ع ح ذف‬
‫العنصر '‪:'octopus‬‬
‫]'‪['blowfish', 'clownfish', 'catfish‬‬
‫أي أصبحت القائمة الجديدة تحتوي على بنية صف أصلية لكن ما عدا السلس لة النص ية ال تي‬
‫اس تثنيناها ع بر التعب ير الش رطي‪ .‬س ُن ِ‬
‫نش ئ مث ااًل آخ ر يس تعمل المع امالت الرياض ية واألرق ام‬
‫الصحيحة والدالة )(‪:range‬‬
‫]‪number_list = [x ** 2 for x in range(10) if x % 2 == 0‬‬
‫)‪print(number_list‬‬
‫ست َ‬
‫القائم ة ال تي ُ‬
‫نش أ باس م ‪ number_list‬س تحتوي على مرب ع جمي ع القيم الموج ودة من‬
‫المجال ‪ 0‬إلى ‪ 9‬لكن إذا كان الرقم قاباًل للقسمة على ‪ .2‬وستبدو المخرجات اآلتية‪:‬‬
‫]‪[0, 4, 16, 36, 64‬‬
‫ِّ‬
‫دعنا ُن ِّ‬
‫نفكر بال ذي س يظهر إذا‬
‫فصل ما الذي يفعله تعبير ‪ list comprehension‬السابق‪ ،‬ودعنا‬
‫استعملنا التعبير )‪ x for x in range(10‬فقط‪ .‬يجب أن يبدو برنامجنا الصغير كاآلتي‪:‬‬
‫])‪number_list = [x for x in range(10‬‬
‫)‪print(number_list‬‬
‫الناتج‪:‬‬
‫]‪[0, 1, 2, 3, 4, 5, 6, 7, 8, 9‬‬
‫لنضف العبارة الشرطية اآلن‪:‬‬
‫‪219‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫]‪number_list = [x for x in range(10) if x % 2 == 0‬‬
‫)‪print(number_list‬‬
‫الناتج‪:‬‬
‫]‪[0, 2, 4, 6, 8‬‬
‫أ َّدت التعليم ة الش رطية ‪ if‬إلى قب ول العناص ر القابل ة للقس مة على ‪ 2‬فق ط وإض افتها إلى‬
‫القائم ة‪ ،‬مم ا ي ؤدي إلى ح ذف جمي ع األرق ام الفردي ة‪ .‬يمكنن ا اآلن اس تخدام معام ل رياض ي ل تربيع‬
‫قيمة المتغير ‪:x‬‬
‫]‪number_list = [x ** 2 for x in range(10) if x % 2 == 0‬‬
‫)‪print(number_list‬‬
‫أي ُ‬
‫وسيخرَ ج الناتج اآلتي‪:‬‬
‫ستربَّع قيم القائمة السابقة ]‪[0, 2, 4, 6, 8‬‬
‫ُ‬
‫]‪[0, 4, 16, 36, 64‬‬
‫ً‬
‫أيضا استعمال ما يشبه عبارات ‪ if‬المتشعبة في تعابير ‪:list comprehension‬‬
‫يمكننا‬
‫== ‪number_list = [x for x in range(100) if x % 3 == 0 if x % 5‬‬
‫]‪0‬‬
‫)‪print(number_list‬‬
‫ُّ‬
‫أن المتغ ير ‪ x‬قاب ل للقس مة على ال رقم ‪ ،3‬ثم س نتحقق إن ك ان المتغ ير ‪x‬‬
‫س يتم‬
‫التحقق أواًل َّ‬
‫قاب ل للقس مة على ال رقم ‪ ،5‬وإذا َّ‬
‫فسيض اف إلى القائم ة‪،‬‬
‫حقق المتغ ير ‪ x‬الش رطين الس ابقين‬
‫ُ‬
‫وسي َ‬
‫ظهر في الناتج‪:‬‬
‫ُ‬
‫]‪[0, 15, 30, 45, 60, 75, 90‬‬
‫‪220‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫يمكن اس تخدام تعليم ة ‪ if‬الش رطية لتحدي د م ا هي العناص ر ال تي نري د إض افتها إلى‬
‫القائمة الجديدة‪.‬‬
‫ب‪ .‬حلقات التكرار المتشعبة في تعابير ‪List Comprehension‬‬
‫يمكن اس تعمال حلق ات التك رار المتش عبة إلج راء ع ِّدة عملي ات دوران متداخل ة في برامجن ا‪.‬‬
‫س‬
‫ننظر في ه‬
‫ذا القس‬
‫م إلى حلق‬
‫ة ‪ for‬متش‬
‫عبة وس‬
‫نحاول تحويله‬
‫ير‬
‫ا إلى تعب‬
‫نش ئ ه ذه الش يفرة قائم ًة جدي ً‬
‫‪ُ .list comprehension‬‬
‫ست ِ‬
‫دة بال دوران على ق ائمتين وب إجراء‬
‫عمليات رياضية عليها‪:‬‬
‫][ = ‪my_list‬‬
‫‪for x in [20, 40, 60]:‬‬
‫‪for y in [2, 4, 6]:‬‬
‫)‪my_list.append(x * y‬‬
‫)‪print(my_list‬‬
‫سنحصل على الناتج اآلتي عند تشغيل البرنامج‪:‬‬
‫]‪[40, 80, 120, 80, 160, 240, 120, 240, 360‬‬
‫تضرب الشيفرة السابقة العناصر الموجودة في أوَّ ل قائمة بالعناصر الموجودة في ثاني قائمة‬
‫في ك ل دورة‪ .‬لتحوي ل م ا س بق إلى تعب ير ‪ ،list comprehension‬وذل ك باختص ار الس طرين‬
‫طر وحي دٍ ‪ ،‬ال ذي يب دأ ب إجراء العملي ة ‪ ،x*y‬ثم‬
‫الموج ودين في الش يفرة الس ابقة وتحويلهم ا إلى س ٍ‬
‫ستلي هذه العملية حلقة ‪ for‬الخارجية‪ ،‬ثم يليه ا حلق ة ‪ for‬الداخلي ة؛ وسنض يف تعب ير )(‪print‬‬
‫أن ناتج القائمة الجديدة يُ طا ِبق ناتج البرنامج الذي فيه حلقتين متداخلتين‪:‬‬
‫للتأكد َّ‬
‫‪221‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫]]‪my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6‬‬
‫)‪print(my_list‬‬
‫الناتج‪:‬‬
‫]‪[40, 80, 120, 80, 160, 240, 120, 240, 360‬‬
‫أدى اس تعمال تعب ير ‪ list comprehension‬في المث ال الس ابق إلى تبس يط حلقتَي ‪for‬‬
‫ستس نَد إلى المتغ ير ‪ .my_list‬ت ِّ‬
‫لتصبحا سط ًرا وحي ًدا‪ ،‬لكن م ع إنش اء نفس القائم ة وال تي ُ‬
‫وفر لن ا‬
‫ً‬
‫يطة إلنش اء الق وائم‪ ،‬مم ا يس مح لن ا باختص ار ع ِّدة أس طر‬
‫تع ابير ‪ list comprehension‬طريق ًة بس‬
‫أن سهولة قراءة الشيفرة لها األولوية دومً ا‪ ،‬ل ذا‬
‫إلى‬
‫سطر وحيد‪ .‬لكن من المهم أن تبقي في ذهنك َّ‬
‫ٍ‬
‫َّ‬
‫َ‬
‫ومعقدة‪ ،‬فمن األفض ل حينه ا تحويله ا إلى‬
‫بحت تع ابير ‪ list comprehension‬طويل ًة ج ًدا‬
‫إذا أص‬
‫حلقات تكرار عادية‪.‬‬
‫‪ .9‬خالصة الفصل‬
‫الق وائم هي ن وع بيان ات م رن يمكن تعديل ه بس هولة خالل أط وار البرن امج‪ .‬غطين ا في ه ذا‬
‫َّ‬
‫والض م‪.‬‬
‫الفصل الميزات والخصائص األساس ية لق وائم‪ ،‬بم ا في ذل ك الفهرس ة واالقتط اع والتع ديل‬
‫ُ‬
‫لمَّ ا كانت القوائم تسلسالت قابلة للتغيير (‪َّ ،)mutable‬‬
‫هياكل بيانات مرنة ومفيدة للغاية‪ .‬كما‬
‫فإنها‬
‫تتيح لنا توابع القوائم إجراء العديد من العمليات على القوائم بسهولة‪ ،‬إذ يمكنن ا اس تخدام التواب ع‬
‫لتعديل القوائم وترتيبها ومعالجتها بفعالية‪.‬‬
‫تسمح تعابير ‪ list comprehension‬لنا بتحويل قائمة أو أي نوع من البيانات المتسلسلة إلى‬
‫بسيط يُ ِّ‬
‫ٌ‬
‫ٌ‬
‫قلل عدد األسطر التي نكتبها‪ .‬تتبع تعابير ‪list comprehension‬‬
‫شكل‬
‫سلسلةٍ جديدة‪ ،‬ولها‬
‫أن‬
‫ٌ‬
‫معي ًن ا‪ ،‬ل ذا ق د يج دها الم برمجون أول و الخلفي ة الرياض ية س هلة الفهم‪ .‬وص‬
‫ش كاًل رياض ًيا‬
‫حيح َّ‬
‫ّ‬
‫‪222‬‬
‫|‬
‫▲‬
‫النوع ‪ :List‬مدخل إلى القوائم‬
‫البرمجة بلغة بايثون‬
‫تع ابير ‪ list comprehension‬تختص ر الشيفرةـ لكن من المهم جع ل س هولة ق راءة الش يفرة من‬
‫أولوياتنا‪ ،‬وحاول تجنُّب األسطر الطويلة لتسهيل قراءة الشيفرة‪.‬‬
‫‪223‬‬
‫|‬
‫▲‬
‫‪12‬‬
‫النوع ‪ :Tuple‬فهم‬
‫الصفوف‬
‫‪224‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫يبدو نوع البيانات ‪( tuple‬صف) في بايثون كما يلي‪:‬‬
‫‪coral = ('blue coral', 'staghorn coral', 'pillar coral',‬‬
‫)'‪'elkhorn coral‬‬
‫وتجمَ ع إلى ص فوف) هي بني ة بيان ات ُت ِّ‬
‫الن وع ‪( tuple‬ص ف ُ‬
‫مثل سلس لة مرتب ة من العناص ر‬
‫غير القابلة للتب ديل‪ ،‬وبالت الي ال يمكن تع ديل القيم الموج ودة فيه ا‪ .‬يس تعمل ن وع البيان ات ‪tuple‬‬
‫لتجميع البيانات‪ ،‬فكل عنصر أو قيمة داخل الصف ُت ِّ‬
‫جزءا منه‪ .‬توضع القيم داخل الص ف بين‬
‫ً‬
‫شكل‬
‫فصل بينه ا بفاص لة أجنبي ة ‪ ,‬وتب دو القيم الفارغ ة كم ا يلي )( = ‪ ،coral‬لكن إذا‬
‫قوسين ( ) ويُ َ‬
‫احت وى الص ف على قيم –ح تى ل و ك انت قيم ًة واح ً‬
‫دة فق ط– فيجب وض ع فاص لة في ه‬
‫مث ل )‪= ('blue coral',‬‬
‫‪ .coral‬إذا اس تخدمنا الدال ة )(‪ print‬على الن وع ‪،tuple‬‬
‫أن القيمة الناتجة ستوضع بين قوسين‪:‬‬
‫بين َّ‬
‫فسنحصل على الناتج اآلتي الذي يُ ّ‬
‫)‪print(coral‬‬
‫‪('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn‬‬
‫)'‪coral‬‬
‫عن د التفك ير ب النوع ‪ tuple‬وغ يره من ب نى البيان ات ال تي ُتع ُّد من أن واع «التجميع ات»‬
‫(‪ ،)collections‬فمن المفي د أن تض ع ببال ك مختل ف التجميع ات الموج ودة في حاس وبك‪ :‬تش كيلة‬
‫الملف ات الموج ودة عن دك‪ ،‬وق وائم التش غيل للموس يقى‪ ،‬والمفض لة الموج ودة في متص فحك‪،‬‬
‫ورس ائل بري دك اإللك تروني‪ ،‬ومجموع ة مق اطع الفي ديو ال تي تس تطيع الوص ول إليه ا من التلف از‪،‬‬
‫والكثير‪ .‬نوع ‪( tuple‬صف) شبيه بالنوع ‪( list‬قائمة)‪ ،‬لكن القيم الموجودة فيه ال يمكن تعديلها‪،‬‬
‫وبس بب ذل ك‪ ،‬ف أنت تخ بر اآلخ رين َّ‬
‫أنك ال تري د إج راء أيَّ ة تع ديالت على ه ذه السلس لة من القيم‬
‫عن دما تس تعمل الن وع ‪ tuple‬في ش يفرتك‪ .‬إض ً‬
‫افة إلى م ا س بق‪ ،‬ولع دم الق درة على تع ديل القيم‪،‬‬
‫‪225‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫ست َّ‬
‫فسيكون أداء برنامجك أفضل‪ ،‬حيث ُ‬
‫َ‬
‫تعملت الص فوف ب داًل من‬
‫نفذ الشيفرة بشكل أسرع إذا اس‬
‫القوائم (‪.)lists‬‬
‫‪ .1‬فهرسة الصفوف‬
‫يمكن الوصول إلى كل عنصر من عناصر الصف بمفرده َّ‬
‫ألنه سلسلة مرتب ة من العناص ر‪ ،‬وذل ك‬
‫عبر الفهرسة‪ .‬وكل عنص ر يرتب ط ب رقم فه رس‪ ،‬ال ذي ه و ع دد ص حيح يب دأ من الفه رس ‪ .0‬س تبدو‬
‫الفهارس من مثال ‪ coral‬السابق والقيم المرتبطة بها كاآلتي‪:‬‬
‫‪blue coral‬‬
‫‪staghorn coral‬‬
‫‪pillar coral‬‬
‫‪elkhorn coral‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫العنص ر األول ال ذي يُ ِّ‬
‫مثل السلس لة النص ية '‪ 'blue coral‬فهرس ه ‪ ،0‬وتنتهي القائم ة‬
‫وألن ك ل عنص ر من عناص ر الص ف ل ه رقم‬
‫بالفهرس رقم ‪ 3‬المرتبط بالقيم ة '‪.'elkhorn coral‬‬
‫َّ‬
‫فه رس مرتب ط ب ه‪ ،‬فس نتمكن من الوص ول إلى عناص ره ف رادى‪ .‬يمكنن ا اآلن الوص ول إلى عنص ر‬
‫معين في الصف عبر استخدام رقم الفهرس المرتبط به‪.‬‬
‫ّ‬
‫)]‪print(coral[2‬‬
‫‪pillar coral‬‬
‫تتراوح قيم الفهارس في المتغير ‪ coral‬من ‪ 0‬إلى ‪ 3‬كما ه و ظ اهر في الج دول الس ابق‪ ،‬ل ذا‬
‫يمكننا استدعاء العناصر الموجودة فيه فرادى كما يلي‪:‬‬
‫]‪coral[0‬‬
‫]‪coral[1‬‬
‫]‪coral[2‬‬
‫‪226‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫]‪coral[3‬‬
‫إذا حاولن ا اس تدعاء المتغ ير ‪ coral‬م ع رقم فه رس أك بر من ‪ ،3‬فس تظهر رس الة خط أ تش ير‬
‫أن الفهرس خارج المجال‪:‬‬
‫إلى َّ‬
‫)]‪print(coral[22‬‬
‫‪# IndexError: tuple index out of range‬‬
‫إض ً‬
‫ً‬
‫أيض ا الوص ول إلى الفه ارس باس تخدام رقم‬
‫افة إلى أرق ام الفه ارس الموجب ة‪ ،‬يمكنن ا‬
‫بدءا من نهاي ة قائم ة العناص ر وس يرتبط آخ ر عنص ر ب الفهرس ‪ ،-1‬وه ذا‬
‫ً‬
‫فهرس سالب‪ ،‬وذلك بالعد‬
‫َ‬
‫وأردت الوص ول إلى‬
‫مفي ٌد ج ًدا إذا كان لديك متغ ير من الن وع ‪ tuple‬وك ان يحت وي عناص ر كث يرة‬
‫ً‬
‫انطالق ا من النهاي ة‪ .‬ففي مثالن ا الس ابق عن ‪ ،coral‬إذا أردن ا اس تخدام الفه ارس‬
‫أح د عناص ره‬
‫السالبة فالناتج كاآلتي‪:‬‬
‫‪blue coral‬‬
‫‪staghorn coral‬‬
‫‪pillar coral‬‬
‫‪elkhorn coral‬‬
‫‪-4‬‬
‫‪-3‬‬
‫‪-2‬‬
‫‪-1‬‬
‫إذا أردن ا طباع ة العنص ر '‪ 'blue coral‬باس تخدام الفه ارس الس البة‪ ،‬فس تبدو التعليم ة‬
‫كما يلي‪:‬‬
‫)]‪print(coral[-4‬‬
‫‪blue coral‬‬
‫يمكننا إضافة العناصر النصية الموجودة في الص ف إلى السالس ل النص ية األخ رى باس تخدام‬
‫العامل ‪:+‬‬
‫‪227‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫)]‪print('This reef is made up of ' + coral[1‬‬
‫‪# This reef is made up of staghorn coral‬‬
‫اس تطعنا في المث ال الس ابق إض افة عنص ر موج ود في الفه رس ‪ 1‬م ع السلس لة النص ية‬
‫ً‬
‫أيضا استخدام العامل ‪ +‬إلضافة بنيتَي صف معً ا‪.‬‬
‫' ‪ ،'This reef is made up of‬ويمكننا‬
‫‪ .2‬تقطيع قيم صف‬
‫يمكنن ا اس تخدام الفه ارس للوص ول إلى ع ِّدة عناص ر من ص ف‪ ،‬أم ا التقطي ع فيس مح لن ا‬
‫بالوصول إلى ِّ‬
‫عدة قيم عبر إنشاء مجال من أرقام الفهارس المفص ولة بنقط تين رأس يتين [‪.]x:y‬‬
‫لنق ل َّ‬
‫أنن ا نري د ع رض العناص ر الموج ودة في وس ط المتغ ير ‪ ،coral‬يمكنن ا فع ل ذل ك بإنش اء‬
‫قطعة جديدة‪:‬‬
‫)]‪print(coral[1:3‬‬
‫)'‪('staghorn coral', 'pillar coral‬‬
‫ِّ‬
‫فيمثل أوَّ ل رقم مك ان ب دأ القطع ة‬
‫عن د إنش اء قطع ة جدي دة –كم ا في المث ال الس ابق–‬
‫ً‬
‫متضمنة هذا الفه رس)‪ ،‬ورقم الفه رس الث اني ه و مك ان نهاي ة القطع ة (دون تض مين ه ذا الفه رس‬
‫(‬
‫بالقطع ة)‪ ،‬وه ذا ه و الس بب وراء ع رض المث ال الس ابق للقيم المرتبط ة بالعناص ر الموج ودة في‬
‫َ‬
‫أردت تضمين إحدى نه ايتَي القائم ة‪ ،‬فيمكن ك ح ذف أح د األرق ام في التعب ير‬
‫الفهرسين ‪ 1‬و ‪ .2‬إذا‬
‫]‪ ،tuple[x:y‬فمثاًل ‪ ،‬لنق ل أنن ا نري د ع رض أوَّ ل ثالث ة عناص ر من ‪ ،coral‬وال تي هي‬
‫'‪ 'blue coral‬و '‪ 'staghorn coral‬و '‪ ،'pillar coral‬فيمكننا فعل ذلك كاآلتي‪:‬‬
‫)]‪print(coral[:3‬‬
‫)'‪('blue coral', 'staghorn coral', 'pillar coral‬‬
‫المثال السابق عرض العناصر من بداية القائم ة وتوق ف قب ل العنص ر ذي الفه رس ‪ .3‬لتض مين‬
‫‪228‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫كل العناصر الموجودة في نهاية الصف‪ ،‬فيمكننا عكس التعبير السابق‪:‬‬
‫)]‪print(coral[1:‬‬
‫)'‪# ('staghorn coral', 'pillar coral', 'elkhorn coral‬‬
‫ً‬
‫أيضا عند التقطيع‪ ،‬كما فعلنا مع أرقام الفهارس الموجبة‪:‬‬
‫يمكننا استخدام الفهارس السالبة‬
‫)]‪print(coral[-3:-1‬‬
‫)]‪print(coral[-2:‬‬
‫)'‪# ('staghorn coral', 'pillar coral‬‬
‫)'‪# ('pillar coral', 'elkhorn coral‬‬
‫هنال ك معام ٌ‬
‫افي يمكنن ا اس تعماله ويس مى «الخط وة»‪ ،‬ويُ ش ير إلى ع دد العناص ر ال تي‬
‫ل إض‬
‫ٌ‬
‫يجب تجاوزها بعد الحصول على أوّ ل عنصر من القائم ة‪ .‬ح ذفنا في جمي ع أمثلتن ا الس ابقة معام ل‬
‫الخط وة‪ ،‬إذ القيم ة االفتراض ية ل ه في ب ايثون هي ‪ ،1‬ل ذا سنحص ل على جمي ع العناص ر الموج ودة‬
‫الفهرس ين الم ذكورين‪ .‬ش كل ه ذا التعب ير الع ام ه و ]‪ ،tuple[x:y:z‬إذ يُ ش ير المعام ل ‪ z‬إلى‬
‫بين‬
‫َ‬
‫ً‬
‫قائمة أكبر‪ ،‬ثم ِّ‬
‫الخطوة‪ .‬ل ُن ِ‬
‫نقسمها‪ ،‬ونعطيها القيمة ‪ 2‬للخطوة‪:‬‬
‫نشئ‬
‫)‪numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12‬‬
‫)]‪print(numbers[1:11:2‬‬
‫)‪# (1, 3, 5, 7, 9‬‬
‫س تطبع التعليمة]‪ numbers[1:11:2‬القيم الموج ودة بين رقمين الفهرس ين ‪( 1‬بم ا في ذل ك‬
‫العنص ر المرتب ط ب الفهرس ‪ )1‬و ‪( 11‬دون تض مين ذل ك العنص ر)‪ ،‬ومن ثم س تخبر قيم ُة الخط وة ‪2‬‬
‫أن يتخطى عنص رً ا بين ك ل عنص رين‪ .‬يمكنن ا ح ذف أوَّ ل مع املين واس تخدام معام ل‬
‫البرن‬
‫َ‬
‫امج َّ‬
‫برمجي من الشكل ]‪:tuple[::z‬‬
‫بتعبير‬
‫الخطوة بمفرده‬
‫ٍ‬
‫ٍ‬
‫‪229‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫)]‪print(numbers[::3‬‬
‫)‪# (0, 3, 6, 9, 12‬‬
‫طبعن ا في المث ال الس ابق عناص ر ‪ numbers‬بع د ض بط قيم ة الخط وة إلى ‪ ،3‬وبالت الي س يتم‬
‫تخطي عنصرين‪.‬‬
‫‪0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12‬‬
‫تقطي ع الص فوف باس تخدام أرق ام الفه ارس الموجب ة والس البة واس تعمال معام ل الخط وة‬
‫يسمح لنا بالتحكم بالناتج الذي نريد عرضه‪.‬‬
‫‪ .3‬إضافة بنى صف إلى بعضها‬
‫يمكن أن ُنض يف ب نى ص ف إلى بعض ها أو أن «نض ربها» ( ‪ ،)multiply‬تتم عملي ة اإلض افة‬
‫باس تخدام المعام ل ‪ ،+‬أم ا عملي ة الض رب فباس تخدام المعام ل *‪ .‬يمكن أن يُ س تخ َدم المعام ل ‪+‬‬
‫ً‬
‫بعض ا‪ .‬يمكنن ا إس ناد القيم الموج ودة في ب نيتَي ص ف إلى‬
‫إلض افة ب نيتَي ص ف أو أك ثر إلى بعض ها‬
‫بنية جديدة‪:‬‬
‫‪coral = ('blue coral', 'staghorn coral', 'pillar coral',‬‬
‫)'‪'elkhorn coral‬‬
‫)'‪kelp = ('wakame', 'alaria', 'deep-sea tangle', 'macrocystis‬‬
‫)‪coral_kelp = (coral + kelp‬‬
‫)‪print(coral_kelp‬‬
‫الناتج‪:‬‬
‫‪('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn‬‬
‫)'‪coral', 'wakame', 'alaria', 'deep-sea tangle', 'macrocystis‬‬
‫‪230‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫أن المعام ل ‪ +‬يمكن ه إض افة ب نى ص ف إلى بعض ها‪ ،‬لكن يمكن أن يس تعمل إلنش اء‬
‫ٌ‬
‫وص‬
‫حيح َّ‬
‫بنية صف جديدة ناتجة عن جمع ب نى أخ رى‪ ،‬لكن ال يمكن ه تع ديل بني ة ص ف موج ودة مس ً‬
‫بقا‪ .‬أم ا‬
‫العام ل * فيمكن اس تخدامه لض رب ب نى ص ف‪ ،‬فربم ا تري د إنش اء نس خ من الملف ات الموج ودة في‬
‫أحد المجلدات إلى الخ ادوم أو مش اركة قائم ة بالمقطوع ات الموس يقية ال تي تحبه ا م ع أص دقائك‪،‬‬
‫ففي هذه الحاالت سترغب بمضاعفة مجموعات من البيانات (أو «ضربها»)‪ .‬لنضرب البنية ‪coral‬‬
‫بالرقم ‪ 2‬والبنية ‪ kelp‬بالرقم ‪ ،3‬ثم نسندها إلى بنى صف جديدة‪:‬‬
‫‪multiplied_coral = coral * 2‬‬
‫‪multiplied_kelp = kelp * 3‬‬
‫)‪print(multiplied_coral‬‬
‫)‪print(multiplied_kelp‬‬
‫الناتج‪:‬‬
‫‪('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn‬‬
‫‪coral', 'blue coral', 'staghorn coral', 'pillar coral',‬‬
‫)'‪'elkhorn coral‬‬
‫‪('wakame', 'alaria', 'deep-sea tangle', 'macrocystis',‬‬
‫‪'wakame', 'alaria', 'deep-sea tangle', 'macrocystis', 'wakame',‬‬
‫)'‪'alaria', 'deep-sea tangle', 'macrocystis‬‬
‫يمكنن ا باس تخدام العام ل * أن ُنك ِّرر (أو ُنض اعِ ف) ب نى ص ف ب أي ع دد من الم رات نش اء‪ ،‬مم ا‬
‫أن ب نى الص ف‬
‫سي ُن ِشئ بنى صف جديدة اعتما ًدا على محتوى البنى األصلية‪ .‬خالصة ما س بق هي َّ‬
‫َ‬
‫العاملين ‪ +‬و *‪.‬‬
‫يمكن إضافتها إلى بعضها أو ضربها لتشكيل بنى صف جديدة عبر استخدام‬
‫‪231‬‬
‫|‬
‫▲‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫البرمجة بلغة بايثون‬
‫‪ .4‬دوال التعامل مع الصفوف‬
‫هنالك دوال مُ ضمَّ نة في لغة بايثون للتعامل مع بنى النوع ‪ ،tuple‬لننظر إلى بعضها‪.‬‬
‫ا‪len() .‬‬
‫وكم ا في السالس ل النص ية والق وائم‪ ،‬يمكنن ا حس اب ط ول (أو ع دد عناص ر) بني ة ص ف‬
‫باستخدام الدالة )(‪ len‬إذ ُن ِّ‬
‫مرر إليها بنية صف (معامل)‪ ،‬كما يلي‪:‬‬
‫)‪len(coral‬‬
‫معين‪ ،‬فمثاًل يمكننا االستفادة‬
‫أن لبنية صف عدد عناصر‬
‫َّ‬
‫هذه الدالة مفيدة إذا أردنا أن َنضمَ ن َّ‬
‫من ذل ك بموازن ة بني تين م ع بعض هما‪ .‬إذا أردن ا طباع ة ع دد عناص ر ‪ kelp‬و ‪ ،numbers‬فس يظهر‬
‫الناتج اآلتي‪:‬‬
‫))‪print(len(kelp‬‬
‫))‪print(len(numbers‬‬
‫الناتج‪:‬‬
‫‪4‬‬
‫‪13‬‬
‫أن للبنية ‪ kelp‬أربعة عناصر‪:‬‬
‫يشير الناتج أعاله إلى َّ‬
‫)'‪kelp = ('wakame', 'alaria', 'deep-sea tangle', 'macrocystis‬‬
‫أمَّ ا البنية ‪ numbers‬فتملك ثالثة عشر عنصرًا‪:‬‬
‫)‪numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12‬‬
‫‪232‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫أن الدالة )(‪ len‬تس تطيع أن تخبرن ا بع دد‬
‫أن هذه األمثلة عناصرها قليلة‬
‫ٌ‬
‫نسبيا‪ ،‬إال َّ‬
‫وصحيح َّ‬
‫ً‬
‫عناصر بنى ‪ tuple‬الكبيرة‪.‬‬
‫ب‪ .‬الدالتان )(‪ max‬و )(‪min‬‬
‫عن دما نتعام ل م ع ب نى ص ف مكوَّ ن ة من عناص ر رقمي ة (بم ا فيه ا األع داد الص حيحة واألرق ام‬
‫ذات الفاصلة العشرية)‪ ،‬فيمكننا استخدام الدالتين )(‪ max‬و )(‪ min‬للعثور على أك بر وأص غر قيم ة‬
‫معين ة‪ .‬تس مح لن ا هات ان ال دالتان باس تخراج معلوم ات تخص البيان ات‬
‫موج ودة في بني ة ص ف‬
‫َّ‬
‫القابلة لإلحصاء‪ ،‬مثل نت ائج االمتحان ات أو درج ات الح رارة أو أس عار المنتج ات …إلخ‪ .‬لننظ ر إلى‬
‫بنية صف مكونة من أعداد عشرية‪:‬‬
‫‪more_numbers = (11.13, 34.87, 95.59, 82.49, 42.73, 11.12,‬‬
‫)‪95.57‬‬
‫للحصول على القيمة العظمى من بين القيم اآلتي ة فعلين ا تمري ر بني ة ص ف إلى الدال ة )(‪max‬‬
‫كما في )‪ ،max(more_numbers‬وسنستخدم الدالة )(‪ print‬لعرض الناتج‪:‬‬
‫))‪print(max(more_numbers‬‬
‫‪# 95.59‬‬
‫كل ش بيهٍ بم ا س بق نس تخدم‬
‫أعادت الدالة )(‪ max‬أعلى قيمة في بنية ‪ .more_numbers‬وبش ٍ‬
‫الدالة )(‪:min‬‬
‫))‪print(min(more_numbers‬‬
‫‪# 11.12‬‬
‫ُأ عي َد هن ا أص غر رقم عش ري موج ودة في البني ة‪ .‬يمكن االس تفادة من ال دالتين )(‪max‬‬
‫و )(‪ min‬كثيرً ا للتعامل مع بنى ‪ tuple‬التي تحتوي الكثير من القيم‪.‬‬
‫‪233‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫‪ .5‬كيف تختلف بنى الصفوف عن القوائم‬
‫الف رق الرئيس ي بين الن وع ‪ tuple‬والن وع ‪ list‬ه و ع دم الق درة على تع ديل العناص ر‪ ،‬وه ذا‬
‫يعني َّ‬
‫أنن ا ال نس تطيع إض افة أو ح ذف أو اس تبدال العناص ر داخ ل بني ة ‪ .tuple‬لكن يمكنن ا إض افة‬
‫ً‬
‫بعض ا لتش كيل بني ة جدي دة كم ا رأين ا في أح د األقس ام الس ابقة‪.‬‬
‫ب نيتَي ‪ tuple‬أو أك ثر إلى بعض ها‬
‫لتكن لدينا البنية ‪ coral‬اآلتية‪:‬‬
‫‪coral = ('blue coral', 'staghorn coral', 'pillar coral',‬‬
‫)'‪'elkhorn coral‬‬
‫لنقل أننا نريد استبدال العنصر '‪ 'blue coral‬ووضع العنصر '‪ 'black coral‬بداًل منه‪.‬‬
‫فلو حاولنا تغيير بنية صف بنفس الطريقة التي ُن ِّ‬
‫عدل فيها القوائم بكتابة‪:‬‬
‫'‪coral[0] = 'black coral‬‬
‫فستظهر رسالة خطأ كاآلتية‪:‬‬
‫‪TypeError: 'tuple' object does not support item assignment‬‬
‫أن ما نحتاج له‬
‫وذلك بسبب عدم إمكانية تعديل بنى الصفوف‪ .‬إذا أنشأنا بنية صف ثم قررنا َّ‬
‫هو بنية قائمة‪ ،‬فيمكننا تحويلها إلى قائمة ‪ ،list‬وذلك بالدالة )(‪:list‬‬
‫)‪list(coral‬‬
‫ً‬
‫قائمة اآلن‪:‬‬
‫أصبحت بنية ‪coral‬‬
‫]'‪coral = ['blue coral', 'staghorn coral', 'pillar coral‬‬
‫أن بني ة الص ف ‪ tuple‬تح وَّ َ‬
‫ألن األق واس المحيط ة‬
‫لت إلى قائم ة ‪َّ list‬‬
‫يمكنن ا أن نالح ظ َّ‬
‫بالقيم أصبحت مربعة الشكل‪.‬‬
‫‪234‬‬
‫|‬
‫▲‬
‫النوع ‪ :Tuple‬فهم الصفوف‬
‫البرمجة بلغة بايثون‬
‫كل ش بيهٍ بم ا س بق‪ ،‬نس تطيع تحوي ل الق وائم من الن وع ‪ list‬إلى ‪ tuple‬باس تخدام‬
‫وبش ٍ‬
‫الدالة )(‪.tuple‬‬
‫‪ .6‬خالصة الفصل‬
‫نوع البيانات ‪( tuple‬الصفوف) ه و مجموع ٌة من البيان ات المتسلس لة ال تي ال يمكن تع ديلها‪،‬‬
‫وي ِّ‬
‫وفر تحس ينًا في أداء برامج ك ألن ه أس رع معالج ًة من الق وائم في ب ايثون‪ .‬وعن دما يراج ع‬
‫اآلخرون شيفرتك فس يعلمون من اس تخدامك لب نى ‪ tuple‬أن ك ال تري د تع ديل ه ذه القيم‪ .‬ش رحنا‬
‫في هذا الفصل الميزات األساسية لبنى ‪ tuple‬بما في ذلك الفهارس وتقطيعها وتجميعها‪ ،‬وعرضنا‬
‫بعض الدوال المُ ضمَّ نة المتوافرة لهذا النوع من البيانات‪.‬‬
‫‪235‬‬
‫|‬
‫▲‬
‫‪13‬‬
‫النوع ‪:Dictionary‬‬
‫فهم القواميس‬
‫‪236‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫الن وع ‪( dictionary‬الق اموس) ه و ن وع مُ ض مَّ ن في ب ايثون‪ .‬ترب ط الق واميس مف اتيح بقيم‬
‫على هيئة أزواج‪ ،‬وهذه األزواج مفيدة لتخزين البيانات في بايثون‪.‬‬
‫ً‬
‫عادة لتخزين البيانات المترابطة‪ ،‬مثل المعلومات المرتبطة برقم تعريف‪،‬‬
‫تستخدم القواميس‬
‫أو ملفات تعريف المستخدم‪ُ ،‬‬
‫وتنشأ باستخدام األقواس المعقوصة {}‪.‬‬
‫تبدو القواميس على الشكل التالي‪:‬‬
‫‪sammy = {'username': 'sammy-shark', 'online': True,‬‬
‫}‪'followers': 987‬‬
‫باإلض افة إلى القوس ين المعقوص ين‪ ،‬الح ظ وج ود النقط تين الرأس يتين (‪ ):‬في الق اموس‪.‬‬
‫أي ن وع‬
‫الكلم ات الموج ودة على يس ار النقط تين الرأس يتين هي المف اتيح (‪ )keys‬ال تي ق د تك ون َّ‬
‫بيانات غير قابل للتغيير‪ .‬المفاتيح في القاموس أعاله هي‪:‬‬
‫•‬
‫‪username‬‬
‫•‬
‫‪online‬‬
‫•‬
‫‪followers‬‬
‫المفاتيح في المثال أعاله عبارة عن سالسل نصية‪.‬‬
‫ِّ‬
‫تمثل الكلم ات الموج ودة على يمين النقط تين «القيم» (‪ .)values‬يمكن أن تت ألف القيم من‬
‫أي نوع من البيانات‪ .‬القيم في القاموس أعاله هي‪:‬‬
‫•‬
‫‪sammy-shark‬‬
‫•‬
‫‪True‬‬
‫•‬
‫‪87‬‬
‫‪237‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫قيم الق اموس أعاله هي إمَّ ا سالس ل نص ية أو قيم منطقي ة أو أع داد ص حيحة‪ .‬س نطبع اآلن‬
‫القاموس ‪:sammy‬‬
‫)‪print(sammy‬‬
‫الناتج‪:‬‬
‫}‪{'username': 'sammy-shark', 'followers': 987, 'online': True‬‬
‫نالح ظ ب النظر إلى المخرج ات تغ ير ت رتيب األزواج قيم ة‪-‬مفت اح (‪ .)key-value‬في اإلص دار‬
‫داء من ب ايثون ‪ ،3.6‬ص ارت الق واميس‬
‫ب ايثون ‪ 3.5‬وم ا قبل ه‪ ،‬ك انت الق واميس غ ير مرتب ة‪ .‬لكن ابت ً‬
‫مرتب ا أم ال‪ ،‬س تظل األزواج قيم ة‪-‬مفت اح كم ا هي‪ ،‬وه ذا‬
‫مرتب ًة‪ .‬بغض النظ ر عم ا إذا ك ان الق اموس‬
‫ً‬
‫ِّ‬
‫سيمكنك من الوصول إلى البيانات بناء على ترابطاتها‪.‬‬
‫‪ .1‬الوصول إلى عناصر قاموس‬
‫يمكنن ا الوص ول إلى قيم مح َّددة في الق اموس ب الرجوع إلى المف اتيح المرتبط ة به ا ويمكن‬
‫ً‬
‫أيضا االستعانة ببعض التوابع الجاهزة للوصول إلى القيم أو المفاتيح أو كليهما‪.‬‬
‫ا‪ .‬الوصول إلى عناصر القاموس باستخدام المفاتيح‬
‫إذا أردن ا الحص ول على اس م المس تخدم في ‪ ،Sammy‬فيمكنن ا ذل ك عن طري ق‬
‫استدعاء ]'‪ .sammy['username‬هذا مثال على ذلك‪:‬‬
‫‪sammy-shark‬‬
‫‪#‬‬
‫)]'‪print(sammy['username‬‬
‫‪238‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫تتصرف القواميس مثل قواعد البيان ات‪ ،‬فهي ب داًل من فهرس ة العناص ر بأع داد ص حيحة‪ ،‬كما‬
‫ه و الح ال في الق وائم‪ِّ ،‬‬
‫فإنه ا ُتفه رس العناص ر (أو قيم الق اموس) بمف اتيح‪ ،‬ويمكن ك ع بر تل ك‬
‫المفاتيح الحصول على القيم المقابلة لها‪.‬‬
‫باس تدعاء المفت اح ‪ ،username‬سنحص ل على القيم ة المرتبط ة ب ه‪ ،‬وهي ‪.sammy-shark‬‬
‫وبالمِ ثل‪ ،‬يمكن استدعاء القيم األخرى في القاموس ‪ sammy‬باستخدام نفس الصياغة‪:‬‬
‫‪# 987‬‬
‫‪# True‬‬
‫]'‪sammy['followers‬‬
‫]'‪sammy['online‬‬
‫ب‪ .‬استخدام التوابع للوصول إلى العناصر‬
‫ً‬
‫أيض ا اس تخدام بعض التواب ع‬
‫باإلض افة إلى اس تخدام المف اتيح للوص ول إلى القيم‪ ،‬يمكنن ا‬
‫المُ ضمّ نة‪ ،‬مثل‪:‬‬
‫•‬
‫)(‪ :dict.keys‬الحصول على المفاتيح‬
‫•‬
‫)(‪ :dict.values‬الحصول على القيم‬
‫•‬
‫)(‪ :dict.items‬الحصول على العناصر على هيئة قائمة من أزواج (‪)key, value‬‬
‫إلعادة المفاتيح‪ ،‬نستخدم التابع )(‪ ،dict.keys‬كما يوضح المثال التالي‪:‬‬
‫))(‪print(sammy.keys‬‬
‫)]'‪dict_keys(['followers', 'username', 'online‬‬
‫‪#‬‬
‫كائن ع رض تك راري (‪ )iterable view object‬من الص نف ‪dict_keys‬‬
‫تلقينا في المخرجات‬
‫َ‬
‫يحوي المفاتيح ثم ُط ِبعت المفاتيح على هيئة قائمة‪.‬‬
‫‪239‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫يمكن اس تخدام ه ذا الت ابع لالس تعالم من الق واميس‪ .‬على س بيل المث ال‪ ،‬يمكنن ا البحث عن‬
‫المفاتيح المشتركة بين قاموسين‪:‬‬
‫‪sammy = {'username': 'sammy-shark', 'online': True,‬‬
‫}‪'followers': 987‬‬
‫‪jesse = {'username': 'JOctopus', 'online': False, 'points':‬‬
‫}‪723‬‬
‫‪for common_key in sammy.keys() & jesse.keys():‬‬
‫)]‪print(sammy[common_key], jesse[common_key‬‬
‫أن لهم ا مف اتيح‬
‫يح وي القاموس ان ‪ sammy‬و ‪ jesse‬معلوم ات تعري ف المس تخدم‪ .‬كم ا َّ‬
‫ً‬
‫مفتاح ا ‪ followers‬يمث ل المت ابعين على‬
‫ألن ل دى ‪ Sammy‬مل ف تعري ف اجتم اعي يض م‬
‫مختلف ة‪َّ ،‬‬
‫ً‬
‫مفتاح ا ‪ points‬يمث ل النق اط‪ .‬كال‬
‫الشبكة االجتماعية‪ ،‬أما ‪ Jesse‬فلها مل ف تعري ف لأللع اب يض م‬
‫القاموس ين يش تركان في المفت احين ‪ username‬و ‪ ،online‬ويمكن العث ور عليهم ا عن د تنفي ذ‬
‫البريمج‪:‬‬
‫هذا ُ‬
‫‪sammy-shark JOctopus‬‬
‫‪True False‬‬
‫ولكن الغ رض هن ا ه و توض يح‬
‫يمكنن ا بالتأكي د تحس ين البرن امج لتس هيل ق راءة المخرج ات‪،‬‬
‫َّ‬
‫إمكانية اس تخدام )(‪ dict.keys‬لرص د المف اتيح المش تركة بين ع َّدة ق واميس‪ .‬ه ذا مفي د بش كل‬
‫خاص عند العمل على القواميس الكبيرة‪.‬‬
‫وبالمث ل‪ ،‬يمكنن ا اس تخدام الت ابع )(‪ dict.values‬لالس تعالم عن القيم الموج ودة في‬
‫القاموس ‪ sammy‬على النحو التالي‪:‬‬
‫‪240‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫‪sammy = {'username': 'sammy-shark', 'online': True,‬‬
‫}‪'followers': 987‬‬
‫‪dict_values([True, 'sammy-shark',‬‬
‫‪#‬‬
‫))(‪print(sammy.values‬‬
‫)]‪987‬‬
‫يُ عي د كال الت ابعين )(‪ values‬و )(‪ keys‬ق وائم غ ير مرتب ة تض م مف اتيح وقيم الق اموس‬
‫عرض من الصنف ‪ dict_values‬و ‪ dict_keys‬على التوالي‪.‬‬
‫ٍ‬
‫‪ sammy‬على هيئة كاِئني‬
‫إن أردت الحصول على األزواج الموجودة في القاموس‪ ،‬فاستخدم التابع )(‪:items‬‬
‫))(‪print(sammy.items‬‬
‫المخرجات ستكون‪:‬‬
‫‪dict_items([('online', True), ('username', 'sammy-shark'),‬‬
‫)])‪('followers', 987‬‬
‫س تكون النتيج ة المع ادة على هيئ ة قائم ة مكون ة من أزواج (‪value‬‬
‫‪ )key,‬من‬
‫الصنف ‪.dict_items‬‬
‫يمكنن ا التك رار (‪ )iterate‬على القائم ة المُ ع ادة باس تخدام الحلق ة ‪ .for‬على س بيل المث ال‪،‬‬
‫يمكنن ا طباع ة جمي ع مف اتيح وقيم الق اموس المح دد‪ ،‬ثم جعله ا أك ثر مقروئي ة ع بر إض افة سلس لة‬
‫نصية توضيحية‪:‬‬
‫‪for key, value in sammy.items():‬‬
‫)‪print(key, 'is the key for the value', value‬‬
‫وسينتج لنا‪:‬‬
‫‪241‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫‪online is the key for the value True‬‬
‫‪followers is the key for the value 987‬‬
‫‪username is the key for the value sammy-shark‬‬
‫ك رَّ رت الحلق ة ‪ for‬على العناص ر الموج ودة في الق اموس ‪ ،sammy‬وطبعت المف اتيح والقيم‬
‫سط ًرا سطرًا‪ ،‬مع إضافة معلومات توضيحية‪.‬‬
‫‪ .2‬تعديل القواميس‬
‫الق واميس هي هياك ل بيان ات قابل ة للتغي ير (‪ ،)mutable‬أي يمكن تع ديلها‪ .‬في ه ذا القس م‪،‬‬
‫سنتعلم كيفية إضافة عناصر إلى قاموس‪ ،‬وكيفية حذفها‪.‬‬
‫ا‪ .‬إضافة وتغيير عناصر القاموس‬
‫يمكن ك إض افة أزواج قيم ة‪-‬مفت اح إلى ق اموس دون اس تخدام تواب ع أو دوال باس تخدام‬
‫الصياغة التالية‪:‬‬
‫‪dict[key] = value‬‬
‫ً‬
‫زوجا مفتاح‪-‬قيمة إلى قاموس يُ سمى ‪:usernames‬‬
‫في المثال التالي‪ ،‬سنضيف‬
‫}'‪usernames = {'Sammy': 'sammy-shark', 'Jamie': 'mantisshrimp54‬‬
‫'‪usernames['Drew'] = 'squidly‬‬
‫‪{'Drew': 'squidly', 'Sammy': 'sammy-‬‬
‫‪#‬‬
‫)‪print(usernames‬‬
‫}'‪shark', 'Jamie': 'mantisshrimp54‬‬
‫أن القاموس قد تم تحديثه بالزوج '‪.'Drew': 'squidly‬‬
‫الحظ َّ‬
‫‪242‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫أي مك ان في مخرج ات‬
‫ألن الق واميس غ ير مرتب ة‪ ،‬فيمكن أن يظه ر ال زوج المُ ض اف في ِّ‬
‫نظ رًا َّ‬
‫ً‬
‫الحقا‪ ،‬فسيظهر فيه الزوج المضاف حدي ًثا‪.‬‬
‫القاموس‪ .‬إذا استخدمنا القاموس ‪usernames‬‬
‫معين‪ .‬في هذه الحالة‪ ،‬سنش ير‬
‫يمكن استخدام هذه الصياغة لتعديل القيمة المرتبطة بمفتاح‬
‫َّ‬
‫ً‬
‫ِّ‬
‫ونمرر قيمة مختلفة إليه‪.‬‬
‫سلفا‪،‬‬
‫إلى مفتاح موجود‬
‫قاموس ا باس م ‪ِّ drew‬‬
‫س ِّ‬
‫يمثل البيان ات الخاص ة بأح د المس تخدمين‬
‫نعرف في المث ال الت الي‬
‫ً‬
‫على بعض الشبكات االجتماعية‪ .‬حص ل ه ذا المس تخدم على ع دد من المت ابعين اإلض افيين الي وم‪،‬‬
‫أن‬
‫لذلك سنح ّدث القيمة المرتبطة بالمفتاح ‪ followers‬ثم نس تخدم الت ابع )(‪ print‬للتحق ق من ّ‬
‫القاموس قد عُ ِّدل‪.‬‬
‫‪drew = {'username': 'squidly', 'online': True, 'followers':‬‬
‫}‪305‬‬
‫‪drew['followers'] = 342‬‬
‫)‪print(drew‬‬
‫}‪{'username': 'squidly', 'followers': 342, 'online': True‬‬
‫‪#‬‬
‫أن عدد المتابعين قد قفز من ‪ 305‬إلى ‪.342‬‬
‫في المخرجات نرى ّ‬
‫يمكنن ا اس تخدام ه ذه الطريق ة إلض افة أزواج قيم ة‪-‬مفت اح إلى الق واميس ع بر م دخالت‬
‫ً‬
‫بريمج ا س ريعً ا‪ ،usernames.py ،‬يعم ل من س طر األوام ر ويس مح للمس تخدم‬
‫المستخدم‪ .‬س نكتب‬
‫بإضافة األسماء وأسماء المستخدمين المرتبطة بها‪:‬‬
‫‪243‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫تعريف القاموس األصلي ‪#‬‬
‫}'‪usernames = {'Sammy': 'sammy-shark', 'Jamie': 'mantisshrimp54‬‬
‫إعداد الحلقة التكرارية ‪# while‬‬
‫‪while True:‬‬
‫اطلب من المستخدم إدخال اسم ‪#‬‬
‫)'‪print('Enter a name:‬‬
‫تعيين المدخالت إلى المتغير ‪# name‬‬
‫)(‪name = input‬‬
‫ًا في القاموس ثم اطبع الرد ‪#‬‬
‫تحقق مما إذا كان االسم موجود‬
‫‪if name in usernames:‬‬
‫)‪print(usernames[name] + ' is the username of ' + name‬‬
‫إذا لم يكن االسم في القاموس ‪#‬‬
‫‪else:‬‬
‫اطبع الرد ‪#‬‬
‫‪print('I don\'t have ' + name + '\'s username, what is‬‬
‫)'?‪it‬‬
‫خذ اسم مستخدم جديد لربطه بذلك االسم ‪#‬‬
‫)(‪username = input‬‬
‫عين قيمة اسم المستخدم إلى المفتاح ‪# name‬‬
‫‪usernames[name] = username‬‬
‫ّثت ‪#‬‬
‫ّ البيانات قد حُد‬
‫ّن أن‬
‫ًا يبي‬
‫اطبع رد‬
‫)'‪print('Data updated.‬‬
‫ِّ‬
‫سننفذ البرنامج من سطر األوامر‪:‬‬
‫‪python usernames.py‬‬
‫‪244‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫عندما ِّ‬
‫ننفذ البرنامج‪ ،‬سنحصل على مخرجات مشابهة لما يلي‪:‬‬
‫‪Enter a name:‬‬
‫‪Sammy‬‬
‫‪sammy-shark is the username of Sammy‬‬
‫‪Enter a name:‬‬
‫‪Jesse‬‬
‫?‪I don't have Jesse's username, what is it‬‬
‫‪JOctopus‬‬
‫‪Data updated.‬‬
‫‪Enter a name:‬‬
‫عن د االنته اء من اختب ار البرن امج‪ ،‬اض غط على ‪ CTRL + C‬للخ روج من البرن امج‪ .‬يمكن ك‬
‫تخص يص ح رف إلنه اء البرن امج (مث ل الح رف ‪ ،)q‬وجع ل البرن امج يُ نص ت ل ه ع بر‬
‫التعليمات الشرطية‪.‬‬
‫يوضح ه ذا المث ال كي ف يمكن ك تع ديل الق واميس بش كل تف اعلي‪ .‬في ه ذا البرن امج‪ ،‬بمج رد‬
‫خروجك باستخدام ‪ ،CTRL + C‬ستفقد جميع بياناتك‪ ،‬إال إن ّ‬
‫خزنَت البيانات في ملف‪.‬‬
‫ً‬
‫أيضا إضافة عناصر إلى القواميس وتعديلها باس تخدام الت ابع )(‪ .dict.update‬ه ذا‬
‫يمكننا‬
‫التابع مختلف عن التابع )(‪ append‬الذي يُ ستخدم مع القوائم‪.‬‬
‫سنض يف المفت اح ‪ followers‬في الق اموس ‪ jesse‬أدن اه‪ ،‬و َنمنح ه قيم ة عددي ة ص حيحة‬
‫بواسطة التابع )(‪ .jesse.update‬بعد ذلك‪ ،‬سنطبع القاموس المُ ح َّدث‪.‬‬
‫‪jesse = {'username': 'JOctopus', 'online': False, 'points':‬‬
‫}‪723‬‬
‫)}‪jesse.update({'followers': 481‬‬
‫‪{'followers': 481, 'username': 'JOctopus',‬‬
‫‪#‬‬
‫)‪print(jesse‬‬
‫‪245‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫}‪'points': 723, 'online': False‬‬
‫نتبين من المخرجات َّ‬
‫أننا نجحنا في إضافة الزوج ‪ followers: 481‬إلى القاموس ‪.jesse‬‬
‫َّ‬
‫أيض ا اس تخدام الت ابع )(‪ dict.update‬لتع ديل زوج قيم ة‪-‬مفت اح موج ود س ً‬
‫ً‬
‫لفا عن‬
‫يمكنن ا‬
‫معين‪.‬‬
‫طريق استبدال قيمة مفتاح‬
‫َّ‬
‫سنغيِّ ر القيمة المرتبطة بالمفتاح ‪ online‬في القاموس ‪ Sammy‬من ‪ True‬إلى ‪:False‬‬
‫‪sammy = {'username': 'sammy-shark', 'online': True,‬‬
‫}‪'followers': 987‬‬
‫)}‪sammy.update({'online': False‬‬
‫‪{'username': 'sammy-shark', 'followers': 987,‬‬
‫‪#‬‬
‫)‪print(sammy‬‬
‫}‪'online': False‬‬
‫يغي ر الس طر )}‪False‬‬
‫ّ‬
‫‪ sammy.update({'online':‬القيم ة المرتبط ة بالمفت اح‬
‫'‪ 'online‬من ‪ True‬إلى ‪ .False‬عن د اس تدعاء الت ابع )(‪ print‬على الق اموس‪ ،‬يمكن ك أن ت رى‬
‫أن التحديث قد تمّ‪.‬‬
‫في المخرجات َّ‬
‫إلض افة عناص ر إلى الق واميس أو تع ديل القيم‪ ،‬يمكن إمّ‬
‫ا اس تخدام الص ياغة‬
‫‪ ،dict[key] = value‬أو التابع )(‪.dict.update‬‬
‫‪ .3‬حذف عناصر من القاموس‬
‫ً‬
‫أيض ا ح ذف‬
‫كم ا يمكن ك إض افة أزواج قيم ة‪-‬مفت اح إلى الق اموس‪ ،‬أو تغي ير قيم ه‪ ،‬يمكن ك‬
‫العناصر الموجودة في القاموس‪.‬‬
‫لتزيل زوج قيمة‪-‬مفتاح من القاموس‪ ،‬استخدم الصياغة التالية‪:‬‬
‫‪246‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫]‪del dict[key‬‬
‫أن ‪ jesse‬لم تع د تس تخدم‬
‫لنأخذ القاموس ‪ jesse‬الذي يمثل أحد المس تخدمين‪ ،‬ولنف ترض َّ‬
‫المنصة ألجل ممارسة األلع اب‪ ،‬ل ذلك س نزيل العنص ر المرتب ط بالمفت اح ‪ .points‬بع د ذل ك‪ ،‬س نطبع‬
‫القاموس لتأكيد حذف العنصر‪:‬‬
‫‪jesse = {'username': 'JOctopus', 'online': False, 'points':‬‬
‫}‪723, 'followers': 481‬‬
‫]'‪del jesse['points‬‬
‫)‪print(jesse‬‬
‫‪#‬‬
‫}‪{'online': False, 'username': 'JOctopus', 'followers': 481‬‬
‫يزيل السطر ]'‪ del jesse ['points‬الزوج '‪ points': 723‬من القاموس ‪.jesse‬‬
‫إذا أردت مح و جمي ع عناص ر الق اموس‪ ،‬فيمكن ك ذل ك باس تخدام الت ابع )(‪.dict.clear‬‬
‫ً‬
‫الحق ا في البرن امج‪،‬‬
‫سي بقى هذا القاموس في الذاكرة‪ ،‬وهذا مفيد في حال احتجنا إلى استخدامه‬
‫َ‬
‫سي ِّ‬
‫فرغ جميع العناصر من القاموس‪.‬‬
‫بيد أنه ُ‬
‫ْ‬
‫دعنا نزيل كل عناصر القاموس ‪:jesse‬‬
‫‪jesse = {'username': 'JOctopus', 'online': False, 'points':‬‬
‫}‪723, 'followers': 481‬‬
‫)(‪jesse.clear‬‬
‫}{‬
‫‪#‬‬
‫)‪print(jesse‬‬
‫ً‬
‫فارغا اآلن‪.‬‬
‫أن القاموس صار‬
‫ظهر المخرجات َّ‬
‫ُت ِ‬
‫إذا لم تعد بحاجة إلى القاموس‪ ،‬فاستخدم ‪ del‬للتخلص منه بالكامل‪:‬‬
‫‪247‬‬
‫|‬
‫▲‬
‫النوع ‪ :Dictionary‬فهم القواميس‬
‫البرمجة بلغة بايثون‬
‫‪del jesse‬‬
‫)‪print(jesse‬‬
‫إذا ّ‬
‫نفذت األمر )(‪ print‬بعد حذف القاموس ‪ ،jesse‬سوف تتلقى الخطأ التالي‪:‬‬
‫‪NameError: name 'jesse' is not defined‬‬
‫‪ .4‬خالصة الفصل‬
‫ألقين ا في ه ذا الفص ل نظ رة على الن وع ‪( dictionary‬الق واميس) في ب ايثون‪ .‬تت ألف‬
‫الق واميس (‪ )dictionaries‬من أزواج قيم ة‪-‬مفت اح‪ ،‬وت وفر حاًّل ممت ً‬
‫ازا لتخ زين البيان ات دون‬
‫اء على معانيه ا وعالقته ا ب أنواع‬
‫الحاج ة إلى فهرس تها‪ .‬ي تيح لن ا ذل ك اس ترداد القيم بن ً‬
‫البيانات األخرى‪.‬‬
‫إن لم تطلع على فصل فهم أنواع البيانات‪ ،‬فيمكنك الرجوع إلي ه للتع رف على أن واع البيان ات‬
‫األخرى الموجودة في بايثون‪.‬‬
‫‪248‬‬
‫|‬
‫▲‬
‫‪14‬‬
‫التعليمات الشرطية‬
‫‪249‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫ال تخلو لغة برمج ة من التعليم ات الش رطية (‪ )conditional statement‬ال تي ُت َّ‬
‫اء على‬
‫نفذ بن ً‬
‫تحقق شرط معين‪ ،‬وهي تعليمات برمجية يمكنها التحكم في تنفيذ شيفرات معينة بحسب تحق ق‬
‫شرط ما من عدمه في وقت التنفيذ‪.‬‬
‫ُت َّ‬
‫نفذ تعليم ات ب رامج ب ايثون من األعلى إلى األس فل‪ ،‬م ع تنفي ذ ك ل س طر بحس ب ترتيب ه‪.‬‬
‫باستخدام التعليم ات الش رطية‪ ،‬يمكن لل برامج التحق ق من اس تيفاء ش روط معين ة‪ ،‬ومن ثم تنفي ذ‬
‫الشيفرة المقابلة‪.‬‬
‫هذه بعض األمثلة التي سنستخدم فيها التعليمات الشرطية‪:‬‬
‫•‬
‫إن حص لت طالب ة على أك ثر من ‪ ٪65‬في االمتح ان‪ ،‬ف أعلن عن نجاحه ا؛ وإال‪ ،‬ف أعلن‬
‫عن رسوبها‬
‫•‬
‫إذا كان لديه مال في حسابه‪ ،‬فاحسب الفائدة‪ .‬وإال‪ ،‬فاحسب غرامة‬
‫•‬
‫إن اشتروا ‪ 10‬برتقاالت أو أكثر‪ ،‬فاحسب خصمً ا بمقدار ‪٪5‬؛ وإال فال تفعل‬
‫شروطا‪ ،‬ثم ُت ِّ‬
‫ً‬
‫ً‬
‫اء على م ا إذا تحققت تل ك الش روط أم ال‪.‬‬
‫يفرة بن ً‬
‫نفذ ش‬
‫تقيِّ م الشيفرة الشرطية‬
‫كيفية كتابة التعليمات الشرطية في بايثون‪.‬‬
‫ستتعلم في هذا الفصل‬
‫َّ‬
‫‪ .1‬التعليمة ‪if‬‬
‫سنبدأ بالتعليمة ‪ ،if‬والتي تتحقق مما إذا تحقق شرط مح َّدد أم ال‪ ،‬وفي حال تحق ق الش رط‪،‬‬
‫َّ‬
‫فستنفذ الشيفرة المقابلة له‪ .‬لنبدأ بأمثلة عملية توضح ذلك‪ .‬افتح ً‬
‫ملفا‪ ،‬واكتب الشيفرة التالية‪:‬‬
‫‪grade = 70‬‬
‫‪if grade >= 65:‬‬
‫)"درجة النجاح"(‪print‬‬
‫‪250‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫أعطين ا للمتغ ير ‪ grade‬القيم ة ‪ .70‬ثمَّ اس تخدمنا التعليم ة ‪ if‬لتق ييم م ا إذا ك ان المتغ ير‬
‫‪ grade‬أك بر من (=>) أو يس اوي ‪ .65‬وفي تل ك الحال ة‪ ،‬س يطبع البرن امج السلس لة النص ية التالي ة‪:‬‬
‫"درجة النجاح"‪.‬‬
‫احف ظ البرن امج باالس م ‪ ،grade.py‬ثم ِّ‬
‫نفذه في بيئ ة البرمج ة المحلي ة من ناف ذة الطرفي ة‬
‫باستخدام األمر ‪ .python grade.py‬في هذه الحالة‪ ،‬الدرجة ‪ 70‬تل بي الش رط‪ّ ،‬‬
‫ألنه ا أك بر من ‪،65‬‬
‫لذلك ستحصل على المخرجات التالية عند تنفيذ البرنامج‪:‬‬
‫درجة النجاح‬
‫لنغير اآلن نتيجة هذا البرنامج عبر تغيير قيمة المتغير ‪ grade‬إلى ‪:60‬‬
‫ّ‬
‫‪grade = 60‬‬
‫‪if grade >= 65:‬‬
‫)"درجة النجاح"(‪print‬‬
‫ألن الش رط لم يتحق ق‪ ،‬ولم ن أمر‬
‫بع د حف ظ وتنفي ذ الش يفرة‪ ،‬لن نحص ل على أي مخرج ات‪ّ ،‬‬
‫البرنامج بتنفيذ تعليمة أخرى‪.‬‬
‫َّ‬
‫نتحقق مم ا إذا ك ان رص يد الحس اب المص رفي أق ل من ‪ .0‬لننش ئ ملف ا باس م‬
‫مثال آخر‪ ،‬دعن ا‬
‫‪ ،account.py‬ونكتب البرنامج التالي‪:‬‬
‫‪balance = -5‬‬
‫‪if balance < 0:‬‬
‫)"‪.‬الحساب فارغ‪ ،‬أضف مبلغا اآلن‪ ،‬أو ستحصل على غرامة"(‪print‬‬
‫‪251‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫عند تنفيذ البرنامج باستخدام ‪ ،python account.py‬سنحصل على المخرجات التالية‪:‬‬
‫‪.‬الحساب فارغ‪ ،‬أضف مبلً‬
‫غا اآلن‪ ،‬أو ستحصل على غرامة‬
‫أعطينا للمتغ ير ‪ balance‬القيم ة ‪ ،-5‬وهي أق ل من ‪ 0‬في البرن امج الس ابق‪ .‬ولمَّ ا ك ان الرص يد‬
‫توفيا لش رط التعليم ة ‪( if‬أي ‪ ،)balance < 0‬فسنحص ل على سلس لة نص ية في المخرج ات‬
‫مس‬
‫ً‬
‫بمجرد حفظ الشيفرة وتنفيذها‪ .‬مرة أخرى‪ ،‬لو غيرنا الرصيد إلى القيمة ‪ 0‬أو إلى عدد م وجب‪ ،‬فلن‬
‫أي مخرجات‪.‬‬
‫نحصل على ّ‬
‫‪ .2‬التعليمة ‪else‬‬
‫ق د تري د من البرن امج أن يفع ل ش يًئا م ا في ح ال ع دم تحق ق ش رط التعليم ة ‪ .if‬في المث ال‬
‫أعاله‪ ،‬نريد طباعة مخرجات في حال النجاح والرسوب‪ .‬ولفع ل ذل ك‪ ،‬سنض يف التعليم ة ‪ else‬إلى‬
‫شرط الدرجة أعاله وفق الصياغة التالية‪:‬‬
‫‪grade = 60‬‬
‫‪if grade >= 65:‬‬
‫)"درجة النجاح"(‪print‬‬
‫‪else:‬‬
‫)"درجة الرسوب"(‪print‬‬
‫إن‬
‫قيم ة المتغ ير ‪ grade‬تس اوي ‪ ،60‬ل ذلك فش رط التعليم ة ‪ if‬غ ير متحق ق‪ ،‬وبالت الي ف َّ‬
‫أن عليه طباع ة السلس لة‬
‫البرنامج لن يطبع السلسلة "درجة النجاح"‪ .‬تخبر التعليمة ‪else‬‬
‫َ‬
‫البرنامج َّ‬
‫ِّ‬
‫وننفذه‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫النصية "درجة الرسوب"‪ .‬عندما نحفظ البرنامج‬
‫درجة الرسوب‬
‫‪252‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫إذا ع ّدلنا البرن امج وأعطين ا المتغ يرَ ‪ grade‬القيم ة ‪ 65‬أو أعلى منه ا‪ ،‬فسنحص ل ب داًل من ذل ك‬
‫على الناتج "درجة النجاح"‪.‬‬
‫إلضافة التعليمة ‪ else‬إلى مثال الحساب المصرفي‪ ،‬سنعيد كتابة الشيفرة كما يلي‪:‬‬
‫‪balance = 522‬‬
‫‪if balance < 0:‬‬
‫)"‪.‬الحساب فارغ‪ ،‬أضف مبلغا اآلن‪ ،‬أو ستحصل على غرامة"(‪print‬‬
‫‪else:‬‬
‫)"‪.‬رصيدك أكبر من ‪print("0‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪.‬رصيدك أكبر من ‪0‬‬
‫غيرن ا قيم ة المتغ ير ‪ balance‬إلى ع دد م وجب لكي ُت َّ‬
‫نفذ الش يفرة المقابل ة‬
‫هن ا‪َّ ،‬‬
‫للتعليمة ‪ .else‬إن أردت تنفيذ الشيفرة المقابلة للتعليمة ‪ ،if‬غيِّ ر القيمة إلى عدد سالب‪.‬‬
‫من خالل دمج العب ارتين ‪ if‬و ‪ ،else‬ف أنت تنش ئ تعليم ة ش رطية مزدوج ة‪ ،‬وال تي س تجعل‬
‫الحاسوب ينفذ شيفرة برمجية معينة سواء تم استيفاء شرط ‪ if‬أم ال‪.‬‬
‫‪ .3‬التعليمة ‪else if‬‬
‫ح تى اآلن‪ ،‬عملن ا على تعليم ات ش رطية ثنائي ة‪ ،‬أي إن تحق ق الش رط‪ ،‬فنف ذ ش يفرة م ا‪ ،‬وإال‪،‬‬
‫ِّ‬
‫ً‬
‫برنامجا يتحقق من عدة حاالت شرطية‪.‬‬
‫فنفذ شيفرة أخرى فقط‪ .‬لكن في بعض الحاالت‪ ،‬قد تريد‬
‫وألج ل ه ذا‪ ،‬س وف نس تخدم التعليمة ‪ ،else if‬وال تي ُتكتب في ب ايثون هك ذا ‪ .elif‬تش به‬
‫التعليمة ‪ - elif‬أو ‪ - else if‬التعليمة ‪ ،if‬ومهمتها التحقق من شرط إضافي آخر‪.‬‬
‫‪253‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫في برنامج الحساب المصرفي‪ ،‬قد ن رغب في الحص ول على ثالث ة مخرج ات مختلف ة مقابل ة‬
‫لثالث حاالت مختلفة‪:‬‬
‫•‬
‫•‬
‫•‬
‫الرصيد أقل من ‪0‬‬
‫الرصيد يساوي ‪0‬‬
‫الرصيد أعلى من ‪0‬‬
‫ستوضع التعليمة ‪ elif‬بين التعليمة ‪ if‬والتعليمة ‪ else‬كما يلي‪:‬‬
‫‪. . .‬‬
‫‪if balance < 0:‬‬
‫)"‪.‬الحساب فارغ‪ ،‬أضف مبلغا اآلن‪ ،‬أو ستحصل على غرامة"(‪print‬‬
‫‪elif balance == 0:‬‬
‫)"‪.‬الرصيد يساوي ‪ ،0‬أضف مبلً‬
‫ًا"(‪print‬‬
‫غا قريب‬
‫‪else:‬‬
‫)"‪.‬رصيدك أكبر من ‪print("0‬‬
‫اآلن‪ ،‬هناك ثالثة مخرجات محتملة يمكن أن ُتطبع عند تنفيذ البرنامج‪:‬‬
‫•‬
‫إن ك ان المتغ ير ‪ balance‬يس اوي ‪ ،0‬فسنحص ل على المخرج ات من التعليم ة ‪( elif‬أي‬
‫•‬
‫إذا ُ‬
‫ض ِبط المتغ ير ‪ balance‬عن د ع دد م وجب‪ ،‬فس وف نحص ل على المخرج ات من‬
‫•‬
‫إذا ُ‬
‫ض ِبط المتغير ‪ balance‬عن د ع دد س الب‪ ،‬فسنحص ل على المخرج ات من التعليم ة ‪if‬‬
‫ً‬
‫قريبا‪.)".‬‬
‫مبلغا‬
‫السلسلة "الرصيد يساوي ‪ ،0‬أضف‬
‫ً‬
‫التعليمة ‪( else‬أي طباعة السلسلة "رصيدك أكبر من ‪.)".0‬‬
‫(أي السلسلة "الحساب فارغ‪ ،‬أضف مبلغا اآلن‪ ،‬أو ستحصل على غرامة")‪.‬‬
‫‪254‬‬
‫|‬
‫▲‬
‫التعليمات الشرطية‬
‫البرمجة بلغة بايثون‬
‫ماذا لو أردنا أن نأخذ بالحس بان أك ثر من ثالث ة احتم االت؟ يمكنن ا كتاب ة ع دة تعليم ات ‪elif‬‬
‫في الشيفرة البرمجية‪.‬‬
‫ل ُنعِ د كتابة البرنامج ‪ grade.py‬بحيث يقابل كل نطاق من الدرجات عالمة محددة‪:‬‬
‫•‬
‫‪ 90‬أو أعلى تكافئ الدرجة ‪A‬‬
‫•‬
‫‪ 80-89‬تعادل الدرجة ‪B+‬‬
‫•‬
‫‪ 70-79‬تعادل الدرجة ‪B‬‬
‫•‬
‫‪ 65-69‬تعادل الدرجة ‪B-‬‬
‫•‬
‫‪ 64‬أو أقل تكافئ الدرجة ‪F‬‬
‫س نحتاج لتنفي ذ ه ذه الش يفرة إلى تعليم ة ‪ if‬واح د‪ ،‬وثالث تعليم ات ‪ ،elif‬وتعليم ة ‪else‬‬
‫تعالج جميع الحاالت األخرى‪.‬‬
‫دعن ا نعي د كتاب ة الش يفرة من المث ال أعاله لطباع ة سلس لة نص ية مقابل ة لك ل عالم ة‪ .‬يمكنن ا‬
‫اإلبقاء على التعليمة ‪ else‬كما هي‪.‬‬
‫‪. . .‬‬
‫‪if grade >= 90:‬‬
‫)"‪print("A‬‬
‫‪elif grade >=80:‬‬
‫)"‪print("B+‬‬
‫‪elif grade >=70:‬‬
‫)"‪print("B‬‬
‫‪255‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫‪elif grade >= 65:‬‬
‫)"‪print("B-‬‬
‫‪else:‬‬
‫)"‪print("F‬‬
‫ُت ّ‬
‫نفذ التعليمات ‪ elif‬بالترتيب‪ .‬هذا البرنامج سيكمل الخطوات التالية‪:‬‬
‫•‬
‫البرنامج ‪ ،A‬وإذا كانت الدرجة أق ل من ‪ ،90‬فس يمرّ‬
‫ُ‬
‫إذا كانت الدرجة أكبر من ‪ ،90‬فسيطبع‬
‫البرنامج إلى التعليمة التالية ‪...‬‬
‫•‬
‫امج ‪ ،B+‬إذا ك انت الدرج ة تس اوي‬
‫إذا كانت الدرج ة أك بر من أو تس اوي ‪ ،80‬فس يطبع البرن ُ‬
‫•‬
‫إذا كانت الدرجة أكبر من أو تساوي ‪ ،70‬فسيطبعُ‬
‫البرنامج ‪ ،B‬إذا كانت الدرجة تس اوي ‪69‬‬
‫ُ‬
‫‪ 79‬أو أقل‪ ،‬فسيمرّ البرنامج إلى التعليمة التالية ‪...‬‬
‫أو أقل‪ ،‬فسيمرّ البرنامج إلى التعليمة التالية ‪...‬‬
‫•‬
‫البرنامج ‪ ،B-‬وإذا ك انت الدرج ة تس اوي‬
‫ُ‬
‫إذا كانت الدرجة أكبر من أو تساوي ‪ ،65‬فسيطبع‬
‫•‬
‫أي من الشروط المذكورة أعاله‪.‬‬
‫سيطبع البرنامج ‪ ،F‬ألنه لم يتم استيفاء ِّ‬
‫‪ 64‬أو أقل‪ ،‬فسيمرّ البرنامج إلى التعليمة التالية ‪...‬‬
‫‪ .4‬تعليمات ‪ if‬المتشعبة‬
‫بع د أن تتع ود على التعليم ات ‪ if‬و ‪ elif‬و ‪ ،else‬يمكن ك االنتق ال إلى التعليم ات الش رطية‬
‫المتشعبة (‪.)nested conditional statements‬‬
‫ِّ‬
‫المتشعبة في الحاالت التي نري د فيه ا التحق ق من ش رط ث انوي‬
‫يمكننا استخدام تعليمات ‪if‬‬
‫ُّ‬
‫التأكد من تحقق الشرط الرئيسي‪ .‬لهذا‪ ،‬يمكننا حشر تعليمة ‪ if-else‬داخل تعليم ة ‪if-else‬‬
‫بعد‬
‫لنلق نظرة على صياغة ‪ if‬المتشعبة‪:‬‬
‫أخرى‪.‬‬
‫ِ‬
‫‪256‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫‪if statement1:‬‬
‫تعليمة ‪ if‬الخارجية ‪#‬‬
‫)"‪print("true‬‬
‫تعليمة ‪ if‬المتشعبة ‪#‬‬
‫‪if nested_statement:‬‬
‫)"‪print("yes‬‬
‫‪else:‬‬
‫تعليمة ‪ else‬المتشعبة ‪#‬‬
‫)"‪print("no‬‬
‫‪else:‬‬
‫تعليمة ‪ else‬الخارجية ‪#‬‬
‫)"‪print("false‬‬
‫هناك عدة مخرجات محتملة لهذه الشيفرة‪:‬‬
‫•‬
‫إذا ك‬
‫انت ‪ statement1‬ص‬
‫حيحة‪ ،‬فس‬
‫يتحقق البرن‬
‫امج مم‬
‫انت‬
‫ا إذا ك‬
‫ً‬
‫أيض ا‪ .‬إذا ك انت كلت ا الح التين ص حيحتان‪ ،‬فسنحص ل‬
‫‪ nested_statement‬ص حيحة‬
‫على المخرجات التالية‪:‬‬
‫‪true‬‬
‫‪yes‬‬
‫•‬
‫ولكن إن ك انت ‪ statement1‬ص حيحة‪ ،‬و ‪ nested_statement‬خط أ‪ ،‬فسنحص ل على‬
‫المخرجات التالية‪:‬‬
‫‪true‬‬
‫‪no‬‬
‫•‬
‫وإذا كانت ‪ statement1‬خطأ‪ ،‬فلن ُت ّ‬
‫أي ح ال‪ ،‬ل ذلك‬
‫نف ذ تعليم ة ‪ if-else‬المتش ِّعبة على ِّ‬
‫ست ّ‬
‫ُ‬
‫نفذ التعليمة ‪ else‬وحدها‪ ،‬والمخرجات ستكون‪:‬‬
‫‪257‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫‪false‬‬
‫ً‬
‫أيضا استخدام عدة تعليمات ‪ if‬متشعبة في الشيفرة‪:‬‬
‫يمكن‬
‫‪ if‬الخارجية ‪#‬‬
‫‪if statement1:‬‬
‫)"‪print("hello world‬‬
‫‪ if‬المتشعبة األولى ‪#‬‬
‫‪if nested_statement1:‬‬
‫)"‪print("yes‬‬
‫‪ elif‬المتشعبة األولى ‪#‬‬
‫‪elif nested_statement2:‬‬
‫)"‪print("maybe‬‬
‫‪ else‬المتشعبة األولى ‪#‬‬
‫‪else:‬‬
‫)"‪print("no‬‬
‫‪ elif‬الخارجية ‪#‬‬
‫‪elif statement2:‬‬
‫)"‪print("hello galaxy‬‬
‫‪ if‬المتشعبة الثانية ‪#‬‬
‫‪if nested_statement3:‬‬
‫)"‪print("yes‬‬
‫‪ elif‬المتشعبة الثانية ‪#‬‬
‫‪elif nested_statement4:‬‬
‫)"‪print("maybe‬‬
‫‪ else‬المتشعبة الثانية ‪#‬‬
‫‪else:‬‬
‫)"‪print("no‬‬
‫‪ else‬الخارجية ‪#‬‬
‫‪else:‬‬
‫)"‪statement("Hello‬‬
‫في الشيفرة البرمجية أعاله‪ ،‬هناك تعليمات ‪ if‬و ‪ elif‬متش ِّعبة داخ ل ك ل تعليم ات ‪ .if‬ه ذا‬
‫سيفسح المجال لمزيد من الخيارات في كل حالة‪.‬‬
‫‪258‬‬
‫|‬
‫▲‬
‫التعليمات الشرطية‬
‫البرمجة بلغة بايثون‬
‫دعن ا نلقي نظ رة على مث ال لتعليم ات ‪ if‬متش عبة في البرن امج ‪ .grade.py‬يمكنن ا التحق ق‬
‫أواًل مم ا إذا َّ‬
‫حقق الط الب درج ة النج اح (أك بر من أو تس اوي ‪ ،)٪65‬ثم نح ِّدد العالم ة المقابل ة‬
‫ِّ‬
‫يحقق الط الب درج ة النج اح‪ ،‬فال داعي للبحث عن العالم ة المقابل ة للدرج ة‪ ،‬وب داًل‬
‫للدرج ة‪ .‬إذا لم‬
‫من ذلك‪ ،‬يمكن أن نجعل البرنامج يطبع سلسلة نصية فيها إعالن عن رسوب الطالب‪.‬‬
‫ستبدو الشيفرة المعدلة عن المثال السابق كما يلي‪:‬‬
‫‪. . .‬‬
‫‪if grade >= 65:‬‬
‫)"‪:‬درجة النجاح"(‪print‬‬
‫‪if grade >= 90:‬‬
‫)"‪print("A‬‬
‫‪elif grade >=80:‬‬
‫)"‪print("B+‬‬
‫‪elif grade >=70:‬‬
‫)"‪print("B‬‬
‫‪elif grade >= 65:‬‬
‫)"‪print("B-‬‬
‫‪else:‬‬
‫)"‪print("F‬‬
‫امج "درج ة‬
‫فسيس توفى الش رط األول‪ ،‬وس َيطبع البرن ُ‬
‫إذا أعطين ا للمتغ ير ‪ grade‬القيم ة ‪،92‬‬
‫ُ‬
‫َّ‬
‫أن ه ذا الش رط‬
‫النج اح‪ .":‬بع د ذل ك‪ ،‬س‬
‫يتحقق مم ا إذا ك انت الدرج ة أك بر من أو تس اوي ‪ ،90‬وبم ا َّ‬
‫ً‬
‫ُ‬
‫فستطبع ‪.A‬‬
‫أيضا‪،‬‬
‫متحقق‬
‫‪259‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعليمات الشرطية‬
‫َ‬
‫توفى الش رط األول‪ ،‬ل ذلك س يتخطى‬
‫أمَّ ا إذا أعطين ا للمتغ ير ‪ grade‬القيم ة ‪ ،60‬فلن يُ س‬
‫ِّ‬
‫المتشعبة‪ ،‬وينتقل إلى التعليمة ‪ ،else‬ويطبع ‪.F‬‬
‫البرنامج تعليمات ‪if‬‬
‫يمكننا بالطبع إضافة المزيد من الخيارات‪ ،‬واستخدام طبقة ثانية من تعليم ات ‪ if‬المتش ِّعبة‪.‬‬
‫ربما نود إض افة ال درجات التفص يلية ‪ A+‬و ‪ A‬و ‪ .A-‬يمكنن ا القي ام ب ذلك عن طري ق التحق ق أواًل من‬
‫ُّ‬
‫التحقق مم ا إذا ك انت الدرج ة تس اوي ‪ 90‬أو أعلى‪ ،‬ثم التحق ق مم ا إذا‬
‫اجتي از درج ة النج اح‪ ،‬ثم‬
‫كانت الدرجة تتجاوز ‪ ،96‬وفي تلك الحالة ستقابل العالمة ‪ .A+‬اطلع على المثال التالي‪:‬‬
‫‪. . .‬‬
‫‪if grade >= 65:‬‬
‫)"‪:‬درجة النجاح"(‪print‬‬
‫‪if grade >= 90:‬‬
‫‪if grade > 96:‬‬
‫)"‪print("A+‬‬
‫‪elif grade > 93 and grade <= 96:‬‬
‫)"‪print("A‬‬
‫‪elif grade >= 90:‬‬
‫)"‪print("A-‬‬
‫‪. . .‬‬
‫في الشيفرة أعاله‪ ،‬في حال تعيين المتغير ‪ grade‬عند القيمة ‪ ،96‬سيقوم البرنامج بما يلي‪:‬‬
‫•‬
‫التحقق مما إذا كانت الدرجة أكبر من أو تساوي ‪( 65‬صحيح)‬
‫•‬
‫طباعة السلسلة "درجة النجاح‪" :‬‬
‫•‬
‫التحقق مما إذا كانت الدرجة أكبر من أو تساوي ‪( 90‬صحيح)‬
‫‪260‬‬
‫|‬
‫▲‬
‫التعليمات الشرطية‬
‫البرمجة بلغة بايثون‬
‫•‬
‫التحقق مما إذا كانت الدرجة أكبر من ‪( 96‬خطأ)‬
‫•‬
‫التحقق مما إذا كانت الدرجة أكبر من ‪ ،93‬وأقل من أو تساوي ‪( 96‬صحيح)‬
‫•‬
‫طباعة ‪A‬‬
‫•‬
‫تجاوز التعليمات الشرطية المتشعبة وتنفيذ باقي الشيفرة‬
‫ستكون مخرجات البرنامج في حال كانت الدرجة تساوي ‪ 96‬كالتالي‪:‬‬
‫‪:‬درجة النجاح‬
‫‪A‬‬
‫تساعد تعليمات ‪ if‬المتشعبة على إضافة عدة مستويات من الشروط الفرعية إلى الشيفرة‪.‬‬
‫‪ .5‬خالصة الفصل‬
‫س تتحكم باس تخدام التعليم ات الش رطية‪ ،‬مث ل التعليم ة ‪ ،if‬في مس ار البرن امج أي ت دفق‬
‫ُّ‬
‫معين من‬
‫التحقق من اس تيفاء ش رط‬
‫تنفي ذ الش يفرة‪ .‬تطلب التعليم ات الش رطية من البرن امج‬
‫َّ‬
‫فست َّ‬
‫ُ‬
‫نفذ شيفرة معينة‪ ،‬وإال فسيس تمر تنفي ذ البرن امج وينتق ل إلى‬
‫عدمه‪ .‬وإذا تم استيفاء الشرط‪،‬‬
‫األسطر التالية‪.‬‬
‫يمكنك الدمج بين التعليمات الشرطية والمعامالت المنطقي ة‪ ،‬بم ا فيه ا ‪ and‬و ‪ ،or‬واس تخدام‬
‫التعليمات الشرطية مع الحلقات التكرارية‪.‬‬
‫‪261‬‬
‫|‬
‫▲‬
‫‪15‬‬
‫المهام التكرارية‪:‬‬
‫مدخل إلى الحلقات‬
‫‪262‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫نستفيد من البرامج الحاسوبية خير استفادة في أتمتة المهام وإجراء المه ام التكراري ة لكيال‬
‫نحتاج إلى القيام بها يدويً ا‪ ،‬وإحدى طرائ ق تك رار المه ام المتش ابهة هي اس تخدام حلق ات التك رار‬
‫(‪ ،)loops‬وسنشرح في ه ذا الفص ل حلق تي التك رار الش هيرتين في ب ايثون ‪-‬وس ائر لغ ات البرمج ة‪-‬‬
‫‪ while‬و ‪ ،for‬وكيفية استعمالهما‪.‬‬
‫‪ .1‬حلقة التكرار ‪while‬‬
‫اء على متغ ير منطقي‬
‫حلق ة التك رار ‪ while‬ت ؤدي إلى تك رار تنفي ذ قس م من الش يفرة بن ً‬
‫(‪ ،)boolean‬وسيس تمر تنفي ذ ه ذه الش يفرة لطالم ا ك انت نتيج ة التعب ير المس تعمل معه ا‬
‫ٌ‬
‫َّ‬
‫محق ًقا‪.‬‬
‫شرط ما‬
‫تساوي ‪ true‬أي طالما كان‬
‫أن حلق ة ‪ while‬هي عب ارة ش ريطة تكراري ة؛ فبع د انته اء تنفي ذ التعليم ة‬
‫يمكن ك أن تتخي ل َّ‬
‫الش رطية ‪ ،if‬يُ س َتكمَ ل تنفي ذ بقي ة البرن امج‪ ،‬لكن م ع حلق ة ‪ while‬فس يعود تنفي ذ البرن امج إلى‬
‫بداي ة الحلق ة بع د انته اء تنفي ذها إلى أن يص بح الش رط مس اويًا للقيم ة ‪ false‬أي لم يع د‬
‫َّ‬
‫محق ًقا‪.‬‬
‫الشرط‬
‫وعلى النقيض من حلق ات ‪ for‬ال تي ُت َّ‬
‫معي ًن ا من الم رات‪ ،‬فسيس تمر تنفي ذ‬
‫نفذ ع د ًدا‬
‫َّ‬
‫معين‪ ،‬لذا لن تحتاج إلى عدد مرات تنفيذ الحلقة قبل إنشائها‪.‬‬
‫شرط‬
‫ٍ‬
‫حلقات ‪ while‬اعتما ًدا على‬
‫َّ‬
‫الشكل العام لحلقات ‪ while‬في لغة بايثون كاآلتي‪:‬‬
‫‪while [a condition is True]:‬‬
‫]‪[do something‬‬
‫قيم الش رط ال ذي يلي‬
‫سيس تمر تنفي ذ التعليم ات البرمجي ة الموج ودة داخ ل الحلق ة إلى أن يُ َّ‬
‫‪ while‬إلى القيمة ‪.false‬‬
‫‪263‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫ً‬
‫ل ُن ِ‬
‫برنامجا صغيرًا في ه حلق ة ‪ ،while‬ففي ه ذه البرن امج س نطلب من المس تخدم إدخ ال‬
‫نشئ‬
‫كلمة مرور‪ .‬وهنالك خياران أمام حلقة التكرار‪:‬‬
‫•‬
‫إمَّ ا أن تكون كلمة المرور صحيحة‪ ،‬فعندها سينتهي تنفيذ حلقة ‪.while‬‬
‫•‬
‫أو أن تكون كلمة المرور غير صحيحة‪ ،‬فعندها سيستمر تنفيذ حلقة التكرار‪.‬‬
‫نش ئ ً‬
‫َّ‬
‫ِّ‬
‫ل ُن ِ‬
‫المفض ل‪ ،‬ولنب دأ بتهيئ ة‬
‫محررن ا النص ي‬
‫ملف ا باس م ‪ password.py‬في‬
‫المتغير ‪ paasword‬بإسناد سلسلة نصية فارغة إليه‪:‬‬
‫'' = ‪password‬‬
‫نس تخدم المتغ ير الس ابق للحص ول على م دخالت المس تخدم داخ ل حلق ة التك رار ‪.while‬‬
‫علينا بعد ذلك إنشاء حلقة ‪ while‬مع تحديد ما هو الشرط الذي يجب تحقيقه‪:‬‬
‫'' = ‪password‬‬
‫‪while password != 'password':‬‬
‫أتبعن ا –في المث ال الس ابق– الكلم ة المحج وزة ‪ while‬ب المتغير ‪ ،password‬ثمَّ س نتحقق إذا‬
‫َ‬
‫أن قيم ة المتغ ير‬
‫ك انت قيم ة المتغ ير ‪ password‬تس اوي السلس لة النص ية '‪( 'password‬ال َ‬
‫تنس َّ‬
‫سنحص ل عليه ا من م دخالت المس تخدم)‪ ،‬يمكن ك أن تخت ار أي سلس لة نص ية تش اء لموازن ة‬
‫مدخالت المستخدم بها‪ .‬هذا يعني َّ‬
‫أنه لو أدخل المستخدم السلسلة النصية ‪ password‬فس تتوقف‬
‫حلق ة التك رار وس ُيكمَ ل تنفي ذ البرن امج وس ُت َّ‬
‫نفذ أيّ ة ش يفرات خ ارج الحلق ة‪ ،‬لكن إذا أدخ ل‬
‫المستخدم أيّ ة سلس لة نص ية ال تس اوي ‪ password‬فس ُيكمَ ل تنفي ذ الحلق ة‪ .‬علين ا بع د ذل ك إض افة‬
‫الشيفرة المسؤولة عمّ ا يحدث داخل حلقة ‪:while‬‬
‫‪264‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫'' = ‪password‬‬
‫‪while password != 'password':‬‬
‫)'?‪print('What is the password‬‬
‫)(‪password = input‬‬
‫َّ‬
‫نفذ البرنامج عب ارة ‪ print‬داخ ل حلق ة ‪ while‬وال تي تس أل المس تخدم عن كلم ة م روره‪ ،‬ثم‬
‫أس ندنا قيم ة م دخالت المس تخدم (ال تي حص لنا عليه ا ع بر الدال ة )(‪ )input‬إلى المتغ ير‬
‫َّ‬
‫يتحقق البرن امج إذا ك انت قيم ة المتغ ير ‪ password‬تس اوي السلس لة النص ية‬
‫‪ .password‬س‬
‫َّ‬
‫تحقق ذل ك فس ينتهي تنفي ذ حلق ة ‪ .while‬لنض ف س طرًا آخ ر إلى البرن امج‬
‫'‪ ،'password‬وإذا‬
‫ً‬
‫مساوية إلى ‪:false‬‬
‫لنعرف ماذا يحدث إن أصبحت قيمة الشرط‬
‫'' = ‪password‬‬
‫‪while password != 'password':‬‬
‫)'?‪print('What is the password‬‬
‫)(‪password = input‬‬
‫)'‪print('Yes, the password is ' + password + '. You may enter.‬‬
‫أن آخ ر عب ارة )(‪ print‬موج ودة خ ارج حلق ة ‪ ،while‬ل ذا عن دما يُ دخِ ل المس تخدم‬
‫الح ظ َّ‬
‫ُ‬
‫طبع آخر جملة وال تي تق ع خ ارج حلق ة التك رار‪.‬‬
‫الكلمة ‪ password‬عند سؤاله عن كلمة مروره‪،‬‬
‫فست َ‬
‫لكن ماذا يحدث لو لم يدخل المس تخدم الكلم ة ‪ password‬ق ط؟ إذ لن يس تمر تنفي ذ البرن امج ولن‬
‫ي روا آخ ر عب ارة )(‪ print‬وسيس تمر تنفي ذ حلق ة التك رار إلى م ا ال نهاي ة! يس تمر تنفي ذ حلق ة‬
‫التك رار إلى م ا ال نهاي ة إذا بقي تنفي ذ البرن امج داخ ل حلق ة تك رار دون الخ روج منه ا‪ .‬وإذا أردت‬
‫الخروج من حلقة تكرار نهائية‪ ،‬فاضغط ‪ Ctrl+C‬في سطر األوامر‪ .‬احفظ البرنامج ثم ِّ‬
‫شغله‪:‬‬
‫‪265‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪python password.py‬‬
‫س ُي َ‬
‫طلب من ك إدخ ال كلم ة الم رور‪ ،‬ويمكن ك تجرب ة م ا تش اء من الكلم ات‪ .‬ه ذا مث ٌ‬
‫ال عن‬
‫ناتج البرنامج‪:‬‬
‫?‪What is the password‬‬
‫‪hello‬‬
‫?‪What is the password‬‬
‫‪sammy‬‬
‫?‪What is the password‬‬
‫‪PASSWORD‬‬
‫?‪What is the password‬‬
‫‪password‬‬
‫‪Yes, the password is password. You may enter.‬‬
‫َ‬
‫تعملت دال ًة من دوال‬
‫أن السالس ل النص ية حساس ة لحال ة األح رف إال إذا اس‬
‫أب ِق في ذهن ك َّ‬
‫النص وص لتحوي ل السلس لة النص ية إلى حال ة األح رف الص غيرة (على س بيل المث ال) قب ل‬
‫ُّ‬
‫التحقق منها‪.‬‬
‫ا‪ .‬تطبيق عملي‬
‫بع د أن تعلمن ا المب دأ األساس ي لحلق ة تك رار ‪ ،while‬فل ُن ِ‬
‫نش ئ لعب ة تعم ل على س طر األوام ر‬
‫ً‬
‫لتخمين األرقام والتي تستعمل الحلقة ‪ . while‬نريد من الحاسوب أن يُ ِ‬
‫وائية لكي‬
‫نشئ أرقامً ا عش‬
‫يحاول المستخدمون تخمينها‪ ،‬لذا علينا استيراد الوحدة ‪ random‬عبر اس تخدام التعليم ة ‪import‬‬
‫ً‬
‫الحقُا إلى كيفي ة اس تيراد الوح دات في فص ل الوح دات)‪ ،‬وإذا لم تكن ه ذه الحزم ة‬
‫(س نطرق‬
‫ً‬
‫مألوفة ل ك فيمكن ك ق راءة المزي د من المعلوم ات عن تولي د األرق ام العش وائية في توثي ق ب ايثون‪.‬‬
‫ً‬
‫بداية ً‬
‫َّ‬
‫ل ُن ِ‬
‫المفضل‪:‬‬
‫ملفا باسم ‪ guess.py‬في محررك النصي‬
‫نشئ‬
‫‪266‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫‪import random‬‬
‫علين ا اآلن إس ناد ع دد ص حيح عش وائي إلى المتغ ير ‪ ،number‬ولنجع ل مجال ه من ‪ 1‬إلى ‪25‬‬
‫(بما فيها تلك األرقام) كيال نجعل اللعبة صعبة ج ًدا‪.‬‬
‫‪import random‬‬
‫)‪number = random.randint(1, 25‬‬
‫يمكننا اآلن إنشاء حلقة ‪ ،while‬وذلك بتهيئة متغير ثم كتابة الحلقة‪:‬‬
‫‪import random‬‬
‫)‪number = random.randint(1, 25‬‬
‫‪number_of_guesses = 0‬‬
‫‪while number_of_guesses < 5:‬‬
‫)'‪print('Guess a number between 1 and 25:‬‬
‫)(‪guess = input‬‬
‫)‪guess = int(guess‬‬
‫‪number_of_guesses = number_of_guesses + 1‬‬
‫‪if guess == number:‬‬
‫‪break‬‬
‫هيأن ا متغ يرًا اس مه ‪ number_of_guesses‬قيمت ه ‪ ،0‬وس وف نزي د قيمت ه عن د ك ل تك رار‬
‫للحلقة لكي ال تصبح حلقتنا ال نهائية ثم سنضيف حلقة ‪ while‬التي تشترط أاّل تزيد قيمة المتغ ير‬
‫‪ number_of_guesses‬عن خمس تكرارات‪.‬‬
‫‪267‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫وبع د المحاول ة الخامس ة س ُيعاد المس تخدم إلى س طر األوام ر‪ ،‬وإذا ح اول المس تخدم إدخ ال‬
‫أي شيء غير رقمي فسيحصل على رسالة خطأ‪.‬‬
‫ّ‬
‫أض فنا داخ ل حلق ة ‪ while‬عب ارة )(‪ print‬لطلب إدخ ال رقم من المس تخدم‪ ،‬ثم س نأخذ‬
‫مدخالت المستخدم عبر الدالة )(‪ُ input‬‬
‫ِّ‬
‫سنحول المتغير ‪guess‬‬
‫ونس ِن َدها إلى المتغير ‪ ،guess‬ثم‬
‫من سلس لة نص ية إلى ع دد ص حيح‪ .‬وقب ل انته اء حلق ة التك رار‪ ،‬فعلين ا زي ادة قيم ة المتغ ير‬
‫‪ number_of_guesses‬بمقدار ‪ ،1‬لكيال ُت َّ‬
‫نفذ حلقة التكرار أكثر من ‪ 5‬مرات‪.‬‬
‫وفي النهاية‪ ،‬كتبنا التعليم ة ‪ if‬ش رطية ل نرى إذا ك ان المتغ ير ‪ guess‬ال ذي أدخل ه المس تخدم‬
‫مس او لل رقم الموج ود في المتغ ير ‪ number‬ال ذي َّ‬
‫ولده الحاس وب‪ ،‬وإذا تحق ق الش رط فسنس تخدم‬
‫ٍ‬
‫ً‬
‫جاهزا لالستخدام‪ ،‬ويمكننا تشغيله عبر تنفي ذ‬
‫التعليمة ‪ break‬للخروج من الحلقة‪ .‬أصبح البرنامج‬
‫األمر التالي‪:‬‬
‫‪python guess.py‬‬
‫ً‬
‫حيحا‬
‫أن البرن امج يعم ل عماًل س ليمً ا‪ ،‬لكن المس تخدم لن يعلم إذا ك ان تخمين ه ص‬
‫ٌ‬
‫ص‬
‫حيح َّ‬
‫ِّ‬
‫يخمن الرقم خمس م رات دون أن يعلم إذا ك انت إح دى محاوالت ه ص حيحة‪ .‬ه ذا مث ال‬
‫ويمكنه أن‬
‫عن مخرجات البرنامج‪:‬‬
‫‪Guess a number between 1 and 25:‬‬
‫‪11‬‬
‫‪Guess a number between 1 and 25:‬‬
‫‪19‬‬
‫‪Guess a number between 1 and 25:‬‬
‫‪22‬‬
‫‪Guess a number between 1 and 25:‬‬
‫‪3‬‬
‫‪268‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫ مدخل إلى الحلقات‬:‫المهام التكرارية‬
Guess a number between 1 and 25:
8
‫لنضف بعض التعليمات الشرطية خ ارج حلق ة التك رار لكي يحص ل المس تخدم على معلوم ات‬
:‫ وسنضيف هذه العبارات في نهاية الملف‬،‫فيما إذا استطاعوا تخمين الرقم أم ال‬
import random
number = random.randint(1, 25)
number_of_guesses = 0
while number_of_guesses < 5:
print('Guess a number between 1 and 25:')
guess = input()
guess = int(guess)
number_of_guesses = number_of_guesses + 1
if guess == number:
break
if guess == number:
print('You guessed the number in ' + str(number_of_guesses)
+ ' tries!')
else:
print('You did not guess the number. The number was ' +
str(number))
‫ لكن ذل ك لن‬،‫امج في ه ذه المرحل ة المس تخدمَ إذا اس تطاعوا تخمين ال رقم‬
ُ
‫س ُيخ ِبر البرن‬
‫ ولمس اعد‬.‫يح دث إال بع د انته اء حلق ة التك رار وبع د انته اء ع دد م رات التخمين المس موحة‬
▲
|
269
‫البرمجة بلغة بايثون‬
‫ مدخل إلى الحلقات‬:‫المهام التكرارية‬
‫ وس تخبر تل ك التعليم ات‬while ‫ فلنض ف بعض التعليم ات الش رطية داخ ل حلق ة‬، ‫المس تخدم قلياًل‬
،‫ لكي يس تطيعوا تخمين ال رقم بنج اح‬،‫المس تخدم إذا ك ان تخمين ه أعلى من ال رقم أو أص غر من ه‬
:if guess == number ‫وسنضيف تلك التعليمات الشرطية قبل السطر الذي يحتوي على‬
import random
number = random.randint(1, 25)
number_of_guesses = 0
while number_of_guesses < 5:
print('Guess a number between 1 and 25:')
guess = input()
guess = int(guess)
number_of_guesses = number_of_guesses + 1
if guess < number:
print('Your guess is too low')
if guess > number:
print('Your guess is too high')
if guess == number:
break
if guess == number:
print('You guessed the number in ' + str(number_of_guesses)
+ ' tries!')
else:
print('You did not guess the number. The number was ' +
str(number))
▲
|
270
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫وعن دما ُنش ِّغل البرن امج م ً‬
‫أن‬
‫رة أخ رى بتنفي ذ ‪ ،python guess.py‬فيمكنن ا مالحظ ة َّ‬
‫َّ‬
‫وائيا ه و ‪ 12‬وك ان تخمين‬
‫المولد عش‬
‫المس تخدم سيحص ل على بعض المس اعدة‪ ،‬فل و ك ان ال رقم‬
‫ً‬
‫أن ال رقم ال ذي خمن ه أك بر من ال رقم العش وائي‪ ،‬وذل ك لكي‬
‫المس تخدم ‪ ،18‬فس ُيخبره البرن امج َّ‬
‫ً‬
‫وفق ا ل ذلك‪ .‬هنال ك الكث ير من التحس ينات ال تي يمكن إجراؤه ا على‬
‫يس تطيع تع ديل تخمني ه‬
‫الشيفرة السابقة‪ ،‬مثل تضمين آلية لمعالجة األخطاء التي تحدث عن دما ال يُ دخِ ل المس تخدم ع د ًدا‬
‫ً‬
‫صحيحا‪ ،‬لكن كان غرضنا هو رؤي ة كيفي ة اس تخدام حلق ة ‪ while‬في برن امج قص ير ومفي د يعم ل‬
‫من سطر األوامر‪.‬‬
‫‪ .2‬حلقة التكرار ‪for‬‬
‫اء على ع َّداد أو على متغيِّ ر‪ ،‬وه ذا‬
‫حلق ة ‪ for‬ت ؤدي إلى تك رار تنفي ذ ج زء من الش يفرات بن ً‬
‫أن حلقات ‪ for‬تستعمل عندما يكون عدد مرات تنفيذ حلقة التكرار معلومً ا قبل ال دخول في‬
‫يعني َّ‬
‫الحلقة‪ ،‬وذلك على النقيض من حلقات ‪ while‬المبنية على شرط‪.‬‬
‫ُتبنى حلقات ‪ for‬في بايثون كما يلي‪:‬‬
‫‪for [iterating variable] in [sequence]:‬‬
‫]‪[do something‬‬
‫ست َّ‬
‫ُ‬
‫نفذ الشيفرات الموجودة داخل حلق ة التك رار ع ِّدة م رات إلى أن تنتهي الحلق ة‪ .‬لننظ ر إلى‬
‫مجال من القيم‪:‬‬
‫كيفية مرور الحلقة ‪ for‬على‬
‫ٍ‬
‫‪for i in range(0,5):‬‬
‫)‪print(i‬‬
‫سيخ ِرج البرنامج السابق عند تشغيله الناتج اآلتي‪:‬‬
‫ُ‬
‫‪271‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫ضبطنا المتغير ‪ i‬في حلقة ‪ for‬ليحت وي على القيم ة ال تي س ُت َّ‬
‫نفذ عليه ا حلق ة التك رار‪ ،‬وك ان‬
‫مجال القيم التي ُ‬
‫ستسنَد إلى هذا المتغير من ‪ 0‬إلى ‪ .5‬ثم طبعً ا قيمة المتغير في ك ل دوران لحلق ة‬
‫التكرار‪ ،‬لكن أبق في ذهنك َّ‬
‫أننا نميل إلى بدء العد من الرقم ‪ 0‬في البرمجة‪ ،‬وعلى الرغم من ع رض‬
‫ِ‬
‫خمسة أرقام‪ ،‬لكنها تبدأ بالرقم ‪ 0‬وتنتهي بالرقم ‪ .4‬من الشائع أن ترى استخدامً ا لحلق ة ‪ for‬عن دما‬
‫معينة من الشيفرات لعددٍ من المرات‪.‬‬
‫تحتاج إلى تكرار كتلة‬
‫َّ‬
‫ا‪ .‬استخدام حلقة التكرار ‪ for‬مع الدالة )(‪range‬‬
‫إحدى أنواع السالسل غير القابلة للتع ديل في ب ايثون هي تل ك الناتج ة من الدال ة )(‪،range‬‬
‫وتستخدم الدالة )(‪ range‬في حلقات التكرار للتحكم بع دد م رات تك رار الحلق ة‪ .‬عن د التعام ل م ع‬
‫الدالة )(‪ range‬عليك أن تمرر معاماًل‬
‫رقميا أو معاملين أو ثالثة معامالت‪:‬‬
‫ً‬
‫•‬
‫‪ :start‬يش ير إلى القيم العددي ة الص يحية ال تي س تبدأ به ا السلس لة‪ ،‬وإذا لم ُتم رَّ ر قيم ة‬
‫لهذا المعامل فستبدأ السلسلة من ‪.0‬‬
‫•‬
‫‪ :stop‬ه ذا المعام ل مطل وب دومً ا وه و القيم ة العددي ة الص حيحة ال تي تمث ل نهاي ة‬
‫السلسلة العددية لكن دون تضمينها‪.‬‬
‫•‬
‫‪ :step‬هي مقدار الخطوة‪ ،‬أي عدد األرقام التي يجب زيادتها (أو إنقاصها إن كنَّا نتعام ل‬
‫مع أرقام سالبة) في الدورة القادمة‪ ،‬وقيمة المعامل ‪ step‬تساوي ‪ 1‬إن لم ُتح َّدد له قيمة‪.‬‬
‫‪272‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫لننظر إلى بعض األمثلة التي ُن ِّ‬
‫مرر فيها مختلف المع امالت إلى الدال ة )(‪ .range‬لنب دأ بتمري ر‬
‫أن السلسلة اآلتية من الشكل )‪:range(stop‬‬
‫المعامل ‪ stop‬فقط‪ ،‬أي َّ‬
‫‪for i in range(6):‬‬
‫)‪print(i‬‬
‫ً‬
‫اوية لل رقم ‪ ،6‬ل ذا س تمر حلق ة التك رار من‬
‫ك انت قيم ة المعام ل ‪ stop‬في المث ال الس ابق مس‬
‫بداية المجال ‪ 0‬إلى نهايته ‪( 6‬باستثناء الرقم ‪ 6‬كما ذكرنا أعاله)‪:‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫‪5‬‬
‫المثال اآلتي من الشكل )‪ range(start ,stop‬الذي ُتمرَّ ر قيم بدء السلسلة ونهايتها‪:‬‬
‫‪for i in range(20,25):‬‬
‫)‪print(i‬‬
‫المج ال –في المث ال الس ابق– ي تراوح بين ‪( 20‬بم ا فيه ا ال رقم ‪ )20‬إلى ‪( 25‬باس تثناء ال رقم‬
‫‪ ،)25‬لذا سيبدو الناتج كما يلي‪:‬‬
‫‪20‬‬
‫‪21‬‬
‫‪22‬‬
‫‪23‬‬
‫‪24‬‬
‫الوس يط ‪ step‬الخ اص بالدال ة )(‪ range‬ش بيه بمعام ل الخط وة ال ذي نس تعمله عن د تقس يم‬
‫السالس ل النص ية ألن ه يس تعمل لتج اوز بعض القيم ض من السلس لة‪ .‬ي أتي المعام ل ‪ step‬في آخ ر‬
‫‪273‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫قائم ة المع امالت ال تي تقبله ا الدال ة )(‪ range‬وذل ك بالش كل )‪.range(start, stop, step‬‬
‫لنستعمل المعامل ‪ step‬مع قيمة موجبة‪:‬‬
‫‪for i in range(0,15,3):‬‬
‫)‪print(i‬‬
‫س يؤدي المث ال الس ابق إلى إنش اء سلس لة من األرق ام ال تي تب دأ من ‪ 0‬وتنتهي عن د ‪ 15‬لكن‬
‫قيمة المعامل ‪ step‬هي ‪ ،3‬لذا سيتم تخطي رقمين في كل دورة‪ ،‬أي سيكون الناتج كاآلتي‪:‬‬
‫‪0‬‬
‫‪3‬‬
‫‪6‬‬
‫‪9‬‬
‫‪12‬‬
‫ً‬
‫أيضا استخدام قيم ة س البة للمعام ل ‪ step‬لل دوران إلى الخل ف‪ ،‬لكن علين ا تع ديل قيم‬
‫يمكننا‬
‫‪ start‬و ‪ stop‬بما يتوافق مع ذلك‪:‬‬
‫‪for i in range(100,0,-10):‬‬
‫)‪print(i‬‬
‫قيم ة المعام ل ‪ start‬في المث ال الس ابق هي ‪ ،100‬وك انت قيم ة المعام ل ‪ stop‬هي ‪،0‬‬
‫والخط وة هي ‪ ،-10‬ل ذا س تبدأ السلس لة من ال رقم ‪ 100‬وس تنتهي عن د ال رقم ‪ ،0‬وس يكون التن اقص‬
‫بمقدار ‪ 10‬في كل دورة‪ ،‬ويمكننا مالحظة ذلك في الناتج اآلتي‪:‬‬
‫‪100‬‬
‫‪90‬‬
‫‪80‬‬
‫‪70‬‬
‫‪60‬‬
‫‪274‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪50‬‬
‫‪40‬‬
‫‪30‬‬
‫‪20‬‬
‫‪10‬‬
‫عن دما ن برمج باس تخدام لغ ة ب ايثون‪ ،‬فس نجد أنن ا نس تفيد كث يرًا من السالس ل الرقمي ة ال تي‬
‫تنتجها الدالة )(‪.range‬‬
‫ب‪ .‬استخدام حلقة ‪ for‬مع أنواع البيانات المتسلسلة‬
‫يمكن االس تفادة من الق وائم (من الن وع ‪ )list‬وغيره ا من أن واع البيان ات المتسلس لة‬
‫واس تعمالها بع ِّدها مع امالت لحلق ات ‪ ،for‬فب داًل من ال دوران باس تخدام الدال ة )(‪ range‬فيمكنن ا‬
‫تعريف قائمة ثم الدوران على عناصرها‪ .‬س ُنسنِد في المث ال اآلتي قائم ًة إلى متغيِّ ر‪ ،‬ثم سنس تخدم‬
‫حلقة ‪ for‬للدوران على عناصر القائمة‪:‬‬
‫‪sharks = ['hammerhead', 'great white', 'dogfish', 'frilled',‬‬
‫]'‪'bullhead', 'requiem‬‬
‫‪for shark in sharks:‬‬
‫)‪print(shark‬‬
‫حيح أنن ا اس تعملنا الكلم ة ‪shark‬‬
‫ٌ‬
‫في ه ذه الحال ة‪ ،‬طبعن ا ك ل عنص ر موج ود في القائم ة؛ وص‬
‫اسمً ا للمتغير‪ ،‬لكن يمكنك استعمال أي اسم صحيح آخر ترغب به‪ ،‬وستحصل على نفس النتيجة‪.‬‬
‫ناتج تنفيذ المثال السابق هو‪:‬‬
‫‪hammerhead‬‬
‫‪great white‬‬
‫‪275‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫‪dogfish‬‬
‫‪frilled‬‬
‫‪bullhead‬‬
‫‪requiem‬‬
‫ظه ر دوران الحلق ة ‪ for‬على جمي ع عناص ر القائم ة م ع طباع ة ك ل عنص ر في‬
‫الن اتج الس ابق يُ ِ‬
‫طر منفص ل‪ .‬يش يع اس تخدام الق وائم واألن واع األخ رى من البيان ات المتسلس لة مث ل السالس ل‬
‫س ٍ‬
‫النص ية وب نى ‪( tuple‬الص فوف) م ع حلق ات التك رار لس هولة ال دوران على عناص رها‪ .‬يمكن ك دمج‬
‫هذه األنواع من البيانات مع الدالة )(‪ range‬إلضافة عناصر إلى قائمة‪ ،‬مثل‪:‬‬
‫‪sharks = ['hammerhead', 'great white', 'dogfish', 'frilled',‬‬
‫]'‪'bullhead', 'requiem‬‬
‫‪for item in range(len(sharks)):‬‬
‫)'‪sharks.append('shark‬‬
‫)‪print(sharks‬‬
‫الناتج‪:‬‬
‫‪['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead',‬‬
‫‪'requiem', 'shark', 'shark', 'shark', 'shark', 'shark',‬‬
‫]'‪'shark‬‬
‫أض فنا هن ا السلس لة النص ية '‪ 'shark‬خمس م رات (وه و نفس ط ول القائم ة ‪sharks‬‬
‫األصلي) إلى القائمة ‪.sharks‬‬
‫يمكننا استخدام حلقة ‪ for‬لبناء قائمة جديدة‪:‬‬
‫][ = ‪integers‬‬
‫‪276‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫‪for i in range(10):‬‬
‫)‪integers.append(i‬‬
‫)‪print(integers‬‬
‫هيئنا في المث ال الس ابق قائم ًة فارغ ًة باس م ‪ integers‬لكن حلق ة التك رار ‪ for‬مألت القائم ة‬
‫ّ‬
‫لتصبح كما يلي‪:‬‬
‫]‪[0, 1, 2, 3, 4, 5, 6, 7, 8, 9‬‬
‫وبشكل شبيهٍ بما سبق‪ ،‬يمكننا الدوران على السالسل النصية‪:‬‬
‫ٍ‬
‫'‪sammy = 'Sammy‬‬
‫‪for letter in sammy:‬‬
‫)‪print(letter‬‬
‫الناتج‪:‬‬
‫‪S‬‬
‫‪a‬‬
‫‪m‬‬
‫‪m‬‬
‫‪y‬‬
‫يمكن الدوران على بنى ‪ tuple‬كما هو الحال في القوائم والسالسل النصية‪ .‬عند المرور على‬
‫عناصر نوع البيانات ‪ ،dictionary‬فمن المهم أن تبقي بذهنك البنية الخاص ة ب ه «مفت اح‪:‬قيم ة»‬
‫(‪ )key:value‬لكي تضمن َّ‬
‫أنك تستدعي العنصر الصحيح من المتغير‪.‬‬
‫ٌ‬
‫ٌ‬
‫بسيط نعرض فيه المفتاح (‪ )key‬والقيمة (‪:)value‬‬
‫مثال‬
‫إليك‬
‫‪sammy_shark = {'name': 'Sammy', 'animal': 'shark', 'color':‬‬
‫}'‪'blue', 'location': 'ocean‬‬
‫‪277‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫‪for key in sammy_shark:‬‬
‫)]‪print(key + ': ' + sammy_shark[key‬‬
‫الناتج‪:‬‬
‫‪name: Sammy‬‬
‫‪animal: shark‬‬
‫‪location: ocean‬‬
‫‪color: blue‬‬
‫عن د اس تخدام متغ يرات من الن وع ‪( dictionary‬ق اموس) م ع حلق ات ‪ for‬فيك ون‬
‫ً‬
‫متعلق ا بمفت اح القيم‪ ،‬وعلين ا اس تخدام الص ياغة‬
‫المتغ ير المرتب ط بحلق ة التك رار‬
‫]‪ dictionary_variable[iterating_variable‬للوصول إلى القيمة الموافقة للمفتاح‪ .‬ففي‬
‫المث ال الس ابق ك ان المتغ ير المرتب ط بحلق ة التك رار باس م ‪ key‬وه و يُ ِّ‬
‫مثل المف اتيح‪ ،‬واس تعملنا‬
‫]‪ sammy_shark[key‬للوص ول إلى القيم ة المرتبط ة ب ذاك المفت اح‪ .‬خالص ة م ا س بق‪ُ ،‬تس تعمَ ل‬
‫ً‬
‫عادة للدوران على عناصر البيانات المتسلسلة وتعديلها‪.‬‬
‫حلقات التكرار‬
‫ِّ‬
‫المتشعبة‬
‫ج‪ .‬حلقات ‪for‬‬
‫يمكن تش عيب حلق ات التك رار في ب ايثون‪ ،‬كم ا ه و الح ال في بقي ة لغ ات البرمج ة‪ .‬حلق ة‬
‫التك رار المتش ِّعبة هي الحلق ة الموج ودة ض من حلق ة تك رار أخ رى‪ ،‬وهي ش بيهة بعب ارات ‪if‬‬
‫ِّ‬
‫المتشعبة‪ُ .‬تبنى حلقات التكرار المتشعبة كما يلي‪:‬‬
‫الحلقة الخارجية ‪#‬‬
‫‪for [first iterating variable] in [outer loop]:‬‬
‫اختياري ‪#‬‬
‫]‪[do something‬‬
‫‪278‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫الحلقة الداخلية الفرعية ‪#‬‬
‫‪for [second iterating variable] in [nested loop]:‬‬
‫]‪[do something‬‬
‫يب دأ البرن امج بتنفي ذ حلق ة التك رار الخارجي ة‪ ،‬ويُ َّ‬
‫نفذ أوّ ل دوران فيه ا‪ ،‬وأوَّ ل دوران س يؤدي‬
‫إلى ال دخول إلى حلق ة التك رار الداخلي ة‪ ،‬مم ا ي ؤدي إلى تنفي ذها إلى أن تنتهي تمامً ا‪ .‬ثم س يعود‬
‫تنفيذ البرنامج إلى بداية حلقة التكرار الخارجية‪ ،‬ويبدأ بتنفيذ ال دوران الث اني‪ ،‬ثم سيص ل التنفي ذ‬
‫إلى حلقة التكرار الداخلي ة‪ ،‬وس ُت َّ‬
‫نفذ حلق ة التك رار الداخلي ة بالكام ل‪ ،‬ثم س يعود التنفي ذ إلى بداي ة‬
‫حلق ة التك رار الخارجي ة‪ ،‬وهلم ج رًا إلى أن ينتهي تنفي ذ حلق ة التك رار الخارجي ة أو إيق اف حلق ة‬
‫التك رار ع بر اس تخدام التعليم ة ‪ break‬أو غيره ا‪ .‬ل ُن ِ‬
‫نش ئ مث ااًل يس تعمل حلق ة ‪ for‬متش عبة لكي‬
‫نفهم كي ف تعم ل بدق ة‪ ،‬إذ س تمر حلق ة التك رار الخارجي ة في المث ال اآلتي على قائم ة من األرق ام‬
‫اس مها ‪ ،num_list‬أم ا حلق ة التك رار الداخلي ة فس تمر على قائم ة من السالس ل النص ية‬
‫اسمها ‪:alpha_list‬‬
‫]‪num_list = [1, 2, 3‬‬
‫]'‪alpha_list = ['a', 'b', 'c‬‬
‫‪for number in num_list:‬‬
‫)‪print(number‬‬
‫‪for letter in alpha_list:‬‬
‫)‪print(letter‬‬
‫سيظهر الناتج اآلتي عند تشغيل البرنامج‪:‬‬
‫‪1‬‬
‫‪a‬‬
‫‪b‬‬
‫‪c‬‬
‫‪279‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪2‬‬
‫‪a‬‬
‫‪b‬‬
‫‪c‬‬
‫‪3‬‬
‫‪a‬‬
‫‪b‬‬
‫‪c‬‬
‫أن البرن امج أكم ل أوَّ ل دوران على عناص ر حلق ة التك رار الخارجي ة‬
‫ظه ر الن اتج الس ابق َّ‬
‫يُ ِ‬
‫بطباع ة ال رقم ‪ ،1‬ومن ثم ب دأ تنفي ذ حلق ة التك رار الدخلي ة مم ا يطب ع األح رف ‪ a‬و ‪ b‬و ‪ c‬على‬
‫التوالي‪ .‬وبعد انتهاء تنفيذ حلقة التكرار الداخلية‪ ،‬عاد البرنامج إلى بداي ة حلق ة التك رار الخارجي ة‬
‫طابعً ا ال رقم ‪ ،2‬ثم ب دأ تنفي ذ حلق ة التك رار الداخلي ة (مم ا ي ؤدي إلى إظه ار ‪ a‬و ‪ b‬و ‪ c‬مج د ًدا)‪.‬‬
‫وهكذا دواليك‪.‬‬
‫يمكن االس تفادة من حلق ات ‪ for‬المتش عبة عن د الم رور على عناص ر ق وائم تت ألف من ق وائم‪.‬‬
‫فل و اس تعملنا حلق ة تك رار وحي دة لع رض عناص ر قائم ة تت ألف من عناص ر تحت وي على ق وائم‪،‬‬
‫ُ‬
‫فستعرَ ض قيم القوائم الداخلية‪:‬‬
‫‪list_of_lists = [['hammerhead', 'great white', 'dogfish'],[0,‬‬
‫]]‪1, 2],[9.9, 8.8, 7.7‬‬
‫‪for list in list_of_lists:‬‬
‫)‪print(list‬‬
‫الناتج‪:‬‬
‫]'‪['hammerhead', 'great white', 'dogfish‬‬
‫]‪[0, 1, 2‬‬
‫‪280‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫]‪[9.9, 8.8, 7.7‬‬
‫وفي حال أردنا الوصول إلى العناصر الموجودة في القوائم الداخلية‪ ،‬فيمكننا استعمال حلق ة‬
‫‪ for‬متشعبة‪:‬‬
‫‪list_of_lists = [['hammerhead', 'great white', 'dogfish'],[0,‬‬
‫]]‪1, 2],[9.9, 8.8, 7.7‬‬
‫‪for list in list_of_lists:‬‬
‫‪for item in list:‬‬
‫)‪print(item‬‬
‫الناتج‪:‬‬
‫‪hammerhead‬‬
‫‪great white‬‬
‫‪dogfish‬‬
‫‪0‬‬
‫‪1‬‬
‫‪2‬‬
‫‪9.9‬‬
‫‪8.8‬‬
‫‪7.7‬‬
‫نس تطيع االس تفادة من حلق ات ‪ for‬المتش عبة عن دما نري د ال دوران على عناص ر محت وى‬
‫في قوائم‪.‬‬
‫‪ .3‬التحكم بحلقات التكرار‬
‫أن اس تخدام حلق ات ‪ for‬أو ‪ while‬تس مح بأتمت ة وتك رار المه ام بطريق ة فعّ ال ة‪ .‬لكن‬
‫وج دنا َّ‬
‫في بعض األحي ان‪ ،‬ق د يت دخل عام ل خ ارجي في طريق ة تش غيل برنامج ك‪ ،‬وعن دما يح دث ذل ك‪،‬‬
‫‪281‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫فربم ا تري د من برنامج ك الخ روج تمامً ا من حلق ة التك رار‪ ،‬أو تج اوز ج زء من الحلق ة قب ل إكم ال‬
‫تنفي ذها‪ ،‬أو تجاه ل ه ذا العام ل الخ ارجي تمامً ا‪ .‬ل ذا يمكن ك فع ل م ا س بق باس تخدام‬
‫التعليمات ‪ break‬و ‪ continue‬و ‪.pass‬‬
‫ا‪ .‬التعليمة ‪break‬‬
‫ِّ‬
‫توفر لك التعليم ة ‪ break‬الق درة على الخ روج من حلق ة التك رار عن د ح دوث عام ل خ ارجي‪.‬‬
‫نفذ في ك ل تك رار للحلق ة‪ ،‬وتوض ع ع ً‬
‫فعليك وضع التعليم ة ‪ break‬في الش يفرة ال تي س ُت َّ‬
‫ادة ض من‬
‫تعليم ة ش رطية مث ل ‪ .if‬أل ق نظ ً‬
‫رة إلى أح د األمثل ة ال ذي يس تعمل التعليم ة ‪ break‬داخ ل‬
‫ِ‬
‫حلقة ‪:for‬‬
‫‪number = 0‬‬
‫‪for number in range(10):‬‬
‫)*( ‪number = number + 1‬‬
‫‪if number == 5:‬‬
‫توقف هنا ‪#‬‬
‫‪break‬‬
‫))‪print('Number is ' + str(number‬‬
‫)'‪print('Out of loop‬‬
‫هيأن ا في بدايت ه المتغ ير ‪ number‬بجعل ه يس اوي الص فر‪ ،‬ثم بنين ا حلق ة‬
‫ه ذا برن ٌ‬
‫امج ص غيرٌ ‪ّ ،‬‬
‫تك رار ‪ for‬ال تي تعم ل لطالم ا ك انت قيم ة المتغ ير ‪ number‬أص غر من ‪ .10‬ثم قمن ا بزي ادة قيم ة‬
‫المتغ ير ‪ number‬داخ ل حلق ة ‪ for‬بمق دار ‪ 1‬في ك ل تك رار‪ ،‬وذل ك في الس طر (*) ثم ك ان هنال ك‬
‫مساو للرقم ‪ ،5‬وعند حدوث ذلك فس ُت َّ‬
‫نفذ التعليم ة‬
‫الشرط ‪ if‬الذي يختبر إن كان المتغير ‪number‬‬
‫ٍ‬
‫‪282‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪ break‬للخ روج من الحلق ة‪ ،‬وتوج د داخ ل حلق ة التك رار الدال ة )(‪ print‬ال تي ُت َّ‬
‫نفذ في ك ل تك رار‬
‫إلى أن نخرج من الحلقة عبر التعليمة ‪ ،break‬إذ هي موجودة بعد التعليمة ‪ .break‬لكي نتأكد أنن ا‬
‫خرجنا من الحلقة‪ ،‬وضعنا عبارة )(‪ print‬أخيرة موجودة خارجها‪ .‬سنرى الناتج اآلتي عند‬
‫تنفيذ البرنامج‪:‬‬
‫‪Number is 1‬‬
‫‪Number is 2‬‬
‫‪Number is 3‬‬
‫‪Number is 4‬‬
‫‪Out of loop‬‬
‫ظهر الناتج السابق َّ‬
‫أنه بمجرد أن أصبح العدد الص حيح ‪ number‬مس اويً ا لل رقم ‪ ،5‬فس ينتهي‬
‫يُ ِ‬
‫تنفيذ حلقة التكرار عبر ‪.break‬‬
‫ب‪ .‬التعليمة ‪continue‬‬
‫تس مح لن ا التعليم ة ‪ continue‬بتخطي ج زء من حلق ة التك رار عن د ح دوث عام ل خ ارجي‪،‬‬
‫وعدم إكمال بقية الحلقة إلى نهايتها‪ .‬بعبارةٍ أخرى‪ ،‬سينتقل تنفي ذ البرن امج إلى أوّ ل حلق ة التك رار‬
‫عند تنفيذ التعليمة ‪ .continue‬يجب وضع التعليم ة ‪ continue‬في الش يفرة ال تي س ُت َّ‬
‫نفذ في ك ل‬
‫ً‬
‫عادة ضمن الشرط ‪.if‬‬
‫تكرار للحلقة‪ ،‬ويوضع‬
‫سنس تخدم نفس البرن امج ال ذي اس تعملناها لش رح التعليم ة ‪ break‬أعاله‪ ،‬لكنن ا سنس تخدم‬
‫التعليمة ‪ continue‬بداًل من ‪:break‬‬
‫‪number = 0‬‬
‫‪for number in range(10):‬‬
‫‪number = number + 1‬‬
‫‪283‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫‪if number == 5:‬‬
‫‪# continue here‬‬
‫‪continue‬‬
‫))‪print('Number is ' + str(number‬‬
‫)'‪print('Out of loop‬‬
‫الف رق بين اس تخدام التعليم ة ‪ continue‬ب داًل من ‪ break‬ه و إكم ال تنفي ذ الش يفرة بغض‬
‫ً‬
‫اوية إلى ال رقم ‪ .5‬لننظ ر‬
‫النظ ر عن التوق ف ال ذي ح دث عن دما ك انت قيم ة المتغ ير ‪ number‬مس‬
‫إلى الناتج‪:‬‬
‫‪Number is 1‬‬
‫‪Number is 2‬‬
‫‪Number is 3‬‬
‫‪Number is 4‬‬
‫‪Number is 6‬‬
‫‪Number is 7‬‬
‫‪Number is 8‬‬
‫‪Number is 9‬‬
‫‪Number is 10‬‬
‫‪Out of loop‬‬
‫أن السطر ال ذي يجب أن يحت وي على ‪ Number is 5‬ليس موج و ًدا في المخرج ات‪،‬‬
‫نالحظ َّ‬
‫لكن س ُيكمَ ل تنفي ذ حلق ة التك رار بع د ه ذه المرحل ة مم ا يطب ع األرق ام من ‪ 6‬إلى ‪ 10‬قب ل إنه اء‬
‫تنفيذ الحلقة‪.‬‬
‫َّ‬
‫معقدة ومتش ِّعبة‪،‬‬
‫يمكن ك اس تخدام التعليم ة ‪ continue‬لتف ادي اس تخدام تعليم ات ش رطية‬
‫ست َ‬
‫أو لتحسين أداء البرنامج عن طريق تجاهل الحاالت التي ُ‬
‫رفض نتائجها‪.‬‬
‫‪284‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫ج‪ .‬التعليمة ‪pass‬‬
‫تسمح لنا التعليمة ‪ pass‬بالتعامل مع أحد الشروط دون إيقاف عمل حلق ة التك رار ب أي ش كل‪،‬‬
‫أي س ُت َّ‬
‫نفذ جمي ع التعليم ات البرمجي ة الموج ودة في حلق ة التك رار م ا لم تس تعمل تعليم ات تحكم‬
‫مثل ‪ break‬أو ‪ continue‬فيها‪ .‬وكما هو الحال مع التعليمات السابقة‪ ،‬يجب وض ع التعليم ة ‪pass‬‬
‫نفذ في ك ل تك رار للحلق ة‪ ،‬ويوض ع ع ً‬
‫في الش يفرة ال تي س ُت َّ‬
‫ادة ض من الش رط ‪ .if‬سنس تخدم نفس‬
‫البرن امج ال ذي اس تعملناها لش رح التعليم ة ‪ break‬أو ‪ continue‬أعاله‪ ،‬لكنن ا سنس تخدم‬
‫التعليمة ‪ pass‬هذه المرة‪:‬‬
‫‪number = 0‬‬
‫‪for number in range(10):‬‬
‫‪number = number + 1‬‬
‫‪if number == 5:‬‬
‫تخطى وأكمل ‪#‬‬
‫‪pass‬‬
‫))‪print('Number is ' + str(number‬‬
‫)'‪print('Out of loop‬‬
‫أن علي ه إكم ال تنفي ذ الحلق ة وتجاه ل‬
‫تخبر التعليمة ‪ pass‬التي تقع بعد الشرط ‪ if‬البرنامج َّ‬
‫ِّ‬
‫لنشغل البرنامج ولننظر إلى الناتج‪:‬‬
‫مساواة المتغير ‪ number‬للرقم ‪.5‬‬
‫‪Number is 1‬‬
‫‪Number is 2‬‬
‫‪Number is 3‬‬
‫‪Number is 4‬‬
‫‪285‬‬
‫|‬
‫▲‬
‫المهام التكرارية‪ :‬مدخل إلى الحلقات‬
‫البرمجة بلغة بايثون‬
‫‪Number is 5‬‬
‫‪Number is 6‬‬
‫‪Number is 7‬‬
‫‪Number is 8‬‬
‫‪Number is 9‬‬
‫‪Number is 10‬‬
‫‪Out of loop‬‬
‫أن البرنامج يعمل كما لو أننا لم نض ع‬
‫الحظنا عند استخدامنا للتعليمة ‪ pass‬في هذا البرنامج َّ‬
‫أن‬
‫تعليم ة ش رطية داخ ل حلق ة التك رار؛ إذ تخ بر التعليم ة ‪ pass‬البرن امج أن يكم ل التنفي ذ كم ا ل و َّ‬
‫الش رط لم يتحق ق‪ .‬يمكن أن تس تفيد من التعليم ة ‪ pass‬عن دما تكتب برنامج ك ألوّ ل م رة أثن اء‬
‫ّ‬
‫بحل مشكلة ما عبر خوارزمية‪ ،‬لكن قبل أن تضع التفاصيل التقنية له‪.‬‬
‫تفكيرك‬
‫‪ .4‬خالصة الفصل‬
‫شرحنا في هذا الفصل كيف تعمل حلقتي التكرار ‪ ، while‬و ‪ for‬في بايثون وكيفية إنشائها‪،‬‬
‫إذ تس تمر األولى بتنفي ذ مجموع ة من األس طر البرمجي ة لطالم ا ك ان الش رط مس اويً ا للقيم ة ‪true‬‬
‫بينم ا تس تمر الثاني ة بتنفي ذ مجموع ة من الش يفرات لع ددٍ مُ ح ِّددٍ من الم رات‪ .‬انتقلن ا أخ يرًا إلى‬
‫التعليم ات ‪ break‬و ‪ continue‬و ‪ pass‬ال تي تس مح ب التحكم أك ثر بحلق ات ‪ for‬و ‪while‬‬
‫ِّ‬
‫والتعامل مع األحداث المفاجئة التي تحدث أثناء تنفيذ مهمة مُ‬
‫تكررة‪.‬‬
‫‪286‬‬
‫|‬
‫▲‬
‫‪16‬‬
‫الدوال‪ :‬تعريفها‬
‫واستعمالها‬
‫‪287‬‬
‫|‬
‫▲‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫البرمجة بلغة بايثون‬
‫الدال ة (‪ )function‬هي كتل ة من التعليم ات ال تي ِّ‬
‫راء م ا‪ ،‬ويمكن‪ ،‬بع د تعريفه ا‪ ،‬إع ادة‬
‫تنفذ إج ً‬
‫اس تخدامها في أك ثر من موض ع‪ .‬تجع ل ال دوال الش يفرة تركيبي ة ( ‪ ،)modular‬مم ا يس مح‬
‫باستخدام نفس الشفرة مرارًا وتكرارًا‪.‬‬
‫تضم بايثون عد ًدا من الدوال المُ ضمّ نة الشائعة‪ ،‬مثل‪:‬‬
‫•‬
‫)(‪ print‬والتي تطبع كائنًا في الطرفية‪،‬‬
‫•‬
‫ِّ‬
‫تحول أنواع البيانات النصية أو العددية إلى أعداد صحيحة‪،‬‬
‫)(‪ int‬والتي‬
‫•‬
‫)(‪ len‬التي تعيد طول كائن‪ ،‬وغيرها من الدوال‪.‬‬
‫َّ‬
‫وكيفية استخدامها في البرامج‪.‬‬
‫كيفية تعريف الدوال‪،‬‬
‫سنتعلم في هذا الفصل‬
‫َّ‬
‫َّ‬
‫‪ .1‬تعريف دالة‬
‫مرحبا بالعالم!" إلى دالة‪.‬‬
‫لنبدأ بتحويل البرنامج الذي يطبع عبارة "‬
‫ً‬
‫أنش ئ ً‬
‫ملف ا نص ًيا جدي ًدا‪ ،‬وافتح ه في مح رر النص وص المفض ل عن دك‪ ،‬ثم اس تدع البرن امج‬
‫‪ُ .hello.py‬تع رَّ ف الدال ة باس تخدام الكلم ة المفتاحي ة ‪ ،def‬متبوع ة باس م من اختي ارك‪ ،‬متبوعً ا‬
‫بقوسين يمكن أن يَحتويا المعامالت التي ستأخذها الدال ة‪ ،‬ثم ينتهي التعري ف بنقط تين‪ .‬في ه ذه‬
‫ِّ‬
‫سنعرف دالة باسم )(‪:hello‬‬
‫الحالة‪،‬‬
‫‪def hello():‬‬
‫في الشفرة أعاله‪ ،‬أعددنا السطر األول من تعريف الدالة‪.‬‬
‫ثاني ا مُ ً‬
‫زاح ا ب أربع مس افات بيض اء‪ ،‬وفي ه س نكتب التعليم ات ال تي‬
‫بع د ه ذا‪ ،‬سنض يف س ط ًرا‬
‫ً‬
‫ِّ‬
‫مرحبا بالعالم!" في سطر األوامر‪:‬‬
‫ستنفذها الدالة‪ .‬في هذه الحالة‪ ،‬سنطبع العبارة "‬
‫ً‬
‫‪288‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def hello():‬‬
‫)"مرحبا بالعالم"(‪print‬‬
‫أي ش يء‪ ،‬ألنن ا لم‬
‫لق د أتممن ا تعري ف دالتن ا‪ ،‬غ ير أنن ا إن َن َّفذنا البرن امج اآلن‪ ،‬فلن يح دث ُّ‬
‫نستدع الدالة؛ لذلك‪ ،‬سنستدعي الدالة بالشكل )(‪ hello‬خارج كتلة تعريف الدالة‪:‬‬
‫‪def hello():‬‬
‫)"!مرحبا بالعالم"(‪print‬‬
‫)(‪hello‬‬
‫ِّ‬
‫لننفذ البرنامج‪:‬‬
‫اآلن‪،‬‬
‫‪python hello.py‬‬
‫يجب أن تحصل على المخرجات التالية‪:‬‬
‫!مرحبا بالعالم‬
‫بعض الدوال أكثر تعقي ًدا بكث ير من الدال ة )(‪ hello‬ال تي عرَّ فناه ا أعاله‪ .‬على س بيل المث ال‪،‬‬
‫يمكننا استخدام الحلقة ‪ for‬والتعليمات الشرطية‪ ،‬وغيرها داخل كتلة الدالة‪.‬‬
‫ُّ‬
‫للتحقق مم ا إذا ك انت‬
‫على س بيل المث ال‪ ،‬تس تخدم الدال ة المُ عرَّ ف ة أدن اه تعليم ة ش رطية‬
‫الم دخالت المم رَّ رة إلى المتغ ير ‪ name‬تحت وي على ح رف عل ة (‪ ،)vowel‬ثم تس تخدم الحلق ة ‪for‬‬
‫للمرور (‪ )iterate‬على الحروف الموجودة في السلسلة النصية ‪.name‬‬
‫تعريف الدالة )(‪# names‬‬
‫‪def names():‬‬
‫إعداد المتغير ‪ name‬وإحالة المدخالت عليه ‪#‬‬
‫))'‪:‬أدخل اسمك باللغة اإلنجليزية'(‪name = str(input‬‬
‫‪289‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫التحقق من أن ‪ name‬يحتوي حرف علة ‪#‬‬
‫‪if set('aeiou').intersection(name.lower()):‬‬
‫)'اسمك يحوي حرف علة'(‪print‬‬
‫‪else:‬‬
‫)'اسمك ال يحوي حرف علة'(‪print‬‬
‫المرور على حروف ‪# name‬‬
‫‪for letter in name:‬‬
‫)‪print(letter‬‬
‫استدعاء الدالة ‪#‬‬
‫)(‪names‬‬
‫تس تخدم الدال ة )(‪ names‬ال تي عرَّ فناه ا أعاله تعليم ة ش رطية‪ ،‬وحلق ة ‪ ،for‬وه ذا توض يح‬
‫ً‬
‫أيض ا جع ل التعليم ة الش رطية‬
‫لكيفي ة تنظيم الش فرة البرمجي ة ض من تعري ف الدال ة‪ .‬يمكنن ا‬
‫والحلقة ‪ for‬دالتين منفصلتين‪.‬‬
‫تعري ف ال دوال داخ ل ال برامج يجع ل الش فرة البرمجي ة تركيبي ة (‪ ،)modular‬وقابل ة إلع ادة‬
‫االستخدام‪ ،‬وذلك سيتيح لنا استدعاء نفس الدالة دون إعادة كتابة شيفرتها كل مرة‪.‬‬
‫‪ .2‬المعامالت‪ :‬تمرير بيانات للدوال‬
‫أي وس ائط (‪ ،)arguments‬س نتعلم في‬
‫ح تى اآلن‪ ،‬عرَّ فن ا دال ة ذات قوس ين ف ارغين ال تأخ ذ َّ‬
‫هذا القسم كيفية تعريف المعامالت (‪ )parameters‬وتمرير البيانات إلى الدوال‪.‬‬
‫المعام ل (‪ )parameter‬ه و كي ان مُ س مًّ ى يوض ع في تعري ف الدال ة‪ ،‬ويع ِّرف وس ً‬
‫يطا‬
‫(‪ )arguments‬يمكن أن تقبله الدالة عند استدعائها‪.‬‬
‫ً‬
‫برنامج ا ص غي ًرا يأخ ذ ثالث ة مع امالت ‪ x‬و ‪ y‬و ‪ .z‬سننش ئ دال ة تجم ع تل ك‬
‫دعن ا ننش ئ‬
‫ثم تطبع حاصل جمعها‪.‬‬
‫المعامالت وفق عدة مجموعات َّ‬
‫‪290‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def add_numbers(x, y, z):‬‬
‫‪a = x + y‬‬
‫‪b = x + z‬‬
‫‪c = y + z‬‬
‫)‪print(a, b, c‬‬
‫)‪add_numbers(1, 2, 3‬‬
‫مرّ رن ا الع دد ‪ 1‬إلى المعام ل ‪ ،x‬و ‪ 2‬إلى المعام ل ‪ ،y‬و ‪ 3‬إلى المعام ل ‪ .z‬تتواف ق ه ذه القيم م ع‬
‫المعامالت المقابلة لها في ترتيب الظهور‪.‬‬
‫يُ ج ِري البرنامج العمليات الحسابية على المعامالت على النحو التالي‪:‬‬
‫‪a = 1 + 2‬‬
‫‪b = 1 + 3‬‬
‫‪c = 2 + 3‬‬
‫ً‬
‫إن قيم ة ‪ a‬ستس اوي‬
‫أيض ا ‪ a‬و ‪ b‬و ‪ ،c‬وبن ً‬
‫تطب ع الدال ة‬
‫اء على العملي ات الحس ابية أعاله‪ ،‬ف َّ‬
‫العدد ‪ ،3‬و ‪ b‬ستساوي ‪ ،4‬و ‪ c‬ستساوي العدد ‪.5‬‬
‫ِّ‬
‫لننفذ البرنامج‪:‬‬
‫‪python add_numbers.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪3 4 5‬‬
‫المع امالت هي متغ يرات ُتع رَّ ف ض من جس م الدال ة‪ .‬يمكن تع يين قيم إليه ا عن د تنفي ذ الت ابع‬
‫تلقائيا آنذاك‪.‬‬
‫بتمرير وسائط إلى الدالة‪ ،‬إذ ُتسنَد الوسائط إليها‬
‫ً‬
‫‪291‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫المسماة‬
‫‪ .3‬الوسائط‬
‫َّ‬
‫ُتس تدعى المع امالت بحس ب ت رتيب ظهوره ا في تعري ف الدال ة‪ ،‬أم ا الوس ائط المس ماة‬
‫(‪ُ )Keyword Arguments‬‬
‫فتستخ َدم بأسمائها في استدعاء الدالة‪.‬‬
‫ألن م ترجم‬
‫عند اس تخدام الوس ائط المس مّ اة‪ ،‬يمكن ك اس تخدام المع امالت ب ِّ‬
‫أي ت رتيب تري د‪َّ ،‬‬
‫بايثون سيستخدم الكلمات المفتاحية لمطابقة القيم مع المعامالت‪.‬‬
‫ِّ‬
‫ونمرر إليه ا المُ ع امِ لين ‪username‬‬
‫سننشئ دالة تعرض معلومات الملف الشخصي للمستخدم‪،‬‬
‫(سلسلة نصية)‪ ،‬و ‪( followers‬عدد صحيح)‪.‬‬
‫تعريف دالة ذات معامالت ‪#‬‬
‫‪def profile_info(username, followers):‬‬
‫)‪print("Username: " + username‬‬
‫))‪print("Followers: " + str(followers‬‬
‫داخ‬
‫ل تعري‬
‫ف الدال‬
‫ة‪ ،‬وض‬
‫عنا ‪ username‬و ‪ followers‬بين قوس‬
‫ة‬
‫ي الدال‬
‫الخاص ة بالمس تخدم على هيئ ة‬
‫َّ‬
‫)(‪ profile_info‬أثن اء تعريفه ا‪ .‬تطب ع ش فرة الدال ة المعلوم ات‬
‫سلسلة نصية باستخدام المعاملين المُ مرّ رين‪.‬‬
‫اآلن‪ ،‬يمكننا استدعاء الدالة وتعيين المعامالت‪:‬‬
‫‪def profile_info(username, followers):‬‬
‫)‪print("Username: " + username‬‬
‫))‪print("Followers: " + str(followers‬‬
‫استدعاء الدالة مع تعيين المعامالت ‪#‬‬
‫)‪profile_info("sammyshark", 945‬‬
‫استدعاء الدالة مع تمرير الوسائط المسماة إليها ‪#‬‬
‫)‪profile_info(username="AlexAnglerfish", followers=342‬‬
‫‪292‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫في االس تدعاء األول للدال ة‪ ،‬مرَّ رن ا اس م المس تخدم ‪ ،sammyshark‬وع دد المت ابعين ‪945‬‬
‫ب الترتيب ال وارد في تعري ف الدال ة‪ .‬أمَّ ا في االس تدعاء الث اني للدال ة‪ ،‬فق د اس تخدمنا الوس ائط‬
‫وعينا قيمً ا للوسائط ويمكن عكس الترتيب إن شئنا‪ .‬لننفذ البرنامج‪:‬‬
‫المسمَّ اة‪،‬‬
‫َّ‬
‫‪python profile.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪Username: sammyshark‬‬
‫‪Followers: 945‬‬
‫‪Username: AlexAnglerfish‬‬
‫‪Followers: 342‬‬
‫سنحص ل في المخرج ات على أس ماء المس تخدمين‪ ،‬وأع داد المت ابعين لكال المس تخدمين‪.‬‬
‫يمكننا تغيير ترتيب المعامالت‪ ،‬كما في المثال التالي‪:‬‬
‫‪def profile_info(username, followers):‬‬
‫)‪print("Username: " + username‬‬
‫))‪print("Followers: " + str(followers‬‬
‫تغيير ترتيب المعامالت ‪#‬‬
‫)"‪profile_info(followers=820, username="cameron-catfish‬‬
‫عند تنفيذ البرنامج أعاله‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫‪Username: cameron-catfish‬‬
‫‪Followers: 820‬‬
‫يحاف ظ تعري ف الدال ة على نفس ت رتيب التعليم ات في )(‪ ،print‬ل ذلك يمكنن ا اس تخدام‬
‫بأي ترتيب نشاء‪.‬‬
‫الوسائط المسمّ اة ِّ‬
‫‪293‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪ .4‬القيم االفتراضية للوسائط‬
‫يمكنن ا إعط اء قيم افتراض ية لواح د أو أك ثر من المع امالت‪ .‬في المث ال أدن اه‪ ،‬س نعطي‬
‫للمعام ل ‪ followers‬القيم ة االفتراض ية ‪ 1‬الس تعمالها إن لم ُتم رَّ ر ه ذه القيم ة للدال ة‬
‫عند استدعائها‪:‬‬
‫‪def profile_info(username, followers=1):‬‬
‫)‪print("Username: " + username‬‬
‫))‪print("Followers: " + str(followers‬‬
‫تلقائي ا‬
‫عين ع دد المت ابعين‬
‫اآلن‪ ،‬يمكننا استدعاء الدالة مع تعيين اسم المستخدم فق ط‪ ،‬وس ُي َّ‬
‫ً‬
‫ويأخذ القيمة ‪ .1‬لكن يمكننا تغيير عدد المتابعين إن شئنا‪.‬‬
‫‪def profile_info(username, followers=1):‬‬
‫)‪print("Username: " + username‬‬
‫))‪print("Followers: " + str(followers‬‬
‫)"‪profile_info(username="JOctopus‬‬
‫)‪profile_info(username="sammyshark", followers=945‬‬
‫عندما ِّ‬
‫ننفذ البرنامج باستخدام األمر ‪ ،python profile.py‬ستظهر المخرجات التالية‪:‬‬
‫‪Username: JOctopus‬‬
‫‪Followers: 1‬‬
‫‪Username: sammyshark‬‬
‫‪Followers: 945‬‬
‫تمري ر قيم إلى المع امالت االفتراض ية س يتخطى القيم ة االفتراض ية المعط اة في‬
‫تعريف الدالة‪.‬‬
‫‪294‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪ .5‬إعادة قيمة‬
‫كم ا يمكن تمري ر قيم إلى الدال ة‪ ،‬فيمكن ك ذلك أن تنتج الدال ة قيم ة وتعي دها لمن اس تدعاها‪.‬‬
‫ويكون ذلك عبر استخدام التعليم ة ‪return‬؛ ه ذه التعليم ة اختياري ة‪،‬‬
‫يمكن أن تنتج الدالة قيمة‪،‬‬
‫ُ‬
‫نهي الدال ة مباش ً‬
‫رة عمله ا وتوق ف تنفي ذها‪ُ ،‬‬
‫وتم رَّ ر قيم ة التعب ير ال ذي‬
‫وفي ح ال اس تخدامها‪ ،‬فس ُت ِ‬
‫ُ‬
‫يعقبه‬
‫ا إلى المُ س‬
‫تدعي (‪ .)caller‬إذا لم يلي التعليم‬
‫ة ‪ return‬أي ش‬
‫يء‪ ،‬فس‬
‫ُتعيد الدالة‬
‫َ‬
‫القيمة ‪.None‬‬
‫ح تى اآلن‪ ،‬اس تخدمنا الدال ة )(‪ print‬ب دالً من ‪ return‬في دوالن ا لطباع ة ش يء ب داًل من‬
‫ً‬
‫برنامجا يعيد متغيرً ا بداًل من طباعته اآلن‪.‬‬
‫إعادته‪ .‬لننشئ‬
‫ً‬
‫برنامجا في ملف نصي جديد يسمى ‪ square.py‬يحسب مربع المعام ل ‪ ،x‬ويُ حي ل‬
‫سننشئ‬
‫الن اتج إلى المتغ ير ‪ ،y‬ثم يعي ده‪ .‬س نطبع المتغ ير ‪ ،result‬وال ذي يس اوي ن اتج تنفي ذ‬
‫الدالة )‪.square(3‬‬
‫‪def square(x):‬‬
‫‪y = x ** 2‬‬
‫‪return y‬‬
‫)‪result = square(3‬‬
‫)‪print(result‬‬
‫ّ‬
‫لننفذ البرنامج‪:‬‬
‫‪python square.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪9‬‬
‫‪295‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫مخرج ات البرن امج هي الع دد الص حيح ‪ 9‬ال ذي أعادت ه الدال ة وه و م ا نتوقع ه ل و طلبن ا من‬
‫بايثون حساب مربع العدد ‪.3‬‬
‫لفهم كيفية عمل التعليمة ‪ ،return‬يمكننا تعليق التعليمة ‪:return‬‬
‫‪def square(x):‬‬
‫‪y = x ** 2‬‬
‫‪# return y‬‬
‫)‪result = square(3‬‬
‫)‪print(result‬‬
‫ّ‬
‫لننفذ البرنامج مرة أخرى‪:‬‬
‫اآلن‪،‬‬
‫‪python square.py‬‬
‫سنحصل على الناتج التالي‪:‬‬
‫‪None‬‬
‫أي قيم ة‪ ،‬ل ذلك ُتع اد القيم ة‬
‫ب دون اس تخدام التعليم ة ‪ ،return‬ال يمكن للبرن امج إع ادة ِّ‬
‫االفتراضية ‪.None‬‬
‫إلي ك مث ال آخ ر‪ ،‬في برن امج ‪ add_numbers.py‬أعاله‪ ،‬سنس تبدل بالتعليم ة ‪return‬‬
‫الدالة )(‪:print‬‬
‫‪def add_numbers(x, y, z):‬‬
‫‪a = x + y‬‬
‫‪b = x + z‬‬
‫‪c = y + z‬‬
‫‪return a, b, c‬‬
‫‪296‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫)‪sums = add_numbers(1, 2, 3‬‬
‫)‪print(sums‬‬
‫خ ارج الدال ة‪ ،‬أحلن ا إلى المتغ ير ‪ sums‬نتيج ة اس تدعاء الدال ة بالوس ائط ‪ 1‬و ‪ 2‬و ‪ 3‬كم ا فعلن ا‬
‫أعاله ثم طبعنا قيمته‪.‬‬
‫ِّ‬
‫فلننفذ البرنامج مرة أخرى‪:‬‬
‫‪python add_numbers.py‬‬
‫والناتج سيكون‪:‬‬
‫)‪(3, 4, 5‬‬
‫لق د حص لنا على األع داد ‪ 3‬و ‪ 4‬و ‪ 5‬وهي نفس المخرج ات ال تي تلقيناه ا س ً‬
‫ابقا عن دما‬
‫ألن التعب ير المراف ق‬
‫استخدمنا الدالة )(‪ print‬في الدالة‪ .‬هذه المرة تمت إعادتها على هيئة ص ف َّ‬
‫للتعليمة ‪ return‬يحتوي على فاصلة واحدة على األقل‪.‬‬
‫ُت َ‬
‫وقف الدوال فورًا عندما تصل إلى التعليمة ‪ ،return‬سواء أعادت قيمة‪ ،‬أم لم ُتعِ د‪.‬‬
‫‪def loop_five():‬‬
‫‪for x in range(0, 25):‬‬
‫)‪print(x‬‬
‫‪if x == 5:‬‬
‫إيقاف الدالة عند ‪# x == 5‬‬
‫‪return‬‬
‫)"‪print("This line will not execute.‬‬
‫)(‪loop_five‬‬
‫‪297‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫ي ؤدي اس تخدام التعليم ة ‪ return‬داخ ل الحلق ة ‪ for‬إلى إنه اء الدال ة‪ ،‬وبالت الي لن يُ َّ‬
‫نفذ‬
‫السطر الموجود خارج الحلقة‪.‬‬
‫فسي َّ‬
‫نفذ الس طر )(‪ print‬األخ ير من المث ال الس ابق‪ .‬نعي د‬
‫لو استخدمنا بداًل من ذلك ‪،break‬‬
‫ُ‬
‫أن التعليمة ‪ return‬تنهي عمل الدالة‪ ،‬وقد تعيد قيمة إذا أعقبها تعبير‪.‬‬
‫التذكير َّ‬
‫ً‬
‫ً‬
‫رئيسية‬
‫دالة‬
‫‪ .6‬استخدام )(‪main‬‬
‫رغم َّ‬
‫أنه يمكن ك في ب ايثون اس تدعاء الدال ة في أس فل البرن امج وتنفي ذها (كم ا فعلن ا في‬
‫إن العدي د من لغ ات البرمج ة (مث ل ‪ C++‬و ‪ )Java‬تتطلب وج ود دال ة رئيس ية‬
‫األمثل ة أعاله)‪ ،‬ف َّ‬
‫إلزاميا‪ ،‬يمكن أن يهيكل برامج ب ايثون بطريق ة‬
‫إن تضمين دالة )(‪ ،main‬وإن لم يكن‬
‫تدعى ‪َّ .main‬‬
‫ً‬
‫منطقية‪ ،‬فتضع أهم مكونات البرنامج في دالة واحدة‪ .‬كما يمكن أن يجعل البرن امج أك ثر مقروئي ة‬
‫للمبرمجين غير البايثونيِّ ين‪.‬‬
‫س نبدأ بإض افة دال ة )(‪ main‬إلى برن امج ‪ hello.py‬أعاله‪ .‬س نحتفظ بالدال ة )(‪ ،hello‬ثم‬
‫ِّ‬
‫نعرف الدالة )(‪:main‬‬
‫‪def hello():‬‬
‫)"مرحبا بالعالم"(‪print‬‬
‫‪def main():‬‬
‫ضمن الدالة )(‪ ،main‬سندرج الدالة )(‪ ،print‬والتي ستعُ لِمنا َّ‬
‫ً‬
‫أيض ا‬
‫بأننا في الدال ة )(‪.main‬‬
‫سنستدعي الدالة )(‪ hello‬داخل )(‪:main‬‬
‫‪298‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def hello():‬‬
‫)"مرحبا بالعالم"(‪print‬‬
‫‪def main():‬‬
‫)"هذه هي الدالة الرئيسية"(‪print‬‬
‫)(‪hello‬‬
‫أخي ًرا‪ ،‬في أسفل البرنامج‪ ،‬سنستدعي الدالة )(‪:main‬‬
‫‪def hello():‬‬
‫)"!مرحبا بالعالم"(‪print‬‬
‫‪def main():‬‬
‫)"‪.‬هذه هي الدالة الرئيسية"(‪print‬‬
‫)(‪hello‬‬
‫)(‪main‬‬
‫اآلن يمكننا تنفيذ برنامجنا‪:‬‬
‫‪python hello.py‬‬
‫وسنحصل على المخرجات التالية‪:‬‬
‫‪.‬هذه هي الدالة الرئيسية‬
‫!مرحبا بالعالم‬
‫لمَّ ا اس تدعينا الدال ة )(‪ hello‬داخ ل )(‪ ،main‬ثم َّ‬
‫نفذنا الدال ة )(‪ main‬وح دها‪ ،‬فق د ُطب ع‬
‫النص "مرحبا بالعالم!" مرة واحدة فقط‪ ،‬وذلك عقب السلسلة النصية التي أخبرتن ا بأنن ا في الدال ة‬
‫الرئيسية‪( .‬سنعمل اآلن م ع دوال مُ تع ِّددة‪ ،‬ل ذلك من المستحس ن أن تراج ع نطاق ات المتغ يرات في‬
‫فصل المتغيرات إن كنت قد نسيتها‪).‬‬
‫‪299‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫إذا عرَّ فت متغي ًرا داخل دال ة‪ ،‬فال يمكن ك أن تس تخدم ذل ك المتغ ير إال ض من تل ك الدال ة‪ .‬ل ذا‪،‬‬
‫إن أردت اس تخدام متغ ير م ا في ع دة دوال‪ ،‬فق د يك ون من األفض ل اإلعالن عن ه متغ ي ًرا‬
‫عامً ا (‪.)global variable‬‬
‫في ب ايثون‪ ،‬يع ُّد '__‪ '__main‬اس م النط اق ال ذي س ُت َّ‬
‫نفذ في ه الش يفرة العليا‬
‫(‪ .)top-level code‬عند تنفيذ برنامج من الدخل القياسي (‪ ،)standard input‬أو من س كربت‪ ،‬أو‬
‫من سطر األوامر‪ ،‬سيتم ضبط __‪ __name‬عند القيمة '__‪.'__main‬‬
‫لهذا السبب‪ ،‬اصطلح مطورو بايثون على استخدام الصياغة التالية‪:‬‬
‫‪if __name__ == '__main__':‬‬
‫ُنّ‬
‫فذ لو كان هذا هو البرنامج الرئيسي ‪#‬‬
‫الشفرة التي ست‬
‫هذه الصياغة تتيح استخدام ملفات بايثون إما‪:‬‬
‫•‬
‫برامج رئيسية‪ ،‬مع تنفيذ ما يلي التعليمة ‪ ،if‬أو‬
‫•‬
‫وحدات عادية‪ ،‬مع عدم تنفيذ ما يتبع التعليمة ‪.if‬‬
‫ست َّ‬
‫ُ‬
‫نفذ الش فرة غ ير المُ تض ِّمنة في العب ارة ‪ if __name__ == '__main__':‬عن د التنفي ذ‪.‬‬
‫إذا كنت تس تخدم مل ف ب ايثون كوح دة‪ ،‬فس ُت َّ‬
‫ً‬
‫أيض ا الش يفرة البرمجي ة غ ير المُ تض ِّمنة في ه ذه‬
‫نفذ‬
‫العبارة عند استيراد ذلك الملف‪.‬‬
‫ِّ‬
‫نوسع البرنامج ‪ names.py‬أعاله‪ ،‬لننش ئ ملف ا جدي ًدا يس مى ‪ .more_names.py‬س نعلن‬
‫دعنا‬
‫ِّ‬
‫ِّ‬
‫نقس م في ه التعليم ات إلى‬
‫لية بش كل‬
‫في هذا البرنامج عن متغير عام‪،‬‬
‫ونعدل الدالة )(‪ names‬األص َّ‬
‫دالتين منفصلتين‪.‬‬
‫‪300‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫َّ‬
‫تتحقق الدال ة األولى )(‪ has_vowel‬مم ا إذا ك انت السلس لة النص ية ‪ name‬تحت وي على‬
‫س‬
‫ح رف عل ة (‪ .)vowel‬وتطب ع الدال ة الثاني ة )(‪ print_letters‬ك ل ح رف من السلس لة‬
‫النصية ‪.name‬‬
‫اإلعالن عن متغير عام الستخدامه في جميع الدوال ‪#‬‬
‫))'‪:‬أدخل اسمك باللغة اإلنجليزية'(‪name = str(input‬‬
‫تعريف دالة للتحقق من أن ‪ name‬يحتوي حرف علة ‪#‬‬
‫‪def has_vowel():‬‬
‫‪if set('aeiou').intersection(name.lower()):‬‬
‫)'اسمك يحتوي حرف علة'(‪print‬‬
‫‪else:‬‬
‫)'اسمك ال يحتوي حرف علة'(‪print‬‬
‫المرور على حروف ‪# name‬‬
‫‪def print_letters():‬‬
‫‪for letter in name:‬‬
‫)‪print(letter‬‬
‫بع د ذل ك‪ ،‬دعن ا نع ِّرف الدال ة )(‪ main‬ال تي َستس تدعي كال من الدال ة )(‪has_vowel‬‬
‫والدالة )(‪.print_letters‬‬
‫اإلعالن عن متغير عام الستخدامه في جميع الدوال ‪#‬‬
‫))'‪:‬أدخل اسمك باللغة اإلنجليزية'(‪name = str(input‬‬
‫ّ ‪ name‬يحتوي حرف علة ‪#‬‬
‫تعريف دالة للتحقق من أن‬
‫‪def has_vowel():‬‬
‫‪if set('aeiou').intersection(name.lower()):‬‬
‫‪301‬‬
‫|‬
‫▲‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫البرمجة بلغة بايثون‬
‫)'اسمك يحتوي حرف علة'(‪print‬‬
‫‪else:‬‬
‫)'اسمك ال يحتوي حرف علة'(‪print‬‬
‫المرور على حروف ‪# name‬‬
‫‪def print_letters():‬‬
‫‪for letter in name:‬‬
‫)‪print(letter‬‬
‫تعريف الدالة ‪ main‬التي ستستدعي بقية الدوال ‪#‬‬
‫‪def main():‬‬
‫)(‪has_vowel‬‬
‫)(‪print_letters‬‬
‫أخ ي ًرا‪ ،‬سنض يف العب ارة ‪ if __name__ == '__main__':‬في أس فل المل ف‪ .‬لق د وض عنا‬
‫جميع الدوال التي نو ُّد تنفيذها في الدالة )(‪ ،main‬لذا سنستدعي الدالة )(‪ main‬بعد الشرط ‪.if‬‬
‫اإلعالن عن متغير عام الستخدامه في جميع الدوال ‪#‬‬
‫))'‪:‬أدخل اسمك'(‪name = str(input‬‬
‫تعريف دالة للتحقق من أن ‪ name‬يحتوي حرف علة ‪#‬‬
‫‪def has_vowel():‬‬
‫‪if set('aeiou').intersection(name.lower()):‬‬
‫)'اسمك يحتوي حرف علة'(‪print‬‬
‫‪else:‬‬
‫)'اسمك ال يحتوي حرف علة'(‪print‬‬
‫المرور على حروف ‪# name‬‬
‫‪302‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def print_letters():‬‬
‫‪for letter in name:‬‬
‫)‪print(letter‬‬
‫تعريف الدالة ‪ main‬التي ستستدعي بقية الدوال ‪#‬‬
‫‪def main():‬‬
‫)(‪has_vowel‬‬
‫)(‪print_letters‬‬
‫تنفيذ الدالة )(‪# main‬‬
‫‪if __name__ == '__main__':‬‬
‫)(‪main‬‬
‫يمكننا اآلن تنفيذ البرنامج‪:‬‬
‫‪python more_names.py‬‬
‫أن الشفرة هن ا‬
‫بيد َّ‬
‫سيعرض هذا البرنامج نفس المخرجات التي عرضها البرنامج ‪ْ ،names.py‬‬
‫أكثر تنظيمً ا‪ ،‬ويمكن استخدامها بطريقة تركيبية (‪.)modular‬‬
‫إذا لم ترغب في اإلعالن عن الدالة )(‪ ،main‬يمكنك بداًل من ذلك إنهاء البرنامج كما يلي‪:‬‬
‫‪...‬‬
‫‪if __name__ == '__main__':‬‬
‫)(‪has_vowel‬‬
‫)(‪print_letters‬‬
‫ي‬
‫ؤدي اس‬
‫تخدام دال‬
‫ة رئيس‬
‫ية مث‬
‫ل )(‪ ،main‬واس‬
‫ارة‬
‫تخدام العب‬
‫‪ if __name__ == '__main__':‬إلى تنظيم الشيفرة البرمجية بطريقة منطقية‪ ،‬وجعلها أك ثر‬
‫مقروئية وتراكبية‪.‬‬
‫‪303‬‬
‫|‬
‫▲‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫البرمجة بلغة بايثون‬
‫‪ .7‬استخدام ‪ *args‬و ‪**kwargs‬‬
‫تع ُّد المعامالت في تعاريف الدوال كيانات مسماة ُتح ِّدد وس ً‬
‫يطا (‪ )argument‬يمكن أن يُ م رَّ ر‬
‫إلى الدالة المُ عرَّ فة‪.‬‬
‫أثن اء البرمج ة‪ ،‬ق د ال ت درك جمي ع ح االت االس تخدام الممكن ة للش يفرة‪ ،‬ل ذا ق د ت رغب في‬
‫توسيع خيارات المبرمجين المستقبليين الذين سيستخدمون الوحدة التي طورتها‪.‬‬
‫كيفية تمري ر ع دد متغ ير من الوس ائط إلى دال ة م ا باس تخدام‬
‫س نتعلم في ه ذا القس م‬
‫َّ‬
‫الصياغتين ‪ *args‬و ‪.**kwargs‬‬
‫ا‪*args .‬‬
‫في بايثون‪ ،‬يمكن اس تخدام الش كل أح ادي النجم ة ‪ *args‬مع اماًل لتمري ر قائم ة غ ير مح َّددة‬
‫الطول من الوسائط غ ير المس ماة (‪ )non-keyworded argument‬إلى ال دوال‪ .‬تج در اإلش ارة إلى‬
‫أن الكلم ة ‪ args‬متع ارف عليه ا بين الم برمجين‪ ،‬إال َّ‬
‫أنه ا‬
‫أن النجمة (*) عنص ر ض روري هن ا‪ ،‬إذ رغم َّ‬
‫َّ‬
‫غير رسمية‪.‬‬
‫لنلق نظرة على مثال لدالة تستخدم وسيطين‪:‬‬
‫ِ‬
‫‪def multiply(x, y):‬‬
‫)‪print (x * y‬‬
‫عرَّ فنا في الشيفرة أعاله دالة تقبل وسيطين ‪ x‬و ‪ ،y‬عندما نستدعي هذه الدالة‪ ،‬س نحتاج إلى‬
‫تمرير ع ددين م وافقين للوس يطين ‪ x‬و ‪ .y‬في ه ذا المث ال‪ ،‬س ِّ‬
‫نمرر الع دد الص حيح ‪ 5‬إلى ‪ ،x‬والع دد‬
‫الصحيح ‪ 4‬إلى ‪:y‬‬
‫‪304‬‬
‫|‬
‫▲‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫البرمجة بلغة بايثون‬
‫‪def multiply(x, y):‬‬
‫)‪print (x * y‬‬
‫)‪multiply(5, 4‬‬
‫عند تنفيذ الشفرة أعاله‪:‬‬
‫‪python lets_multiply.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪20‬‬
‫ً‬
‫الحقا حساب ناتج ض رب ثالث ة أع داد ب داًل من ع ددين فق ط؟ إذا ح اولت تمري ر‬
‫ماذا لو قرَّ رنا‬
‫عدد إضافي إلى الدالة‪ ،‬كما هو موضح أدناه‪:‬‬
‫‪def multiply(x, y):‬‬
‫)‪print (x * y‬‬
‫)‪multiply(5, 4, 3‬‬
‫فسي َ‬
‫طلق الخطأ التالي‪:‬‬
‫ُ‬
‫‪TypeError: multiply() takes 2 positional arguments but 3 were‬‬
‫‪given‬‬
‫ً‬
‫إذا ش ككت َّ‬
‫الحق ا‪ ،‬فالح ل ه و‬
‫أنك س تحتاج إلى اس تخدام المزي د من الوس ائط‬
‫اس تخدام ‪ *args‬مع امال‪ .‬س نزيل المُ ع املين ‪ x‬و ‪ y‬من الش يفرة في المث ال األول‪ ،‬ونض ع‬
‫مكانهما ‪:*args‬‬
‫‪305‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def multiply(*args):‬‬
‫‪z = 1‬‬
‫‪for num in args:‬‬
‫‪z *= num‬‬
‫)‪print(z‬‬
‫)‪multiply(4, 5‬‬
‫)‪multiply(10, 9‬‬
‫)‪multiply(2, 3, 4‬‬
‫)‪multiply(3, 5, 10, 6‬‬
‫عندما ِّ‬
‫ننفذ هذه الشيفرة‪ ،‬سنحصل على ناتج استدعاءات الدالة أعاله‪:‬‬
‫‪20‬‬
‫‪90‬‬
‫‪24‬‬
‫‪900‬‬
‫يمكنن ا باس تخدام الوس يط ‪ *args‬تمري ر أي ع دد نحب من الوس ائط عن د اس تدعاء الدال ة‬
‫باإلض افة إلى كتاب ة ش يفرة أك ثر مرون ة‪ ،‬وإنش اء دوال تقب ل ع د ًدا غ ير مح دد مس ً‬
‫بقا من الوس ائط‬
‫غير المسماة‪.‬‬
‫ب‪**kwargs .‬‬
‫متغير الطول من الوسائط المس ماة‬
‫يُ ستخ َدم الشكل ذو النجمتين ‪ **kwargs‬لتمرير قاموس‬
‫َّ‬
‫أن اس تخدام الكلم ة ‪kwargs‬‬
‫إلى الدال ة المعرَّ ف ة‪ .‬م رة أخ رى‪ ،‬النجمت ان (**) ض روريتان‪ ،‬فم ع َّ‬
‫متعارف عليه لدى المبرمجين‪ ،‬إال َّ‬
‫أنها غير رسمية‪.‬‬
‫أي ع دد من الوس ائط ال تي ت رغب في‬
‫يمكن أن تأخ ذ ‪ ،**kwargs‬كم ا ه و ش أن ‪َّ ،*args‬‬
‫‪306‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫أن ‪ **kwargs‬تختل ف عن ‪ *args‬في َّ‬
‫أنه ا تس توجب تع يين أس ماء‬
‫بي د ّ‬
‫تمريره ا إلى الدال ة ْ‬
‫المعامالت (‪.)keywords‬‬
‫في المثال التالي‪ ،‬ستطبع الدالة الوسيط ‪ **kwargs‬الممرر إليها‪:‬‬
‫‪def print_kwargs(**kwargs):‬‬
‫)‪print(kwargs‬‬
‫ِّ‬
‫ونمرر إليها بعض الوسائط المسماة‪:‬‬
‫سنستدعي اآلن الدالة‬
‫‪def print_kwargs(**kwargs):‬‬
‫)‪print(kwargs‬‬
‫)‪print_kwargs(kwargs_1="Shark", kwargs_2=4.5, kwargs_3=True‬‬
‫ِّ‬
‫لننفذ البرنامج أعاله‪:‬‬
‫‪python print_kwargs.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫}'‪{'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark‬‬
‫مرتب ا‪ .‬في ب ايثون ‪3.6‬‬
‫اعتما ًدا على إصدار بايثون ‪ 3‬الذي تس تخدمه‪ ،‬فق د ال يك ون الق اموس‬
‫ً‬
‫وم ا بع ده‪ ،‬ستحص ل على أزواج قيم ة‪-‬مفت اح (‪ )key-value‬مرتب ة‪ ،‬ولكن في اإلص دارات الس ابقة‪،‬‬
‫عشوائيا‪.‬‬
‫سيكون ترتيب األزواج‬
‫ً‬
‫سي َ‬
‫نش أ ق اموس يس مى ‪ ،kwargs‬وال ذي يمكنن ا التعام ل مع ه مث ل أي ق اموس ع ادي‬
‫ُ‬
‫داخل الدالة‪.‬‬
‫‪307‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫ تعريفها واستعمالها‬:‫الدوال‬
ً
‫قاموس ا من‬
‫ سننش ئ دال ة تطب ع‬.**kwargs ‫كيفية اس تخدام‬
‫برنامج ا آخ ر إلظه ار‬
‫لننش ئ‬
ً
َّ
:‫ سنبدأ بقاموس يحوي اسمين‬،ً‫ أوال‬.‫األسماء‬
def print_values(**kwargs):
for key, value in kwargs.items():
print("The value of {} is {}".format(key, value))
print_values(my_name="Sammy", your_name="Casey")
:‫بعد تنفيذ البرنامج عبر األمر التالي‬
python print_values.py
:‫سنحصل على ما يلي‬
The value of your_name is Casey
The value of my_name is Sammy
َّ
.‫ثانيا‬
‫ وقد يظهر‬، ‫ أواًل‬Casey ‫ لذلك قد يظهر االسم‬،‫مرتبة‬
‫قد ال تكون القواميس‬
ً
ِّ ‫س ُن‬
‫أي ع دد‬
َّ ‫مرر اآلن وس ائط إض‬
َّ **kwargs ‫افية إلى الدال ة ل نرى كي ف يمكن أن تقب ل‬
:‫من الوسائط‬
def print_values(**kwargs):
for key, value in kwargs.items():
print("The value of {} is {}".format(key, value))
print_values(
name_1="Alex",
name_2="Gray",
name_3="Harper",
name_4="Phoenix",
name_5="Remy",
▲
|
308
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫"‪name_6="Val‬‬
‫)‬
‫إذا َّ‬
‫نف ذنا البرنامج اآلن‪ ،‬فسنحصل على المخرجات التالية‪ ،‬والتي قد تكون غير مرتبة‪:‬‬
‫‪The value of name_2 is Gray‬‬
‫‪The value of name_6 is Val‬‬
‫‪The value of name_4 is Phoenix‬‬
‫‪The value of name_5 is Remy‬‬
‫‪The value of name_3 is Harper‬‬
‫‪The value of name_1 is Alex‬‬
‫ً‬
‫يرة في اس تخدام الوس ائط المس ماة‪ .‬فعن د‬
‫ي تيح ل ك اس تخدام ‪ **kwargs‬مرون ًة كب‬
‫استخدامها‪ ،‬لن نحتاج إلى معرفة مسبقة بعدد الوسائط التي ستمرر إلى الدالة‪.‬‬
‫‪ .8‬ترتيب الوسائط‬
‫عند الخلط بين عدة أن واع من الوس ائط داخ ل دال ة‪ ،‬أو داخ ل اس تدعاء دال ة‪ ،‬يجب أن تظه ر‬
‫الوسائط وفق الترتيب التالي‪:‬‬
‫•‬
‫الوسائط العادية‬
‫•‬
‫‪*args‬‬
‫•‬
‫الوسائط المسمّ اة‬
‫•‬
‫‪**kwargs‬‬
‫عملي ا‪ ،‬عن د الجم ع بين المع امالت العادي ة‪ ،‬والوس يطين ‪ *args‬و ‪ ،**kwargs‬فينبغي أن‬
‫ً‬
‫تكون وفق الترتيب التالي‪:‬‬
‫‪309‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫‪def example(arg_1, arg_2, *args, **kwargs):‬‬
‫‪...‬‬
‫وعن د الجم ع بين المع امالت العادي ة والمع امالت المس ماة و ‪ *args‬و ‪ ،**kwargs‬ينبغي أن‬
‫تكون وفق الترتيب التالي‪:‬‬
‫‪def example2(arg_1, arg_2, *args, kw_1="shark",‬‬
‫‪kw_2="blobfish", **kwargs):‬‬
‫‪...‬‬
‫من المهم أن تأخ ذ في الحس بان ت رتيب الوس ائط عن د إنش اء ال دوال ح تى ال تتس بب في‬
‫متعلق بالصياغة‪.‬‬
‫إطالق خطٍأ‬
‫ٍ‬
‫‪ .9‬استخدام ‪ *args‬و ‪ **kwargs‬في استدعاءات الدوال‬
‫ً‬
‫أيضا استخدام ‪ *args‬و ‪ **kwargs‬لتمرير الوس ائط إلى ال دوال‪ .‬أواًل ‪ ،‬دعن ا ننظ ر إلى‬
‫يمكننا‬
‫مثال يستخدم ‪:*args‬‬
‫‪def some_args(arg_1, arg_2, arg_3):‬‬
‫)‪print("arg_1:", arg_1‬‬
‫)‪print("arg_2:", arg_2‬‬
‫)‪print("arg_3:", arg_3‬‬
‫)"‪args = ("Sammy", "Casey", "Alex‬‬
‫)‪some_args(*args‬‬
‫في الدالة أعاله‪ ،‬هناك ثالثة معامالت‪ ،‬وهي ‪ arg_1‬و _‪ arg‬و ‪ .arg_3‬ستطبع الدالة كل هذه‬
‫الوس ائط‪ .‬بع د ذل ك أنش أنا متغ ي ًرا‪ ،‬وَأ حلن ا علي ه عنص رًا تكراريً ا (في ه ذه الحال ة‪ ،‬ص ف)‪ ،‬ثم مرَّ رن ا‬
‫ذلك المتغير إلى الدالة باستخدام الصياغة النجمية (‪.)asterisk syntax‬‬
‫‪310‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫عن دما ِّ‬
‫ننفذ البرن امج باس تخدام األم ر ‪some_args.py‬‬
‫‪ ،python‬سنحص ل على‬
‫المخرجات التالية‪:‬‬
‫‪arg_1: Sammy‬‬
‫‪arg_2: Casey‬‬
‫‪arg_3: Alex‬‬
‫ً‬
‫ً‬
‫أيض ا ‪ *args‬م ع‬
‫أيض ا تع ديل البرن امج أعاله‪ ،‬واس تخدام قائم ة‪ .‬س ندمج‬
‫يمكنن ا‬
‫وسيط مسمى‪:‬‬
‫‪def some_args(arg_1, arg_2, arg_3):‬‬
‫)‪print("arg_1:", arg_1‬‬
‫)‪print("arg_2:", arg_2‬‬
‫)‪print("arg_3:", arg_3‬‬
‫]‪my_list = [2, 3‬‬
‫)‪some_args(1, *my_list‬‬
‫إذا َّ‬
‫نفذنا البرنامج أعاله‪ ،‬فسنحصل على المخرجات التالية‪:‬‬
‫‪arg_1: 1‬‬
‫‪arg_2: 2‬‬
‫‪arg_3: 3‬‬
‫وبالمثل‪ ،‬يمكن استخدام الوسائط المسماة ‪ **kwargs‬الستدعاء دالة‪.‬‬
‫قاموس ا من ‪ 3‬أزواج مفت اح‪-‬قيم ة (سنس تخدم ‪ kwargs‬هن ا‪،‬‬
‫سننش ئ متغ يرًا‪ ،‬ونس ند إلي ه‬
‫ً‬
‫ولكن يمكنك تسميته ما تشاء)‪ ،‬ثم ُن ِّ‬
‫مرره إلى دالة ذات ‪ 3‬وسائط‪:‬‬
‫‪311‬‬
‫|‬
‫▲‬
‫الدوال‪ :‬تعريفها واستعمالها‬
‫البرمجة بلغة بايثون‬
‫‪def some_kwargs(kwarg_1, kwarg_2, kwarg_3):‬‬
‫)‪print("kwarg_1:", kwarg_1‬‬
‫)‪print("kwarg_2:", kwarg_2‬‬
‫)‪print("kwarg_3:", kwarg_3‬‬
‫‪kwargs = {"kwarg_1": "Val", "kwarg_2": "Harper", "kwarg_3":‬‬
‫}"‪"Remy‬‬
‫)‪some_kwargs(**kwargs‬‬
‫عن د تنفي ذ البرن امج أعاله باس تخدام األم ر ‪ ،python some_kwargs.py‬سنحص ل على‬
‫المخرجات التالية‪:‬‬
‫‪kwarg_1: Val‬‬
‫‪kwarg_2: Harper‬‬
‫‪kwarg_3: Remy‬‬
‫‪ .10‬خالصة الفصل‬
‫ال دوال هي كت ل من التعليم ات البرمجي ة ال تي ُت ِّ‬
‫معين ة داخ ل البرن امج‪ ،‬كم ا‬
‫نفذ إج راءات‬
‫َّ‬
‫تس اعد على جع ل الش يفرة تركيبي ة‪ ،‬وقابل ة إلع ادة االس تخدام باإلض افة إلى تنظيمه ا وتس هيل‬
‫قراءتها‪( .‬لمعرفة المزيد حول كيفية جعل الشفرة تركيبية‪ ،‬يمكنك الرجوع إلى فصل الوحدات‪).‬‬
‫يمكنك اس تخدام الص ياغتين ‪ *args‬و ‪ **kwargs‬الخاص تين ض من َتع اريف وس ائط ال دوال‬
‫أي عدد تشاء من الوسائط إليها‪ ،‬إذ يُ ستحس ن اس تخدام ‪ *args‬و ‪ **kwargs‬في المواق ف‬
‫لتمرير ِّ‬
‫بيا‪ .‬وض ع في ذهن ك أن‬
‫ال تي تتوق ع أن يظ ل فيه ا ع دد الم دخالت في قائم ة الوس ائط ص غي ًرا نس ً‬
‫ِّ‬
‫يحس ن مقروئي ة الش يفرة‪ ،‬ويس ِّهل على الم برمجين‪ ،‬ولكن ينبغي‬
‫اس تخدام ‪ *args‬و ‪**kwargs‬‬
‫استخدامهما بحذر‪.‬‬
‫‪312‬‬
‫|‬
‫▲‬
‫‪17‬‬
‫الوحدات‪ :‬استيرادها‬
‫وإنشاؤها‬
‫‪313‬‬
‫|‬
‫▲‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫البرمجة بلغة بايثون‬
‫توفر لغة بايثون مجموعة متنوعة من الدوال المضمَّ نة مثل‪:‬‬
‫•‬
‫)(‪ :print‬تطبع التعابير المُ مرَّ رة إليها في مجرى الخرج‬
‫•‬
‫)(‪ُ :abs‬تعيد القيمة المطلقة للعدد‬
‫•‬
‫ِّ‬
‫تحول القيمة المُ مرَّ رة إليها إلى عدد صحيح‬
‫)(‪:int‬‬
‫•‬
‫)(‪ُ :len‬تعيد طول تسلسل أو مجموعة‬
‫هذه الدوال المضمَّ نة مفيدة‪ ،‬لكنها محدودة‪ ،‬له ذا يس تخدم المط ورون الوح دات (‪)modules‬‬
‫لتط وير ب رامج أك ثر تعقي ًدا‪ .‬الوح دات (‪ )Modules‬هي ملف ات ب ايثون ذات امت داد ‪ ،.py‬وال تي‬
‫أي ملف بايثون على أنه وحدة‪ .‬مثاًل ‪ ،‬إن ك ان هن اك مل ف‬
‫تحوي شيفرات بايثون‪ .‬يمكن التعامل مع ِّ‬
‫ب ايثون يس مى ‪ ،hello.py‬فس يكون اس م الوح دة المقابل ة ل ه ‪ ،hello‬وال ذي يمكن اس تيراده في‬
‫ملفات بايثون األخرى‪ ،‬أو استخدامه في مترجم (‪ )interpreter‬سطر أوامر بايثون‪.‬‬
‫يمكن للوح دات أن تع ِّرف دوااًل وأص ً‬
‫نافا ومتغ يرات يمكن الرج وع إليه ا من ملف ات ب ايثون‬
‫األخرى‪ ،‬أو من مترجم سطر أوامر بايثون‪.‬‬
‫في ب ايثون‪ ،‬يمكن ك الوص ول إلى الوح دات باس تخدام التعليم ة ‪ .import‬عن د فع ل ذل ك‪،‬‬
‫س ُت َّ‬
‫نفذ ش يفرة الوح دة‪ ،‬م ع االحتف اظ بنطاق ات ( ‪ )scopes‬التعريف ات ح تى تك ون متاح ة في‬
‫ملفك الحالي‪ .‬فعندما تس تورد ب ايثون وح ً‬
‫دة باس م ‪ hello‬على س بيل المث ال‪ ،‬فس يبحث الم ترجم‬
‫أواًل عن وحدة مضمَّ نة باسم ‪ .hello‬فإن لم يجد‪ ،‬فسيبحث عن ملف يسمى ‪ hello.py‬في قائمة‬
‫من المجلدات يحددها المتغير ‪.sys.path‬‬
‫سيرشدك هذا الفصل إلى كيفية البحث عن الوحدات وتثبيتها‪ ،‬واستيرادها‪ ،‬وإع ادة تس ميتها‬
‫(‪ ،)aliasing‬ثم سيعلمك كيفية إنشاء وحدة كاملة واستعمالها في شيفرة أخرى‪.‬‬
‫‪314‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫‪ .1‬تثبيت الوحدات‬
‫هن اك ع دد من الوح دات المض مَّ نة في مكتب ة ب ايثون القياس ية ال تي تحت وي على العدي د من‬
‫الوح دات ال تي ت وفر الكث ير من وظ ائف النظ ام‪ ،‬أو ت وفر حل واًل قياس ية‪ .‬مكتب ة ب ايثون القياس ية‬
‫تأتي مع كل توزيعات بايثون‪.‬‬
‫أن وح دات ب ايثون ج اهزة للعم ل‪ ،‬ادخ ل إلى بيئ ة برمج ة ب ايثون ‪ 3‬المحلي ة‪ ،‬أو‬
‫للتحق ق من َّ‬
‫ِّ‬
‫وشغل مترجم بايثون في سطر األوامر على النحو التالي‪:‬‬
‫بيئة البرمجة المستندة إلى الخادم‪،‬‬
‫‪(my_env) sammy@ubuntu:~/environment$ python‬‬
‫من داخل المترجم‪ ،‬يمكنك تنفيذ التعليمة ‪ import‬مع اسم الوحدة للتأكد من َّ‬
‫أنها جاهزة‪:‬‬
‫‪import math‬‬
‫لمَّ ا ك انت ‪ math‬وح دة مض مَّ نة‪ ،‬فينبغي أن يُ كم ل الم ترجم المهم ة دون أي مش اكل‪ ،‬ثم يع ود‬
‫إلى المحث (‪ .)prompt‬ه ذا يع ني َّ‬
‫أي ش يء للب دء في اس تخدام‬
‫أنك لس ت بحاج ة إلى فع ل ِّ‬
‫الوحدة ‪.math‬‬
‫ِّ‬
‫ثبت ة عن دك‪ ،‬مث ل ‪ ،matplotlib‬وهي‬
‫لننفذ اآلن التعليم ة ‪ import‬م ع وح دة ق د ال تك ون مُ َّ‬
‫مكتبة للرسم ثنائي األبعاد‪:‬‬
‫‪import matplotlib‬‬
‫ٌأ‬
‫ثبتة‪ ،‬فسيظهر خط مثل الخطأ التالي‪:‬‬
‫إذا لم تكن ‪ matplotlib‬مُ َّ‬
‫'‪ImportError: No module named 'matplotlib‬‬
‫يمكنك إيقاف مترجم بايثون بالضغط على ‪ ،CTRL + D‬ثم تثبيت الوحدة ‪ matplotlib‬عبر‬
‫‪315‬‬
‫|‬
‫▲‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫البرمجة بلغة بايثون‬
‫‪ pip‬بتنفيذ األمر التالي‪:‬‬
‫‪(my_env) sammy@ubuntu:~/environment$ pip install matplotlib‬‬
‫بمج رد تثبيته ا‪ ،‬يمكن ك اس تيراد ‪ matplotlib‬من م ترجم ب ايثون باس تخدام‬
‫‪ ،import matplotlib‬ولن يحدث أي خطأ‪.‬‬
‫‪ .2‬استيراد الوحدات‬
‫لالس تفادة من ال دوال الموج ودة في الوح دة‪ ،‬س تحتاج إلى اس تيراد الوح دة ع بر التعليم ة‬
‫‪ ،import‬إذ تتألف من الكلمة المفتاحية ‪ import‬معقوبة باسم الوحدة كما في المثال اآلتي‪.‬‬
‫يُ ص رَّ ح عن عملي ة اس تيراد الوح دات في أعلى ملف ات ب ايثون‪ ،‬قب ل األس طر التوجيهي ة‬
‫(‪ shebang lines‬أي األس طر ال تي تب دأ بـ !‪ ،)#‬أو التعليق ات العام ة‪ .‬ل ذلك‪ ،‬سنس تورد في مل ف‬
‫برنامج بايثون ‪ my_rand_int.py‬الوحدة ‪ random‬لتوليد أعداد عشوائية على النحو التالي‪:‬‬
‫‪import random‬‬
‫عن دما نس تورد وح دة‪ ،‬نجعله ا ب ذلك متاح ة في برنامجن ا الح الي بوص فها فض اء اس م‬
‫يتعين علين ا الوص ول إلى الدال ة باس تخدام الص ياغة النقطي ة‬
‫(‪ )namespace‬منفص ل‪ .‬أي س‬
‫َّ‬
‫(‪ )dot notation‬على النحو التالي ]‪.[module].[function‬‬
‫عمليا‪ ،‬ستبدو الشيفرة باستخدام مثال الوحدة ‪ random‬كما يلي‪:‬‬
‫ً‬
‫•‬
‫)(‪ :random.randint‬تستدعي الدالة إلعادة عدد صحيح عشوائي‪ ،‬أو‬
‫•‬
‫)(‪ :random.randrange‬تستدعي الدالة إلعادة عنصر عشوائي من نطاق محدد‪.‬‬
‫دعن ا ننش ئ حلق ة ‪ for‬لتوض يح كيفي ة اس تدعاء دال ة من الوح دة ‪ random‬ض من‬
‫‪316‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫البرنامج ‪:my_rand_int.py‬‬
‫‪import random‬‬
‫‪for i in range(10):‬‬
‫))‪print(random.randint(1, 25‬‬
‫يس تورد ه ذا البرن امج الص غير الوح دة ‪ random‬في الس طر األول‪ ،‬ثم ينتق ل إلى الحلق ة ‪for‬‬
‫ً‬
‫وائيا من المج ال ‪1‬‬
‫حيحا عش‬
‫التي ستمر على ‪ 10‬عناص ر‪ .‬داخ ل الحلق ة‪ ،‬س يطبع البرن امج ع د ًدا ص‬
‫ً‬
‫إلى ‪( 25‬مش‬
‫مول)‪ .‬يُ م‬
‫رّّ ر الع‬
‫ددان الص‬
‫حيحان ‪ 1‬و ‪ 25‬بوص‬
‫فهما مع‬
‫امالت‬
‫إلى )(‪.random.randint‬‬
‫عن د تنفي ذ البرن امج باس تخدام األم ر ‪ ،python my_rand_int.py‬س تظهر ‪ 10‬أع داد‬
‫ألن ه ذه العناص ر عش وائية‪ ،‬فستحص ل على األرجح على‬
‫صحيحة عشوائية في المخرج ات‪ .‬نظ رًا َّ‬
‫أعداد مختلفة ( كلها محصورة بين ‪ 1‬و ‪ )25‬في كل مرة ِّ‬
‫تنفذ فيه ا البرن امج‪ ،‬لكنَّه ا عمومً ا س تبدو‬
‫كما يلي‪:‬‬
‫‪6‬‬
‫‪9‬‬
‫‪1‬‬
‫‪14‬‬
‫‪3‬‬
‫‪22‬‬
‫‪10‬‬
‫‪1‬‬
‫‪15‬‬
‫‪9‬‬
‫‪317‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫إذا رغبت في اس تخدام دوال من أك ثر من وح دة‪ ،‬يمكن ك ذل ك عن طري ق إض افة ع دة‬
‫تعليمات استيراد‪:‬‬
‫‪import random‬‬
‫‪import math‬‬
‫قد تصادف شيفرات تستورد عدة وحدات مفصولة بفواصل مثل ‪import random, math‬‬
‫ولكن هذا ال يتوافق مع دليل التنسيق ‪.PEP 8‬‬
‫َّ‬
‫افية‪ ،‬يمكنن ا إض افة الث ابت ‪ pi‬من الوح دة ‪ math‬إلى برنامجن ا‪،‬‬
‫لالس تفادة من الوح دة اإلض َّ‬
‫وتقليل عدد األعداد الصحيحة العشوائية المطبوعة‪:‬‬
‫‪import random‬‬
‫‪import math‬‬
‫‪for i in range(5):‬‬
‫))‪print(random.randint(1, 25‬‬
‫)‪print(math.pi‬‬
‫اآلن‪ ،‬عن د تنفي ذ البرن امج‪ ،‬سنحص ل على مخرج ات على الش كل الت الي‪ ،‬م ع تق ريب للع دد ‪pi‬‬
‫في السطر األخير‪:‬‬
‫‪18‬‬
‫‪10‬‬
‫‪7‬‬
‫‪13‬‬
‫‪10‬‬
‫‪3.141592653589793‬‬
‫‪318‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫ِّ‬
‫يمكن ك من‬
‫ت تيح ل ك التعليم ة ‪ import‬اس تيراد وح دة واح دة أو أك ثر إلى برامج ك‪ ،‬وه ذا‬
‫االستفادة مما تحويها تلك الوحدات‪.‬‬
‫محددة‬
‫‪ .3‬استيراد عناصر‬
‫َّ‬
‫لإلش ارة إلى عناص ر من وح دة مس توردة ض من فض اء األس ماء‪ ،‬يمكن ك اس تخدام التعليم ة‬
‫‪ .from ... import‬عن دما تس تورد الوح دات به ذه الطريق ة‪ ،‬س يكون بمق دورك الرج وع إلى‬
‫ال دوال بأس مائها فق ط‪ ،‬ب داًل من اس تخدام الص ياغة النقطي ة‪ .‬في ه ذه الص ياغة‪ ،‬يمكن ك تحدي د‬
‫التعريفات التي تود اإلشارة إليها مباشرة‪.‬‬
‫في بعض ال برامج‪ ،‬ق د ت رى العب ارة * ‪ ،from ... import‬إذ تش ير العالم ة * إلى جمي ع‬
‫ولكن هذه الصياغة غير معتمدة في ‪.PEP 8‬‬
‫العناصر الموجودة في الوحدة‪،‬‬
‫ّ‬
‫سنحاول في البداية استيراد دالة واحدة من الوحدة ‪ ،random‬وهي )(‪:randint‬‬
‫‪from random import randint‬‬
‫هنا‪ ،‬نستدعي أواًل الكلمة المفتاحية ‪ ،from‬ثم ‪ .random‬بعد ذلك‪ ،‬نس تخدم الكلم ة المفتاحي ة‬
‫‪ ،import‬ونستدعي الدالة المحددة التي نو ُّد استخدامها‪.‬‬
‫اآلن‪ ،‬عندما نرغب في اس تخدام ه ذه الدال ة في برنامجن ا‪ ،‬لن نس تدعي الدال ة وف ق الص ياغة‬
‫ً‬
‫مباشرة‪ ،‬أي )(‪:randint‬‬
‫النقطية‪ ،random.randint() ،‬ولكن سنستدعيها باسمها‬
‫‪from random import randint‬‬
‫‪for i in range(10):‬‬
‫))‪print(randint(1, 25‬‬
‫‪319‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫ً‬
‫مسبقا‪.‬‬
‫عند تنفيذ البرنامج‪ ،‬ستتلقى مخرجات مشابهة لما تلقيته‬
‫يتيح لنا استخدام ‪ from ... import‬الرجوع إلى العناصر المعرَّ فة في الوح دة من فض اء‬
‫األسماء الخاص ببرنامجنا‪ ،‬مما يتيح لنا تجنب استخدام الصياغة النقطية الطويلة‪.‬‬
‫‪ .4‬األسماء المستعارة في الوحدات‬
‫يمكن إعط اء أس ماء مس تعارة للوح دات ودواله ا داخ ل ب ايثون باس تخدام الكلم ة‬
‫المفتاحية ‪.as‬‬
‫ألنك تس تخدمه س ً‬
‫لفا في برنامج ك‪ ،‬أو َّ‬
‫قد ترغب في تغي ير اس م م ا َّ‬
‫أنه مس تخدم في وح دة‬
‫أخ رى مس توردة‪ ،‬أو ق د ت رغب في اختص ار اس م طوي ل تس تخدمه كث يرًا‪ .‬يمكن ك ذل ك ع بر‬
‫الصياغة التالية‪:‬‬
‫]‪import [module] as [another_name‬‬
‫ِّ‬
‫نغير اس م الوح دة ‪ math‬إلى ‪m‬‬
‫لنعدل اسم الوحدة ‪ math‬في ملف البرن امج ‪ .my_math.py‬س ّ‬
‫من أجل اختصاره‪ .‬سيبدو برنامجنا المعدل كالتالي‪:‬‬
‫‪import math as m‬‬
‫)‪print(m.pi‬‬
‫)‪print(m.e‬‬
‫سنشير داخل البرنامج إلى الثابت ‪ pi‬بالتعبير ‪ ،m.pi‬بداًل من ‪.math.pi‬‬
‫يشيع في بعض الوحدات استخدام أسماء مستعارة ( ‪ )aliases‬مح َّددة‪ .‬فمثاًل ‪ ،‬يدعو التوثيق‬
‫الرسمي للوحدة ‪ matplotlib.pyplot‬إلى استخدام االسم المستعار ‪:plt‬‬
‫‪320‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫‪import matplotlib.pyplot as plt‬‬
‫يس مح ه ذا للم برمجين بإلح اق الكلم ة القص يرة ‪ plt‬ب أي دال ة متاح ة داخ ل الوح دة‪ ،‬كم ا ه و‬
‫الحال في )(‪.plt.show‬‬
‫مخصصة واستيرادها‬
‫‪ .5‬كتابة وحدات‬
‫َّ‬
‫س نتعلم اآلن كتاب ة وح دات ب ايثون ‪ -‬بع د تعلم كيفي ة اس تيرادها ‪ -‬الس تخدامها في ملف ات‬
‫البرمجة األخرى‪.‬‬
‫كتابة الوحدات مشابه لكتابة أي ملف بايثون آخ ر‪ .‬يمكن أن تحت وي الوح دات على تعريف ات‬
‫الدوال واألصناف والمتغيِّ رات التي يمكن استخدامها بعد ذلك في برامج بايثون األخرى‪.‬‬
‫سننشئ من بيئة البرمج ة الحالي ة الخاص ة بب ايثون ‪ 3‬أو بيئ ة البرمج ة المس تندة إلى الخ ادم‬
‫ًّ‬
‫ً‬
‫الحقا من ملف آخر‪.‬‬
‫ملفا باسم ‪ ،hello.py‬والذي سنستورده‬
‫في البدء‪ ،‬سننشئ دالة تطبع العبارة "!‪:"Hello, world‬‬
‫تعريف دالة ‪#‬‬
‫‪def world():‬‬
‫)"!‪print("Hello, world‬‬
‫إذا َّ‬
‫نفذنا البرنامج في سطر األوامر باستخدام ‪ ،python hello.py‬فلن يح دث ش يء‪َّ ،‬‬
‫ألنن ا‬
‫لم نطلب من البرنامج فعل أي شيء‪.‬‬
‫لننش ئ ً‬
‫ثاني ا في نفس المجلد (أي بج انب المل ف الس ابق) باس م ‪main_program.py‬‬
‫ملف ا‬
‫ً‬
‫حتى نتمكن من استيراد الوحدة التي أنشأناها للت و‪ ،‬ومن ثم اس تدعاء الدال ة‪ .‬يجب أن يك ون ه ذا‬
‫المل ف في نفس المجل د ح تى تع رف ب ايثون موض ع الوح دة‪َّ ،‬‬
‫ألنه ا ليس ت وح دة مُ ض مَّ نة ض من‬
‫مكتبة بايثون‪.‬‬
‫‪321‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫استيراد الوحدة ‪# hello‬‬
‫‪import hello‬‬
‫استدعاء الدالة ‪#‬‬
‫)(‪hello.world‬‬
‫نظرً ا ألننا اس توردنا الوح دة‪ ،‬نحت اج إلى اس تدعاء الدال ة من خالل اإلش ارة إلى اس م الوح دة‬
‫بالص ياغة النقطي ة (‪ .)dot notation‬يمكنن ا ب داًل من ذل ك اس تيراد دال ة مح َّددة من الوح دة‬
‫بالتعليمة ‪ ،from hello import world‬واستدعاء تلك الدالة بالشكل )(‪ world‬كما تعلمنا ذلك‬
‫من الفصل السابق‪ .‬اآلن‪ ،‬يمكننا تنفيذ البرنامج من سطر األوامر‪:‬‬
‫‪python main_program.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫!‪Hello, world‬‬
‫ً‬
‫تعريف ا لمتغيِّ ر في‬
‫ل نرى كي ف يمكنن ا اس تخدام المتغ يرات في الوح دات‪ ،‬دعن ا نض يف‬
‫الملف ‪:hello.py‬‬
‫تعريف دالة ‪#‬‬
‫‪def world():‬‬
‫)"!‪print("Hello, world‬‬
‫تعريف المتغير ‪#‬‬
‫"‪shark = "Sammy‬‬
‫بعد ذلك‪ ،‬سنستدعي المتغير داخل الدالة )(‪ print‬في الملف ‪:main_program.py‬‬
‫‪322‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫ استيرادها وإنشاؤها‬:‫الوحدات‬
# hello ‫استيراد الوحدة‬
import hello
# ‫استدعاء الدالة‬
hello.world()
# ‫طباعة المتغير‬
print(hello.shark)
:‫ سنحصل على المخرجات التالية‬،‫بمجرد تنفيذ البرنامج‬
Hello, world!
Sammy
ً ‫ دعن ا نع ِّرف ص‬،‫أخ ي ًرا‬
‫ وال ذي يحت وي‬،Octopus ‫ سننش ئ الص نف‬.hello.py ‫نفا في المل ف‬
:‫ إضافة إلى دالة تطبع الخاصيات عند استدعائها‬،color ‫ و‬name ‫على الخاصيتين‬
# ‫تعريف الدالة‬
def world():
print("Hello, world!")
# ‫تعريف المتغير‬
shark = "Sammy"
# ‫تعريف الصنف‬
class Octopus:
def __init__(self, name, color):
self.color = color
self.name = name
def tell_me_about_the_octopus(self):
print("This octopus is " + self.color + ".")
print(self.name + " is the octopus's name.")
▲
|
323
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫َ‬
‫الصنف إلى نهاية الملف ‪:main_program.py‬‬
‫سنضيف اآلن‬
‫استيراد الوحدة ‪# hello‬‬
‫‪import hello‬‬
‫استدعاء الدالة ‪#‬‬
‫)(‪hello.world‬‬
‫طباعة المتغير ‪#‬‬
‫)‪print(hello.shark‬‬
‫استدعاء الصنف ‪#‬‬
‫)"‪jesse = hello.Octopus("Jesse", "orange‬‬
‫)(‪jesse.tell_me_about_the_octopus‬‬
‫بمج رد اس تدعاء الص نف ‪ Octopus‬باس تخدام )(‪ ،hello.Octopus‬يمكنن ا الوص ول إلى‬
‫دوال وخاص يات الص نف من فض اء األس ماء الخ اص ب الملف ‪ .main_program.py‬ي تيح لن ا ه ذا‬
‫كتاب ة )(‪ jesse.tell_me_about_the_octopus‬في الس طر األخ ير دون اس تدعاء ‪.hello‬‬
‫ً‬
‫أيض ا‪ ،‬على س بيل المث ال‪ ،‬اس تدعاء إح دى خاص يات الص نف‪ ،‬مث ل ‪ ،jesse.color‬دون‬
‫يمكنن ا‬
‫الرجوع إلى اسم الوحدة ‪.hello‬‬
‫سنحصل عند تنفيذ البرنامج التالي على المخرجات التالية‪:‬‬
‫!‪Hello, world‬‬
‫‪Sammy‬‬
‫‪This octopus is orange.‬‬
‫‪Jesse is the octopus's name.‬‬
‫ً‬
‫أيض ا أن‬
‫من المهم أن تضع في الحسبان أن الوح دات ال تض م تعريف ات دوال فق ط‪ ،‬ب ل يمكن‬
‫‪324‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫ِّ‬
‫وتنفذها‪ .‬لتوض يح ه ذا‪ ،‬دعن ا نعي د كتاب ة المل ف ‪ hello.py‬لنجعل ه يق دم‬
‫تق دم ش يفرات برمجي ة‬
‫ً‬
‫أيضا‪:‬‬
‫الدالة )(‪ world‬وينفذها‬
‫تعريف دالة ‪#‬‬
‫‪def world():‬‬
‫)"!‪print("Hello, world‬‬
‫استدعاء الدالة داخل الوحدة ‪#‬‬
‫)(‪world‬‬
‫ً‬
‫أيض ا التعريف ات األخ رى في المل ف‪ .‬اآلن‪ ،‬في المل ف ‪،main_program.py‬‬
‫لق د ح ذفنا‬
‫سنحذف كل األسطر باستثناء عبارة االستيراد‪:‬‬
‫استيراد الوحدة ‪# hello‬‬
‫‪import hello‬‬
‫عند تنفيذ ‪ ،main_program.py‬سنحصل على المخرجات التالية‪:‬‬
‫!‪Hello, world‬‬
‫ألن الوح دة ‪ hello‬ق دمت الدال ة )(‪ ،world‬وال تي مُ ِّررت بع د ذل ك إلى‬
‫ه ذا َّ‬
‫لت َّ‬
‫‪ُ main_program.py‬‬
‫نفذ مع السكربت ‪.main_program.py‬‬
‫الوح دة هي مل ف ب ايثون مؤل ف من تعريف ات و ش يفرات برمجي ة يمكن االس تفادة منه ا في‬
‫ملفات بايثون األخرى‪.‬‬
‫‪ .6‬الوصول إلى الوحدات من مجلد آخر‬
‫ق د تك ون الوح دات مفي دة ألك ثر من مش روع واح د‪ ،‬وفي ه ذه الحال ة‪ ،‬لن يك ون من الحكم ة‬
‫االحتفاظ بالوحدة في مجلد مرتبط بمشروع خاص‪.‬‬
‫‪325‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫إذا أردت استخدام وحدة من مجلد آخر غير المجلد الذي يح وي البرن امج الرئيس ي‪ ،‬فأمام ك‬
‫ع َّدة خيارات سنسردها فيما يلي‪.‬‬
‫تلقائيا على مسار الوحدة‬
‫ا‪ .‬التعرف‬
‫ً‬
‫أحد الخيارات هو استدعاء مسار الوحدة من الملفات البرمجية ال تي تس تخدم تل ك الوح دة‪.‬‬
‫يُ ع د ه ذا حاًّل مؤق ًت ا يمكن اس تخدامه أثن اء عملي ة التط وير‪َّ ،‬‬
‫ألنه ال يجع ل الوح دة متاح ة على‬
‫مستوى النظام بأكمله‪ .‬إللح اق مس ار وح دة بمل ف ب رمجي آخ ر‪ ،‬س تبدأ باس تيراد الوح دة ‪ ،sys‬إلى‬
‫جانب الوحدات األخرى التي ترغب في استخدامها في ملف البرنامج الرئيسي‪.‬‬
‫زءا من مكتب ة ب ايثون القياس ية‪ ،‬وت وفر مع امالت ودوال نظامي ة يمكن ك‬
‫تعد الوح دة ‪ sys‬ج ً‬
‫استخدامها في برنامجك لتع يين مس ار الوح دة ال تي ت رغب في تق ديمها‪ .‬على س بيل المث ال‪ ،‬لنق ل‬
‫َّ‬
‫أنن ا نقلن ا المل ف ‪ hello.py‬إلى المس ار ‪ ،/usr/sammy/‬بينم ا يوج د المل ف ‪main_program.py‬‬
‫في مجل د آخ ر‪ .‬في المل ف ‪ ،main_program.py‬م ا ي زال بإمكانن ا اس تيراد الوح دة ‪ hello‬عن‬
‫طري ق اس تيراد الوح دة ‪ ،sys‬ثم إض افة المس ار ‪ /usr/sammy/‬إلى المس ارات ال تي يبحث ب ايثون‬
‫فيها عن الملفات‪.‬‬
‫‪import sys‬‬
‫)'‪sys.path.append('/usr/sammy/‬‬
‫‪import hello‬‬
‫‪...‬‬
‫عينت مس ار المل ف ‪ hello.py‬كم ا يجب‪ ،‬فس يكون بمق دورك تنفي ذ المل ف‬
‫إن َّ‬
‫أي أخط اء‪ ،‬وستحص ل على نفس المخرج ات ال تي حص لنا عليه ا أعاله‬
‫‪ main_program.py‬دون ِّ‬
‫عندما كان الملف ‪ hello.py‬في نفس المجلد‪.‬‬
‫‪326‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫ب‪ .‬إضافة الوحدة إلى مسار بايثون‬
‫الخيار الث اني ه و إض افة الوح دة إلى المس ار ال ذي يبحث في ه ب ايثون عن الوح دات والح زم‪،‬‬
‫ً‬
‫متاحة على نطاق البيئة‪ ،‬أو على مستوى النظام‪.‬‬
‫وهذا حل أفضل وأدوم‪ ،‬إذ يجعل الوحدة‬
‫لمعرف ة المس ار ال ذي يبحث في ه ب ايثون‪ ،‬ش ِّغل م ترجم (‪ )interpreter‬ب ايثون من بيئ ة‬
‫البرمجة خاصتك‪:‬‬
‫‪python‬‬
‫بعد ذلك‪ ،‬استورد الوحدة ‪:sys‬‬
‫‪import sys‬‬
‫ثم اطلب من بايثون طباعة مسار النظام‪:‬‬
‫)‪print(sys.path‬‬
‫ستحص ل على بعض المخرج ات‪ ،‬وس ُيطبع مس ار نظ ام واح د على األق ل‪ .‬إذا كنت تعم ل في‬
‫بيئة برمجة‪ ،‬فقد تتلقى العديد منها‪ .‬سيكون عليك البحث عن المسارات الموجودة في البيئة التي‬
‫ً‬
‫أيض ا في إض افة الوح دة إلى مس ار النظ ام الرئيس ي لب ايثون‪.‬‬
‫حالي ا‪ ،‬ولكن ق د ت رغب‬
‫تس تخدمها‬
‫ً‬
‫النتيجة ستكون مشابهة لما يلي‪:‬‬
‫'‪'/usr/sammy/my_env/lib/python3.5/site-packages‬‬
‫يمكنك اآلن نقل الملف ‪ hello.py‬إلى هذا المجلد‪ .‬بعد ذلك‪ ،‬يمكنك استيراد الوح دة ‪hello‬‬
‫مثل المعتاد‪:‬‬
‫‪import hello‬‬
‫‪...‬‬
‫‪327‬‬
‫|‬
‫▲‬
‫الوحدات‪ :‬استيرادها وإنشاؤها‬
‫البرمجة بلغة بايثون‬
‫أي خط أ‪ .‬يض من ل ك تع ديل مس ار الوح دة‬
‫عن د تنفي ذ البرن امج الس ابق‪ ،‬يُ ف ترض أال يح دث ّ‬
‫إمكانية الوصول إليها مهم ا ك ان المجل د ال ذي تعم ل في ه‪ ،‬إذ ه ذا مفي د خاص ة في ح ال كنت تعم ل‬
‫على عدة مشاريع تشير إلى الوحدة نفسها‪.‬‬
‫‪ .7‬خالصة الفصل‬
‫ثبت ة‬
‫يس مح مفه وم الوح دات باس تدعاء دوال غ ير مض مَّ نة في ب ايثون‪ .‬فبعض الوح دات مُ َّ‬
‫نثبتها ع بر ‪ ،pip‬وي تيح لن ا اس تخدام الوح دات توس يع برامجن ا‬
‫كج زء من ب ايثون‪ ،‬وبعض ها س ّ‬
‫وت دعيمها‪ ،‬إذ تض ع تحت تص رُّ فنا ش فرات ج اهزة لالس تخدام‪ ،‬فيمكنن ا إنش اء وح دات خاص ة بن ا‪،‬‬
‫لنستخدمها نحن‪ ،‬أو المبرمجون اآلخرون‪.‬‬
‫‪328‬‬
‫|‬
‫▲‬
‫‪18‬‬
‫بناء األصناف‬
‫واستنساخ الكائنات‬
‫‪329‬‬
‫|‬
‫▲‬
‫بناء األصناف واستنساخ الكائنات‬
‫البرمجة بلغة بايثون‬
‫ب ايثون لغ ٌة برمج ة كائني ة ( ‪ .)object-oriented programming language‬ف ِّ‬
‫تركز البرمج ة‬
‫الكائني ة (‪ )OOP‬على كتاب ة ش يفرات قابل ة إلع ادة االس تخدام‪ ،‬على عكس البرمج ة اإلجرائي ة‬
‫(‪ )procedural programming‬التي تركز على كتابة تعليمات صريحة ومتسلسلة‪.‬‬
‫تتيح البرمجة الكائنية لمبرمجي بايثون كتابة ش يفرات س هلة الق راءة والص يانة‪ ،‬وه ذا مفي د‬
‫للغاية عند تطوير البرامج المُ َّ‬
‫عقدة‪.‬‬
‫التمي يز بين األص ناف والكائن ات أح ُد المف اهيم األساس ية في البرمج ة الكائني ة‪ ،‬ويوض ح‬
‫التعريفان التاليان الفرق بين المفهومين‪:‬‬
‫•‬
‫الصنف (‪ :)class‬نموذج ع ام ُتنس ج على منوال ه كائن ات يُ ِ‬
‫فيع ِّرف الص نف‬
‫نش ئها الم برمج‪ُ .‬‬
‫•‬
‫الك ائن (‪ :)object‬نس ٌ‬
‫خة (‪ُ )instance‬تش تق من ص نف‪ ،‬فه و تجس يد عملي للص نف داخ ل‬
‫ً‬
‫مجموعة من الخاصيات التي تميز أي كائن يُ‬
‫ستنسخ (‪ )instantiated‬منه‪.‬‬
‫َ‬
‫البرنامج‪.‬‬
‫ُتستخ َدم األصناف إلنشاء أنماط‪ ،‬ثم ُتستعمل تلك األنماط إلنشاء الكائنات‪.‬‬
‫ابع‬
‫ستتعلم في هذا الفصل‬
‫َّ‬
‫كيفية إنشاء األصناف والكائنات‪ ،‬وتهيئ ة الخاص يات باس تخدام ت ٍ‬
‫بان (‪ ،)constructor method‬والعمل على أكثر من كائن من نفس الصنف‪.‬‬
‫ٍ‬
‫‪ .1‬األصناف‬
‫األص ناف هي نم اذج عام ة ُتس تخدم إلنش اء كائن ات‪ ،‬وس بق أن عرَّ فناه ا ً‬
‫آنف ا‪ُ .‬ت َ‬
‫نش أ األص ناف‬
‫باس تخدام الكلم ة المفتاحي ة ‪ ،class‬بش كل مش ابه لتعري ف ال دوال ال ذي يك ون باس تخدام الكلم ة‬
‫المفتاحية ‪.def‬‬
‫ً‬
‫دعنا ِّ‬
‫صنفا يسمى ‪ ،Shark‬وننشئ له تابعين مرتبطين به‪ swim ،‬و ‪:be_awesome‬‬
‫نعرف‬
‫‪330‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫‪class Shark:‬‬
‫‪def swim(self):‬‬
‫)"‪print("The shark is swimming.‬‬
‫‪def be_awesome(self):‬‬
‫)"‪print("The shark is being awesome.‬‬
‫ألنهم ا معرفت ان داخ ل الص نف ‪Shark‬؛ أي َّ‬
‫ُتس مَّ ى مث ل ه ذه ال دوال «ت ابع» (‪َّ )method‬‬
‫أنهم ا‬
‫دالتان تابعتان للصنف ‪.Shark‬‬
‫الوس يط األول له َ‬
‫اتين ال دالتين ه و ‪ ،self‬وه و مرج ع إلى الكائن ات ال تي س ُتبنَى من ه ذا‬
‫الص نف‪ .‬لإلش ارة إلى ُنس خ (أو كائن ات) من الص نف‪ ،‬يوض ع ‪ self‬دائمً ا في البداي ة‪ ،‬لكن يمكن أن‬
‫تكون معه وسائط أخرى‪.‬‬
‫ال ي ؤدي تعري ف الص نف ‪ Shark‬إلى إنش اء كائن ات من ه‪ ،‬وإنم ا يع ِّرف فق ط النم ط الع ام لتل ك‬
‫الحقا‪ .‬لذا‪ ،‬إذا ّ‬
‫ً‬
‫نفذت البرنامج أعاله اآلن‪ ،‬فلن يُ عاد أي شيء‪.‬‬
‫الكائنات‪ ،‬والتي يمكننا تعريفها‬
‫‪ .2‬الكائنات‬
‫ٌ‬
‫خة (‪ )instance‬من ص نف‪ ،‬ويمكن أن نأخ ذ الص نف ‪ Shark‬المُ ع رَّ ف أعاله‪،‬‬
‫الك ائن ه و نس‬
‫ً‬
‫نسخة منه‪.‬‬
‫ونستخدمه إلنشاء كائن يع ُّد‬
‫سننشئ كائنًا من الصنف ‪ Shark‬باسم ‪:sammy‬‬
‫)(‪sammy = Shark‬‬
‫ً‬
‫خة من الص نف‪.‬‬
‫لق د أحلن ا على الك ائن ‪ sammy‬ن اتج الب اني )(‪ ،Shark‬وال ذي يعي د نس‬
‫سنستخدم في الشيفرة التالية التابعين الخاصين بالكائن ‪:sammy‬‬
‫‪331‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫)(‪sammy = Shark‬‬
‫)(‪sammy.swim‬‬
‫)(‪sammy.be_awesome‬‬
‫يس تخدم الك ائن ‪ sammy‬الت ابعين )(‪ swim‬و )(‪ ،be_awesome‬وق د اس تدعينَاهما باس تعمال‬
‫الص ياغة النقطي ة (‪ ،).‬وال تي ُتس تخ َدم لإلش ارة إلى خاص يات (‪)properties‬أو تواب ع (‪)method‬‬
‫الكائنات‪ .‬في هذه الحالة‪ ،‬استدعينا تابعً ا‪ ،‬لذلك استعملنا قوسين مثلما نفعل عند استدعاء دالة‪.‬‬
‫الكلمة ‪ self‬هي معامل يُ مرَّ ر إلى توابع الصنف ‪ ،Shark‬في المث ال أعاله‪ِّ ،‬‬
‫يمثل ‪ self‬الك ائن‬
‫ُ‬
‫استدعيت معه‪.‬‬
‫‪ .sammy‬يتيح المعامل ‪ self‬للتوابع الوصول إلى خاصيات الكائن الذي‬
‫الح ظ َّ‬
‫أن الك ائن ‪sammy‬‬
‫أنن ا لم نم ِّرر ش يًئا داخ ل القوس ين عن د اس تدعاء الت ابع أعاله‪ ،‬ذل ك َّ‬
‫ِّ‬
‫يوضح البرنامج التالي لنا األمر‪:‬‬
‫تلقائيا مع العامل النقطي‪.‬‬
‫يُ مرَّ ر‬
‫ً‬
‫‪class Shark:‬‬
‫‪def swim(self):‬‬
‫)"‪print("The shark is swimming.‬‬
‫‪def be_awesome(self):‬‬
‫)"‪print("The shark is being awesome.‬‬
‫‪def main():‬‬
‫)(‪sammy = Shark‬‬
‫)(‪sammy.swim‬‬
‫)(‪sammy.be_awesome‬‬
‫‪if __name__ == "__main__":‬‬
‫)(‪main‬‬
‫‪332‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫ِّ‬
‫لننفذ البرنامج لنرى ما سيحدث‪:‬‬
‫‪python shark.py‬‬
‫ُ‬
‫طبع المخرجات التالية‪:‬‬
‫ست َ‬
‫‪The shark is swimming.‬‬
‫‪The shark is being awesome.‬‬
‫في الش يفرة أعاله‪ ،‬اس تدعى الك ائن ‪ sammy‬الت ابعين )(‪ swim‬و )(‪ be_awesome‬في الدال ة‬
‫الرئيسية )(‪.main‬‬
‫‪ .3‬الباني (‪)Constructor‬‬
‫يٌ ستخدم الباني (‪ )Constructor Method‬لتهيئة البيانات األولية‪ ،‬ويُ َّ‬
‫نفذ لحظة إنشاء الكائن‪.‬‬
‫في تعري ف الص نف‪ ،‬يأخ ذ الب اني االس م __‪ ،__init‬وه و أول ت ابع يُ ع رَّ ف في الص نف‪ ،‬ويب دو‬
‫كما يلي‪:‬‬
‫‪class Shark:‬‬
‫‪def __init__(self):‬‬
‫)"‪print("This is the constructor method.‬‬
‫امج‬
‫ُ‬
‫إذا أض فت الت ابع __‪ __init‬إلى الص نف ‪ Shark‬في البرن امج أعاله‪ ،‬فس َيطبع البرن‬
‫المخرجات التالية‪:‬‬
‫‪This is the constructor method.‬‬
‫‪The shark is swimming.‬‬
‫‪The shark is being awesome.‬‬
‫يُ َّ‬
‫تلقائيا‪ ،‬لذا يستخدمه مطورو بايثون لتهيئة أصنافهم‪.‬‬
‫نفذ الباني‬
‫ً‬
‫‪333‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫س ُن ِّ‬
‫عدل الباني أعاله‪ ،‬ونجعله يستخدم متغ يرًا اس مه ‪ name‬س ّ‬
‫يمثل اس م الك ائن‪ .‬في الش يفرة‬
‫التالية‪ ،‬سيكون المتغير ‪ name‬المعامل المُ مرَّ ر إلى الباني‪ ،‬ونحيل قيمته إلى الخاصية ‪:self.name‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name):‬‬
‫‪self.name = name‬‬
‫بع د ذل ك‪ ،‬يمكنن ا تع ديل السالس ل النص ية في دوالن ا لإلش ارة إلى اس م الص نف‪ ،‬على‬
‫النحو التالي‪:‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name):‬‬
‫‪self.name = name‬‬
‫‪def swim(self):‬‬
‫اإلشارة إلى االسم ‪#‬‬
‫)"‪print(self.name + " is swimming.‬‬
‫‪def be_awesome(self):‬‬
‫اإلشارة إلى االسم ‪#‬‬
‫)"‪print(self.name + " is being awesome.‬‬
‫أخ يرًا‪ ،‬يمكنن ا تع يين اس م الك ائن ‪ sammy‬عن د القيم ة "‪( "Sammy‬أي قيم ة الخاص ية ‪)name‬‬
‫بتمريره إلى )(‪ Shark‬عند إنشائه‪:‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name):‬‬
‫‪self.name = name‬‬
‫‪def swim(self):‬‬
‫)"‪print(self.name + " is swimming.‬‬
‫‪334‬‬
‫|‬
‫▲‬
‫بناء األصناف واستنساخ الكائنات‬
‫البرمجة بلغة بايثون‬
‫‪def be_awesome(self):‬‬
‫)"‪print(self.name + " is being awesome.‬‬
‫‪def main():‬‬
‫تعيين اسم كائن ‪# Shark‬‬
‫)"‪sammy = Shark("Sammy‬‬
‫)(‪sammy.swim‬‬
‫)(‪sammy.be_awesome‬‬
‫‪if __name__ == "__main__":‬‬
‫)(‪main‬‬
‫أن المعام ل ‪ self‬يُ م رَّ ر‬
‫عرّ فن ا الت ابع __‪ ،__init‬وال ذي يقب ل مُ ع املين ‪ self‬و ‪( name‬ت ذكر َّ‬
‫تلقائيا إلى التابع)‪ ،‬ثم عرَّ فنا متغيرًا فيه‪.‬‬
‫ً‬
‫عند تنفيذ البرنامج‪:‬‬
‫‪python shark.py‬‬
‫سنحصل على‪:‬‬
‫‪Sammy is swimming.‬‬
‫‪Sammy is being awesome.‬‬
‫ألن الب اني يُ َّ‬
‫تلقائي ا‪ ،‬فلس ت بحاج ة إلى‬
‫نفذ‬
‫لق د ُط ِب ع االس م ال ذي مرَّ رن اه إلى الك ائن‪ .‬ونظ ًرا َّ‬
‫ً‬
‫اس تدعائه بش كل ص ريح‪ ،‬فيكفي تمري ر الوس ائط بين القوس ين الت اليين الس م الص نف عن د إنش اء‬
‫نسخة جديدة منه‪.‬‬
‫‪335‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫إذا أردت إضافة معامل آخر‪ ،‬مثل ‪ ،age‬فيمكن ذلك عبر تمريره إلى التابع __‪:__init‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫ً‬
‫ِّ‬
‫أيضا باإلضافة إلى اسمه‪:‬‬
‫سنمرر عُ مره‬
‫عند إنشاء الكائن ‪،sammy‬‬
‫)‪sammy = Shark("Sammy", 5‬‬
‫ً‬
‫إذا‪ ،‬تتيح البانيات تهيئة خاصيات الكائن لحظة إنشائه‪.‬‬
‫‪ .4‬العمل مع عدة كائنات‬
‫ت تيح لن ا األص ناف إنش اء العدي د من الكائن ات المتماثل ة ال تي تتب ع نفس النم ط‪ .‬لتفهم ذل ك‬
‫بشكل أفضل‪ ،‬دعنا نضيف كائنًا آخر من الصنف ‪ Shark‬إلى برنامجنا‪:‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name):‬‬
‫‪self.name = name‬‬
‫‪def swim(self):‬‬
‫)"‪print(self.name + " is swimming.‬‬
‫‪def be_awesome(self):‬‬
‫)"‪print(self.name + " is being awesome.‬‬
‫‪def main():‬‬
‫)"‪sammy = Shark("Sammy‬‬
‫)(‪sammy.be_awesome‬‬
‫)"‪stevie = Shark("Stevie‬‬
‫)(‪stevie.swim‬‬
‫‪336‬‬
‫|‬
‫▲‬
‫بناء األصناف واستنساخ الكائنات‬
‫البرمجة بلغة بايثون‬
‫‪if __name__ == "__main__":‬‬
‫)(‪main‬‬
‫ثاني ا من الص نف ‪ Shark‬يس مى ‪ stevie‬ومرَّ رن ا إلي ه االس م "‪."Stevie‬‬
‫لق د أنش أنا كائ ًن ا‬
‫ً‬
‫اس تدعينا في ه ذا المث ال الت ابع )(‪ be_awesome‬م ع الك ائن ‪ sammy‬والت ابع )(‪ swim‬م ع‬
‫الكائن ‪ .stevie‬سننفذ البرنامج عبر األمر التالي‪:‬‬
‫‪python shark.py‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪Sammy is being awesome.‬‬
‫‪Stevie is swimming.‬‬
‫يب دو ظ اه ًرا في المخرج ات أنن ا نس تخدم ك ائنين مختلفين‪ ،‬الك ائن ‪ sammy‬والك ائن ‪،stevie‬‬
‫وكالهما من الصنف ‪.Shark‬‬
‫تتيح لنا األصناف إنشاء ع دة كائن ات تتب ع كله ا نفس النم ط دون الحاج ة إلى بن اء ك ل واح د‬
‫منها من البداية‪.‬‬
‫‪ .5‬فهم متغيرات األصناف والنسخ‬
‫تسمح البرمجة الكائنية باس تخدام متغ يرات على مس توى الص نف‪ ،‬أو على مس توى النس خة‬
‫(‪ .)instance‬المتغيرات هي رموز (‪ )symbols‬تدل على قيمة تستخدمها في برنامجك‪.‬‬
‫يشار إلى المتغيرات على مستوى الصنف باس م «متغ يرات الص نف» (‪ ،)class variables‬في‬
‫حين تس مى المتغ يرات الموج ودة على مس توى النس خة باس م «متغ يرات النس خة»‬
‫(‪.)instance variables‬‬
‫‪337‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫إذا ت وقعت أن يك ون المتغيِّ ر متس ًقا في جمي ع نس خ الص نف‪ ،‬أو عن دما ت ود تهيئ ة المتغ ير‪،‬‬
‫أن المتغ ير س يختلف من‬
‫فاألفض ل أن ُتع ِّرف ذل ك المتغ ير على مس توى الص نف‪ .‬أمَّ ا إن كنت تعلم َّ‬
‫نسخة إلى أخرى‪ ،‬فاألفضل أن ُت ِّ‬
‫عر َفه على مستوى النس خة‪ .‬يس عى أح د مب ادئ تط وير البرمجي ات‬
‫ِّ‬
‫تكرر نفسك) إلى الحد من‬
‫هو مبدأ ‪( DRY‬اختصا ًرا للعبارة ‪ ،don’t repeat yourself‬والذي يعني ال‬
‫التكرار في الشيفرة‪ .‬أي تلتزم البرمجة الكائنية بمبدأ ‪ DRY‬على تقليل التكرار في الشيفرة‪.‬‬
‫ا‪ .‬متغيرات الصنف‬
‫ٌتع رَّ ف متغ يرات الص نف داخ ل الص نف وخ ارج ك ل توابع ه وع ً‬
‫ادة م ا توض ع مباش رة أس فل‬
‫ترويسة الص نف‪ ،‬وقب ل الب اني (‪ )constructor‬والتواب ع األخ رى‪ .‬ولمَّ ا ك انت مملوك ة للص نف نفس ه‪،‬‬
‫ُ‬
‫فستشارَ ك مع جميع ُن َسخ ذلك الصنف‪ .‬وبالتالي‪ ،‬س يكون له ا نفس القيم ة بغض النظ ر عن النس خة‪،‬‬
‫معين‪.‬‬
‫إال إن كنت ستستخدم متغير الصنف لتهيئة متغير‬
‫َّ‬
‫متغير الصنف يبدو كما يلي‪:‬‬
‫‪class Shark:‬‬
‫"‪animal_type = "fish‬‬
‫في الشيفرة أعاله أحلنا القيمة "‪ "fish‬إلى المتغير ‪.animal_type‬‬
‫يمكنن ا إنش اء نس خة من الص نف ‪( Shark‬س نطلق عليه ا ‪ ،)new_shark‬ونطب ع المتغ ير‬
‫باستخدام الصياغة النقطية (‪:)dot notation‬‬
‫‪class Shark:‬‬
‫"‪animal_type = "fish‬‬
‫)(‪new_shark = Shark‬‬
‫)‪print(new_shark.animal_type‬‬
‫‪338‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫لننفذ البرنامج‪:‬‬
‫‪python shark.py‬‬
‫سيعيد البرنامج قيمة المتغير‪:‬‬
‫‪fish‬‬
‫دعنا نضيف مزي ًدا من متغيرات الصنف‪ ،‬ونطبعها‪:‬‬
‫‪class Shark:‬‬
‫"‪animal_type = "fish‬‬
‫"‪location = "ocean‬‬
‫‪followers = 5‬‬
‫)(‪new_shark = Shark‬‬
‫)‪print(new_shark.animal_type‬‬
‫)‪print(new_shark.location‬‬
‫)‪print(new_shark.followers‬‬
‫يمكن أن تتألف متغيرات الص نف من أي ن وع من البيان ات المتاح ة في ب ايثون تمامً ا مث ل أي‬
‫متغير آخر‪ .‬استخدمنا في هذا البرنامج السالسل النصية واألعداد الص حيحة‪ .‬لننف ذ البرن امج م رة‬
‫أخرى باستخدام األمر ‪ python shark.py‬ونرى المخرجات‪:‬‬
‫‪fish‬‬
‫‪ocean‬‬
‫‪5‬‬
‫يمكن للنس خة ‪ new_shark‬الوص ول إلى جمي ع متغ يرات الص نف وطباعته ا عن د تنفي ذ‬
‫ً‬
‫البرنامج‪ ،‬إذ ُت َ‬
‫مباشرة (وليس عند إنشاء نسخة منه) وتحتل موضعً ا له ا في‬
‫نشأ عند إنشاء الصنف‬
‫الذاكرة ويمكن ألي كائن مُ ش َتق (نسخة) من الصنف نفسه أن يصل إليها ويقرأ قيمتها‪.‬‬
‫‪339‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫ب‪ .‬متغيرات النسخة‬
‫تختل ف متغ يرات النس خة عن متغ يرات الص نف ب أن النس خة المش تقة من الص نف هي من‬
‫وسي َ‬
‫نشأ متغيِّ رٌ مستقل في ال ذاكرة عن د‬
‫تملكها وليس الصنف نفسه أي تكون على مستوى النسخة‬
‫ُ‬
‫أن متغيرات النسخة ستختلف من كائن إلى آخر‪.‬‬
‫إنشاء كل نسخة‪ .‬هذا يعني َّ‬
‫ُتعرَّ ف متغيرات النسخة ضمن التوابع على خالف متغيرات الصنف‪ .‬في مثال الص نف ‪Shark‬‬
‫أدناه‪ ،‬عرفنا متغيري النسخة ‪ name‬و ‪:age‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫يتعين علين ا تعري ف ه ذه المتغ يرات‪ ،‬ع بر تمريره ا‬
‫عن دما ننش ئ كائ ًن ا من الص نف ‪ ،Shark‬س‬
‫َّ‬
‫معامالت ضمن الباني (‪ ،)constructor‬أو أي تابع آخر‪:‬‬
‫ٍ‬
‫‪class Shark:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫)‪new_shark = Shark("Sammy", 5‬‬
‫كما هو الحال مع متغيرات األصناف‪ ،‬يمكننا بالمثل طباعة متغيرات النسخة‪:‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫‪340‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫)‪new_shark = Shark("Sammy", 5‬‬
‫)‪print(new_shark.name‬‬
‫)‪print(new_shark.age‬‬
‫عند تنفيذ البرنامج أعاله باستخدام ‪ ،python shark.py‬سنحصل على المخرجات التالية‪:‬‬
‫‪Sammy‬‬
‫‪5‬‬
‫هيأناه ا ألج ل‬
‫تت ألف المخرج ات ال تي حص لنا عليه ا من قيم المتغ يرات ال تي َّ‬
‫الكائن ‪.new_shark‬‬
‫لننشئ كائنًا آخر من الصنف ‪ Shark‬يسمى ‪:stevie‬‬
‫‪class Shark:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫)‪new_shark = Shark("Sammy", 5‬‬
‫)‪print(new_shark.name‬‬
‫)‪print(new_shark.age‬‬
‫)‪stevie = Shark("Stevie", 8‬‬
‫)‪print(stevie.name‬‬
‫)‪print(stevie.age‬‬
‫ِّ‬
‫يمرر الكائن ‪ stevie‬المعامالت إلى الباني لتعيين قيم متغيرات النسخة الخاصة به‪.‬‬
‫تسمح متغيرات النسخة‪ ،‬المملوكة لكائنات الصنف‪ ،‬لكل كائن أو نسخة أن تكون لها متغ يرات‬
‫ً‬
‫بعضا‪.‬‬
‫خاصة بها ذات قيم مختلفة عن بعضها‬
‫‪341‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫معا‬
‫‪ .6‬العمل مع متغيرات الصنف والنسخة ً‬
‫غالب ا م ا ُتس تخدم متغ يرات الص نف ومتغ يرات النس خة في نفس الش يفرة‪ ،‬ويوض ح المث ال‬
‫ً‬
‫الت الي يس تخدم الص نف ‪ Shark‬ال ذي أنش أناه س ً‬
‫ابقا ه ذا األم ر‪ .‬تش رح التعليق ات في البرن امج ك ل‬
‫خطوة من خطوات العملية‪:‬‬
‫‪class Shark:‬‬
‫متغيرات الصنف ‪#‬‬
‫"‪animal_type = "fish‬‬
‫"‪location = "ocean‬‬
‫باني مع متغيري النسخة ‪ age‬و ‪# name‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name = name‬‬
‫‪self.age = age‬‬
‫تابع مع متغير النسخة ‪# followers‬‬
‫‪def set_followers(self, followers):‬‬
‫)"‪print("This user has " + str(followers) + " followers‬‬
‫‪def main():‬‬
‫الكائن األول‪ ،‬إعداد متغيرات النسخة في الباني ‪#‬‬
‫)‪sammy = Shark("Sammy", 5‬‬
‫طباعة متغير النسخة ‪# name‬‬
‫)‪print(sammy.name‬‬
‫طباعة متغير الصنف ‪# location‬‬
‫)‪print(sammy.location‬‬
‫الكائن الثاني ‪#‬‬
‫‪342‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫بناء األصناف واستنساخ الكائنات‬
‫)‪stevie = Shark("Stevie", 8‬‬
‫طباعة متغير النسخة ‪# name‬‬
‫)‪print(stevie.name‬‬
‫استخدام التابع ‪# set_followers‬‬
‫لتمرير متغير النسخة ‪# followers‬‬
‫)‪stevie.set_followers(77‬‬
‫طباعة متغير الصنف ‪# animal_type‬‬
‫)‪print(stevie.animal_type‬‬
‫‪if __name__ == "__main__":‬‬
‫)(‪main‬‬
‫عند تنفيذ البرنامج باستخدام ‪ ،python shark.py‬سنحصل على المخرجات التالية‪:‬‬
‫‪Sammy‬‬
‫‪ocean‬‬
‫‪Stevie‬‬
‫‪This user has 77 followers‬‬
‫‪fish‬‬
‫‪ .7‬خالصة الفصل‬
‫تطرَّ قن ا في ه ذا الفص ل إلى عِ َّدة مف اهيم‪ ،‬مث ل إنش اء األص ناف‪ ،‬وإنش اء الكائن ات‪ ،‬وتهيئ ة‬
‫الخاصيات باستخدام البانيات‪ ،‬والعمل مع أكثر من كائن من نفس الصنف‪.‬‬
‫ُتع ُّد البرمجة الكائنية أحد المفاهيم الضرورية التي ينبغي أن يتعلمها كل مبرمجي بايثون‪ ،‬إذ‬
‫تس اعد على كتاب ة ش يفرات قابل ة إلع ادة االس تخدام‪ ،‬والكائن ات ال تي ُت َ‬
‫نش أ في برن امج م ا يمكن‬
‫أن ال برامج الكائني ة ع ادة م ا تك ون أوض ح وأك ثر مقروئي ة‪،‬‬
‫اس تخدامها في ب رامج أخ رى‪ .‬كم ا َّ‬
‫‪343‬‬
‫|‬
‫▲‬
‫بناء األصناف واستنساخ الكائنات‬
‫البرمجة بلغة بايثون‬
‫خصوص ا في ال برامج المعق دة ال تي تتطلب تخطيط ا دقيق ا‪ ،‬وه ذا ب دوره يس هل ص يانة‬
‫ً‬
‫البرامج مستقبال‪.‬‬
‫في البرمج ة الكائني ة‪ ،‬يش ار إلى المتغ يرات المُ عرَّ ف ة على مس توى الص نف بمتغ يرات الص نف‪،‬‬
‫في حين تسمى المتغ يرات المُ عرّ ف ة على مس توى الك ائن بمتغ يرات النس خة‪ .‬ي تيح لن ا ه ذا التمي يز‬
‫اس تخدام متغ يرات ذات قيم واح دة بينه ا ع بر متغ يرات الص نف‪ ،‬أو اس تخدام متغ يرات مختلف ة‬
‫لك ل ك ائن على ح دة ع بر متغ يرات النس خة‪ .‬كم ا يض من اس تخدام المتغ يرات الخاص ة بالص نف أو‬
‫النسخة أن تكون الشيفرة متوافقة مع مبدأ ‪.DRY‬‬
‫‪344‬‬
‫|‬
‫▲‬
‫‪19‬‬
‫مفهوم الوراثة‬
‫في البرمجة‬
‫‪345‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫ُت ِّسهل البرمجة الكائنية كتاب ة ش يفرات قابل ة إلع ادة االس تخدام وتجنب التك رار في مش اريع‬
‫ِّ‬
‫تحقق به ا البرمج ة الكائني ة ه ذا اله دف هي مفه وم الوراث ة‬
‫التط وير‪ .‬إح دى اآللي ات ال تي‬
‫نف ف رعي ( ‪ )subclass‬اس تخدام الش يفرة الخاص ة بص نف‬
‫(‪ ،)inheritance‬ال تي بفض لها يمكن لص ٍ‬
‫ً‬
‫ً‬
‫مسبقا‪.‬‬
‫أيضا) موجود‬
‫أساسي (‪ ،base class‬ويطلق عليه «صنف أب»‬
‫سيس تعرض ه ذا الفص ل بعض الج وانب الرئيس ية لمفه وم الوراث ة في ب ايثون‪ ،‬بم ا في ذل ك‬
‫وكيفية‬
‫كيفية إنشاء األصناف األساس ية (‪ )parent classes‬واألص ناف الفرعي ة (‪،)child classes‬‬
‫َّ‬
‫َّ‬
‫وكيفية‬
‫وكيفية اس تخدام الت ابع )(‪،super‬‬
‫إع ادة تعري ف (‪ )override‬التواب ع والخاص يات‪،‬‬
‫َّ‬
‫َّ‬
‫ِّ‬
‫االستفادة من الوراثة المُ‬
‫تعددة (‪.)multiple inheritance‬‬
‫‪ .1‬ما هي الوراثة؟‬
‫تق وم الوراثة على اس تخدام ش يفرة ص نف معين في ص نف آخ ر أي ي رث ص نف ي راد إنش اؤه‬
‫ش يفرة ص نف آخ ر‪ .‬يمكن تمثي ل مفه وم الوراث ة في البرمج ة بالوراث ة في علم األحي اء تمامً ا‪،‬‬
‫فاألبن اء يرث ون خاص يات معين ة من آب ائهم‪ .‬ويمكن لطف ل أن ي رث ط ول وال ده أو ل ون عيني ه‬
‫باإلض افة إلى خاص يات أخ رى جدي دة خاص ة في ه‪ .‬كم ا يتش ارك األطف ال نفس اس م العائل ة‬
‫الخاصة بآبائهم‪.‬‬
‫ً‬
‫أيضا األصناف األبن اء [‪ )]child classes‬التواب ع‬
‫ترث األصناف الفرعية (‪ُ ،subclasses‬تسمى‬
‫والمتغ‬
‫يرات من األص‬
‫ناف األساس‬
‫ية (‪classes‬‬
‫‪ ،base‬تس‬
‫ً‬
‫أيض‬
‫مى‬
‫ا األص‬
‫ناف‬
‫اآلباء [‪.)]parent classes‬‬
‫مثاًل ‪ ،‬قد يكون لدينا ص نف أساس ي يس مى ‪ Parent‬يح وي متغ يرات األص ناف ‪last_name‬‬
‫و ‪ height‬و ‪ ،eye_color‬والتي سيرثها الصنف االبن ‪.Child‬‬
‫‪346‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫لمَّ ا ك ان الص نف الف رعي ‪ Child‬ي رث الص نف األساس ي ‪ ،Parent‬فبإمكان ه إع ادة اس تخدام‬
‫شيفرة ‪ ،Parent‬مما يسمح للمبرمج بكتابة شيفرة أوجز‪ ،‬وتقليل التكرار‪.‬‬
‫‪ .2‬األصناف األساسية‬
‫أساس ا يمكن أن تس تند إلي ه األص ناف الفرعي ة المُ ِّ‬
‫تفرع ة منه ا‪ ،‬إذ‬
‫تش كل األص ناف األساس ية‬
‫ً‬
‫تسمح األصناف األساسية بإنشاء أصناف فرعية عبر الوراثة دون الحاجة إلى كتابة نفس الش يفرة‬
‫في ك ل م رة‪ .‬يمكن تحوي ل أي ص نف إلى ص نف أساس ي‪ ،‬إذ يمكن اس تخدامه لوح ده‪ ،‬أو جعل ه‬
‫ً‬
‫نموذجا)‪.‬‬
‫قالبا (‬
‫ً‬
‫ً‬
‫أساسيا باسم ‪ ،Bank_account‬وصنفين فرعيين مُ شتقين منه باس م‬
‫صنفا‬
‫أن لدينا‬
‫لنفترض َّ‬
‫ً‬
‫‪ Personal_account‬و ‪ .Business_account‬س تكون العدي د من التواب ع مش تركة بين‬
‫الحس ابات الشخص ية ( ‪ )Personal_account‬والحس ابات التجاري ة (‪ ،)Business_account‬مث ل‬
‫تواب ع س حب وإي داع األم وال‪ ،‬ل ذا يمكن أن تنتمي تل ك التواب ع إلى الص نف األساسي‬
‫‪ .Bank_account‬س يكون للص نف ‪ Business_account‬تواب ع خاص ة ب ه‪ ،‬مث ل ت ابع مخص ص‬
‫لعملي‬
‫ة جم‬
‫عس‬
‫جالت ونم‬
‫اذج األعم‬
‫ال‪ ،‬باإلض‬
‫ير‬
‫افة إلى متغ‬
‫‪ employee_identification_number‬موروث من الصنف األب‪.‬‬
‫وبالمثل‪ ،‬قد يحتوي الصنف ‪ Animal‬على التابعين )(‪ eating‬و )(‪ ،sleeping‬وقد يتض من‬
‫الصنف الفرعي ‪ Snake‬تابعين إضافيين باسم )(‪ hissing‬و )(‪ slithering‬خاصين به‪.‬‬
‫ً‬
‫دعنا ننش ئ ص ً‬
‫أساس ا ألص ناف فرعي ة تمث ل أن واع‬
‫الحق ا‬
‫نفا أساس ًيا باس م ‪ Fish‬الس تخدامه‬
‫ً‬
‫األسماك‪ .‬سيكون لكل واحدة من تلك األسماك أسماء أولى وأخيرة‪ ،‬باإلضافة إلى خص ائص مم يزة‬
‫خاصة بها‪.‬‬
‫‪347‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫سننشئ ً‬
‫ملف ا جدي ًدا يس مى ‪ fish.py‬ونب دأ بالب اني‪ ،‬وال ذي س ِّ‬
‫نعرف داخل ه متغ يري الص نف‬
‫‪ first_name‬و ‪ last_name‬لكل كائنات الصنف ‪ ،Fish‬أو أصنافه الفرعية‪.‬‬
‫‪class Fish:‬‬
‫‪def __init__(self, first_name, last_name="Fish"):‬‬
‫‪self.first_name = first_name‬‬
‫‪self.last_name = last_name‬‬
‫أن معظم‬
‫القيم ة االفتراض ية للمتغ ير ‪ last_name‬هي السلس لة النص ية "‪ ،"Fish‬ألنن ا نعلم َّ‬
‫األسماك سيكون هذا هو اسمها األخير‪.‬‬
‫ل ُن ِ‬
‫ضف بعض التوابع األخرى‪:‬‬
‫‪class Fish:‬‬
‫‪def __init__(self, first_name, last_name="Fish"):‬‬
‫‪self.first_name = first_name‬‬
‫‪self.last_name = last_name‬‬
‫‪def swim(self):‬‬
‫)"‪print("The fish is swimming.‬‬
‫‪def swim_backwards(self):‬‬
‫)"‪print("The fish can swim backwards.‬‬
‫لق د أض فنا الت ابعين )(‪ swim‬و )(‪ swim_backwards‬إلى الص نف ‪ Fish‬ح تى يتس نى لك ل‬
‫األصناف الفرعية استخدام هذه التوابع‪.‬‬
‫عظميا) وليس‬
‫أن لها هيكال‬
‫أن معظم األسماك التي ننوي إنشاءها ستكون عظمية (أي َّ‬
‫ما دام َّ‬
‫ً‬
‫روفيا)‪ ،‬فيمكنن ا إض افة بعض الخاص يات اإلض افية إلى‬
‫غض روفية (أي أن له ا هيكاًل غض‬
‫ً‬
‫التابع )(__‪:__init‬‬
‫‪348‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫‪class Fish:‬‬
‫‪def __init__(self, first_name, last_name="Fish",‬‬
‫‪skeleton="bone", eyelids=False):‬‬
‫‪self.first_name = first_name‬‬
‫‪self.last_name = last_name‬‬
‫‪self.skeleton = skeleton‬‬
‫‪self.eyelids = eyelids‬‬
‫‪def swim(self):‬‬
‫)"‪print("The fish is swimming.‬‬
‫‪def swim_backwards(self):‬‬
‫)"‪print("The fish can swim backwards.‬‬
‫ال يختل ف بن اء األص ناف األساس ية عن بن اء أي ص نف آخ ر‪ ،‬إال َّ‬
‫أنن ا نص ممها لتس تفيد منه ا‬
‫ً‬
‫الحقا‪.‬‬
‫األصناف الفرعية المُ عرّ فة‬
‫‪ .3‬األصناف الفرعية‬
‫أن األص ناف‬
‫األص ناف الفرعي ة هي أص ناف ت رث ك ل ش يء من الص نف األساس ي‪ .‬ه ذا يع ني َّ‬
‫الفرعية قادرة على االستفادة من توابع ومتغيرات الصنف األساسي‪.‬‬
‫على س بيل المث ال‪ ،‬س يتمكن الص نف الف رعي ‪ Goldfish‬المش تق من الص نف ‪ Fish‬من‬
‫استخدام التابع )(‪ swim‬المُ عرّ ف في ‪ Fish‬دون الحاجة إلى التصريح عنه‪.‬‬
‫أنها أقسامٌ من الصنف األساسي‪ .‬فإذا كان لدينا ص ً‬
‫يمكننا النظر إلى األصناف الفرعية على َّ‬
‫نفا‬
‫معين)‪ ،‬وص ً‬
‫نفا أساس ًّيا يس مى ‪( Parallelogram‬مت وازي األض الع)‪،‬‬
‫فرعيا يس مى ‪َّ ( Rhombus‬‬
‫ًّ‬
‫أن المعين (‪ )Rhombus‬هو متوازي أضالع (‪.)Parallelogram‬‬
‫يمكننا القول َّ‬
‫‪349‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫ً‬
‫مختلفا قلياًل عن األصناف غير الفرعية‪ ،‬إذ يجب عليك‬
‫يبدو السطر األول من الصنف الفرعي‬
‫تمرير الصنف األساسي إلى الصنف الفرعي كمعامل‪:‬‬
‫‪class Trout(Fish):‬‬
‫ُ‬
‫الكلمة ‪ Fish‬المُ درجة بين قوسين‪.‬‬
‫الصنف ‪ Trout‬هو صنف فرعي من ‪ .Fish‬يدلنا على هذا‬
‫يمكننا إضافة توابع جديدة إلى األصناف الفرعي ة‪ ،‬أو إع ادة تعري ف التواب ع الخاص ة بالص نف‬
‫األساس ي‪ ،‬أو يمكنن ا ببس اطة قب ول التواب ع األساس ية االفتراض ية باس تخدام الكلمة‬
‫المفتاحية ‪ ،pass‬وهو ما سنفعله في المثال التالي‪:‬‬
‫‪...‬‬
‫‪class Trout(Fish):‬‬
‫‪pass‬‬
‫يمكننا اآلن إنشاء كائن من الصنف ‪ Trout‬دون الحاجة إلى تعريف أي توابع إضافية‪.‬‬
‫‪...‬‬
‫‪class Trout(Fish):‬‬
‫‪pass‬‬
‫)"‪terry = Trout("Terry‬‬
‫)‪print(terry.first_name + " " + terry.last_name‬‬
‫)‪print(terry.skeleton‬‬
‫)‪print(terry.eyelids‬‬
‫)(‪terry.swim‬‬
‫)(‪terry.swim_backwards‬‬
‫لق د أنش أنا كائ ًن ا باس م ‪ terry‬من الص نف ‪ ،Trout‬وال ذي سيس تخدم جمي ع تواب ع الص نف‬
‫‪ Fish‬وإن لم ِّ‬
‫نعرفه ا في الص نف الف رعي ‪ .Trout‬يكفي أن نم ِّرر القيم ة "‪ "Terry‬إلى المتغ ير‬
‫ً‬
‫سلفا‪.‬‬
‫‪ ،first_name‬أمَّ ا المتغيرات األخرى فقد جرى تهيئتها‬
‫‪350‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
:‫ سنحصل على المخرجات التالية‬،‫عند تنفيذ البرنامج‬
Terry Fish
bone
False
The fish is swimming.
The fish can swim backwards.
ً ‫لننش ئ اآلن ص‬
.Clownfish ‫ سنس مي ه ذا الص نف‬.‫فرعي ا آخ ر يع رّ ف تابعً ا خاص ا ب ه‬
‫نفا‬
ً
:‫سيسمح التابع الخاص به بالتعايش مع شقائق النعمان البحري‬
...
class Clownfish(Fish):
def live_with_anemone(self):
print("The clownfish is coexisting with sea anemone.")
:Clownfish ‫دعنا ننشئ اآلن كائنًا آخر من الصنف‬
...
casey = Clownfish("Casey")
print(casey.first_name + " " + casey.last_name)
casey.swim()
casey.live_with_anemone()
:‫ سنحصل على المخرجات التالية‬،‫عند تنفيذ البرنامج‬
Casey Fish
The fish is swimming.
The clownfish is coexisting with sea anemone.
‫ ق ادر على اس تخدام‬Clownfish ‫ المستنس خ من الص نف‬casey ‫أن الك ائن‬
َّ ‫ُتظه ر المخرج ات‬
‫ابع‬
▲
‫افة إلى الت‬
|
351
‫ إض‬،Fish ‫نف‬
‫ين بالص‬
‫ الخاص‬swim() ‫__ و‬init__() ‫ابعين‬
‫الت‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫)(‪ live_with_anemone‬الخاص بالصنف الفرعي‪.‬‬
‫إذا حاولنا استخدام التابع )(‪ live_with_anemone‬في الكائن ‪ ،Trout‬فسوف يُ طلق خطأ‪:‬‬
‫)(‪terry.live_with_anemone‬‬
‫‪AttributeError: 'Trout' object has no attribute‬‬
‫'‪'live_with_anemone‬‬
‫أن الت ابع )(‪ live_with_anemone‬ينتمي إلى الص نف الف رعي ‪ Clownfish‬فق ط‪،‬‬
‫ذل ك َّ‬
‫وليس إلى الصنف األساسي ‪.Fish‬‬
‫ت رث األص ناف الفرعي ة تواب ع الص نف األساس ي ال ذي اش ُت َّقت من ه‪ ،‬ل ذا يمكن لك ل األص ناف‬
‫الفرعية استخدام تلك التوابع‪.‬‬
‫‪ .4‬إعادة تعريف توابع الصنف األساسي‬
‫عرَّ فنا في المثال السابق الصنف الفرعي ‪ Trout‬الذي اس تخدم الكلم ة المفتاحي ة ‪ pass‬ل يرث‬
‫جمي ع س لوكيات الص نف األساس ي ‪ ،Fish‬وعرّ فن ا ك ذلك ص ً‬
‫نفا آخ ر ‪ Clownfish‬ي رث جمي ع‬
‫ً‬
‫خاص ا ب ه‪ .‬ق د ن رغب في بعض األحي ان في‬
‫ً‬
‫أيض ا تابعً ا‬
‫س لوكيات الص نف األساس ي‪ ،‬ويُ نش ئ‬
‫استخدام بعض سلوكيات الصنف األساسي‪ ،‬ولكن ليس كلها‪ .‬يُ َ‬
‫طلق على عملية تغيير توابع الصنف‬
‫األساسي «إعادة التعريف» (‪.)Overriding‬‬
‫عند إنشاء األصناف األساسية أو الفرعي ة‪ ،‬فال ب د أن تك ون ل ك رؤي ة عام ة لتص ميم البرن امج‬
‫حتى ال تعيد تعريف التوابع إال عند الضرورة‪.‬‬
‫فرعي ا ‪ Shark‬مش ً‬
‫سننش ئ ص ً‬
‫تقا من الص نف األساس ي ‪ ،Fish‬ال ذي س يمثل األس ماك‬
‫نفا‬
‫ً‬
‫المخصص في األصل‬
‫َّ‬
‫العظمية بشكل أساسي‪ ،‬لذا يتعين علينا إجراء تعديالت على الصنف ‪Shark‬‬
‫لألس ماك الغض روفية‪ .‬من منظ ور تص ميم ال برامج‪ ،‬إذا ك انت ل دينا أك ثر من س مكة غ ير عظمي ة‬
‫‪352‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫ً‬
‫خاصا بكل نوع من هذين النوعين من األسماك‪.‬‬
‫ً‬
‫صنفا‬
‫فيستحب أن ننشئ‬
‫واحدة‪ُ ،‬‬
‫تمتلك أسماك الق رش‪ ،‬على عكس األس ماك العظمي ة‪ ،‬هياك ل مص نوعة من الغض اريف ب داًل من‬
‫جفونا‪ ،‬وال تستطيع الس باحة إلى ال وراء‪ ،‬كم ا َّ‬
‫ً‬
‫أنه ا ق ادرة على المن اورة للخل ف‬
‫أن لديها‬
‫العظام‪ .‬كما َّ‬
‫عن طريق الغوص‪.‬‬
‫على ض‬
‫وء ه‬
‫ذه المعلوم‬
‫ات‪ ،‬س‬
‫نعيد تعري‬
‫ف الب‬
‫ابع‬
‫اني )(__‪ __init‬والت‬
‫ألن أس ماك الق رش يمكنه ا الس باحة‪.‬‬
‫)(‪ .swim_backwards‬ال نحت اج إلى تع ديل الت ابع )(‪َّ swim‬‬
‫دعنا نلقي نظرة على هذا الصنف الفرعي‪:‬‬
‫‪...‬‬
‫‪class Shark(Fish):‬‬
‫‪def __init__(self, first_name, last_name="Shark",‬‬
‫‪skeleton="cartilage", eyelids=True):‬‬
‫‪self.first_name = first_name‬‬
‫‪self.last_name = last_name‬‬
‫‪self.skeleton = skeleton‬‬
‫‪self.eyelids = eyelids‬‬
‫‪def swim_backwards(self):‬‬
‫‪print("The shark cannot swim backwards, but can sink‬‬
‫)"‪backwards.‬‬
‫لق د أع دنا تعري ف المع امالت ال تي تمت تهيئته ا في الت ابع )(__‪ ،__init‬فأخ ذ المتغ ير‬
‫ُأ‬
‫‪ last_name‬القيم ة "‪ ،"Shark‬كم ا س نِد إلى المتغ ير ‪ skeleton‬القيم ة "‪ ،"cartilage‬فيما‬
‫ُأ‬
‫س ِن َدت القيم ة المنطقي ة ‪ True‬إلى المتغ ير ‪ .eyelids‬يمكن لجمي ع ُنس خ الص نف إع ادة تعري ف‬
‫هذه المعامالت‪.‬‬
‫‪353‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫يطب ع الت ابع )(‪ swim_backwards‬سلس لة نص ية مختلف ة عن تل ك ال تي يطبعه ا في الص نف‬
‫ألن أسماك القرش غير قادرة على السباحة للخلف كما تفعل األسماك العظمية‪.‬‬
‫األساسي ‪َّ ،Fish‬‬
‫يمكنن ا اآلن إنش اء نس خة من الص نف الف رعي ‪ ،Shark‬وال ذي سيس تخدم الت ابع )(‪swim‬‬
‫الخاص بالصنف األساسي ‪:Fish‬‬
‫‪...‬‬
‫)"‪sammy = Shark("Sammy‬‬
‫)‪print(sammy.first_name + " " + sammy.last_name‬‬
‫)(‪sammy.swim‬‬
‫)(‪sammy.swim_backwards‬‬
‫)‪print(sammy.eyelids‬‬
‫)‪print(sammy.skeleton‬‬
‫عند تنفيذ هذه الشيفرة‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫‪Sammy Shark‬‬
‫‪The fish is swimming.‬‬
‫‪The shark cannot swim backwards, but can sink backwards.‬‬
‫‪True‬‬
‫‪cartilage‬‬
‫لق د أع اد الص نف الف رعي ‪ Shark‬تعري ف الت ابعين )(__‪ __init‬و )(‪swim_backwards‬‬
‫الخاص‬
‫ين بالص‬
‫نف األساس‬
‫ي ‪ ،Fish‬وورث في نفس ال‬
‫وقت الت‬
‫ابع )(‪ swim‬الخ‬
‫اص‬
‫بالصنف األساسي‪.‬‬
‫‪ .5‬الدالة )(‪ super‬وفائدتها في الوراثة‬
‫ُأ‬
‫يمكنك باستخدام الدالة )(‪ super‬الوصول إلى التوابع الموروثة التي عي َدت كتابتها‪ .‬عن دما‬
‫نستخدم الدالة )(‪َّ ،super‬‬
‫فإننا نستدعي التابع الخاص بالص نف األساس ي الس تخدامه في الص نف‬
‫‪354‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫الفرعي‪ .‬على سبيل المثال‪ ،‬قد نرغب في إعادة تعريف جانب من التابع األساسي وإض افة وظ ائف‬
‫معينة إليه‪ ،‬ثم بعد ذلك نستدعي التابع األساسي إلنهاء بقية العمل‪.‬‬
‫في برن امج خ اص بتق ييم الطالب مثاًل ‪ ،‬ق د ن رغب في تعري ف ص نف ف رعي‬
‫‪ Weighted_grade‬ي‬
‫رث الص‬
‫نف األساس‬
‫ي ‪ ،Grade‬ونعي‬
‫د في‬
‫ه تعري‬
‫ابع‬
‫ف الت‬
‫)(‪ calculate_grade‬الخاص بالصنف األساسي من أجل تضمين شيفرة خاصة بحساب التق دير‬
‫َّ‬
‫المرجح (‪ ، )weighted grade‬مع الحفاظ على بقية وظائف الصنف األساسي‪ .‬عبر استدعاء التابع‬
‫)(‪ ،super‬سنكون قادرين على تحقيق ذلك‪.‬‬
‫عادة ما يُ ستخدم التابع )(‪ super‬ضمن التابع )(__‪َّ ،__init‬‬
‫ألنه المكان ال ذي س تحتاج في ه‬
‫على األرجح إلى إض افة بعض الوظ ائف الخاص ة إلى الص نف الف رعي قب ل إكم ال التهيئ ة من‬
‫الصنف األساسي‪.‬‬
‫ألن س مك الس لمون‬
‫لنض رب مثاًل لتوض يح ذل ك‪ ،‬دعن ا نع ِّدل الص نف الف رعي ‪ .Trout‬نظ ًرا َّ‬
‫َّ‬
‫المرقط من أس ماك المي اه العذب ة‪ ،‬فلنض ف متغ يرًا اس مه ‪ water‬إلى الت ابع )(__‪ ،__init‬ول ُنعط ه‬
‫القيمة "‪ ،"freshwater‬ولكن مع الحفاظ على باقي متغيرات ومعامالت الصنف األساسي‪:‬‬
‫‪...‬‬
‫‪class Trout(Fish):‬‬
‫‪def __init__(self, water = "freshwater"):‬‬
‫‪self.water = water‬‬
‫)‪super().__init__(self‬‬
‫‪...‬‬
‫لق د أع دنا تعري ف الت ابع )(__‪ __init‬في الص نف الف رعي ‪ ،Trout‬وغيرن ا س لوكه موازن ًة‬
‫بالت ابع )(__‪ __init‬المُ ع رَّ ف س ً‬
‫لفا في الص نف األساس ي ‪ .Fish‬الح ظ َّ‬
‫أنن ا اس تدعينا‬
‫‪355‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫ً‬
‫راحة ض من الت ابع )(__‪ __init‬الخ اص‬
‫الت ابع )(__‪ __init‬الخ اص بالص نف ‪ Fish‬ص‬
‫بالصنف ‪.Trout‬‬
‫بع د إع ادة تعري ف الت ابع‪ ،‬لم نع د بحاج ة إلى تمري ر ‪ first_name‬مع اماًل إلى ‪ ،Trout‬وفي‬
‫ح ال فعلن ا ذل ك‪ ،‬فس يؤدي ذل ك إلى إع ادة تع يين ‪ freshwater‬ب دالً من ذل ك‪ .‬س ُنهيِّ ئ بع د ذل ك‬
‫الخاصية ‪ first_name‬عن طريق استدعاء المتغير في الكائن خاصتنا‪.‬‬
‫ُأ‬
‫اآلن يمكنن ا اس تدعاء متغ يرات الص نف األساس ي ال تي ع ِّدت‪ ،‬وك ذلك اس تخدام المتغيِّ ر‬
‫الخاص بالصنف الفرعي‪:‬‬
‫‪...‬‬
‫)(‪terry = Trout‬‬
‫تهيئة االسم األول ‪#‬‬
‫"‪terry.first_name = "Terry‬‬
‫استخدام )(__‪__init‬‬
‫الخاص بالصنف األساسي عبر‬
‫)(‪# super‬‬
‫)‪print(terry.first_name + " " + terry.last_name‬‬
‫)‪print(terry.eyelids‬‬
‫استخدام )(__‪ __init‬المعاد تعريفها في الصنف الفرعي ‪#‬‬
‫)‪print(terry.water‬‬
‫استخدام التابع )(‪ swim‬الخاص بالصنف األساسي ‪#‬‬
‫)(‪terry.swim‬‬
‫سنحصل على المخرجات التالية‪:‬‬
‫‪Terry Fish‬‬
‫‪False‬‬
‫‪freshwater‬‬
‫‪356‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫‪The fish is swimming.‬‬
‫أن الك ائن ‪ terry‬المنس وخ من الص نف الف رعي ‪ Trout‬ق ادر على اس تخدام‬
‫ُتظهر المخرجات َّ‬
‫المتغ ير ‪ water‬الخ اص بت ابع الص نف الف رعي )(__‪ ،__init‬إض افة إلى اس تدعاء المتغ يرات‬
‫‪ first_name‬و ‪ last_name‬و ‪ eyelids‬الخاص ة بالت ابع )(__‪ __init‬المُ ع رَّ ف في الص نف‬
‫األساسي ‪.Fish‬‬
‫يسمح لنا الت ابع )(‪ super‬المُ ض من في ب ايثون باس تخدام تواب ع الص نف األساس ي ح تى بع د‬
‫إعادة تعريف تلك التوابع في األصناف الفرعية‪.‬‬
‫تعددة (‪)Multiple Inheritance‬‬
‫الم ِّ‬
‫‪ .6‬الوراثة ُ‬
‫المقصود بالوراث ة المتع ددة هي ق درة الص نف على أن ي رث الخاص يات والتواب ع من أك ثر من‬
‫ص نف أساس ي واح د‪ .‬ه ذا من ش أنه تقلي ل التك رار في ال برامج‪ ،‬ولكنَّه ق د يُ ِّ‬
‫عقد العم ل‪ ،‬ل ذلك يجب‬
‫استخدام هذا المفهوم بحذر‪.‬‬
‫إلظه ار كيفي ة عم ل الوراث ة المتع ِّددة‪ ،‬دعن ا ننش ئ ص ً‬
‫فرعي ا ‪ Coral_reef‬ي رث من‬
‫نفا‬
‫ً‬
‫الصنفين ‪ Coral‬و ‪ .Sea_anemone‬يمكننا إنش اء ت ابع في ك ل ص نف أساس ي‪ ،‬ثم اس تخدام الكلم ة‬
‫المفتاحية ‪ pass‬في الصنف الفرعي ‪:Coral_reef‬‬
‫‪class Coral:‬‬
‫‪def community(self):‬‬
‫)"‪print("Coral lives in a community.‬‬
‫‪class Anemone:‬‬
‫‪def protect_clownfish(self):‬‬
‫‪357‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫مفهوم الوراثة في البرمجة‬
‫)"‪print("The anemone is protecting the clownfish.‬‬
‫‪class CoralReef(Coral, Anemone):‬‬
‫‪pass‬‬
‫يحت وي الص نف ‪ Coral‬على ت ابع يس مى )(‪ ،community‬وال ذي يطب ع س طرًا واح ًدا‪ ،‬بينم ا‬
‫يحت وي الص نف ‪ Anemone‬على ت ابع يس مى )(‪ ،protect_clownfish‬وال ذي يطب ع س طرًا آخ ر‪.‬‬
‫مرر الص نفين كالهم ا بين قوس ين في تعري ف الص نف ‪ ،CoralReef‬م ا يع ني َّ‬
‫س ُن ِّ‬
‫أنه س يرث‬
‫الصنفين معً ا‪.‬‬
‫دعنا اآلن ننشئ كائنًا من الصنف ‪:CoralReef‬‬
‫‪...‬‬
‫)(‪great_barrier = CoralReef‬‬
‫)(‪great_barrier.community‬‬
‫)(‪great_barrier.protect_clownfish‬‬
‫الك ائن ‪ great_barrier‬مُ ش ٌ‬
‫تق الص نف ‪ ،CoralReef‬ويمكن ه اس تخدام التواب ع من كال‬
‫الصنفين األساسيين‪ .‬عند تنفيذ البرنامج‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫‪Coral lives in a community.‬‬
‫‪The anemone is protecting the clownfish.‬‬
‫أن التواب ع من كال الص نفين األساس يين اس ُتخدِ ما بفعالي ة في‬
‫ظه ر المخرج ات َّ‬
‫ُت ِ‬
‫الصنف الفرعي‪.‬‬
‫ِّ‬
‫تسمح لنا الوراثة المُ‬
‫تعد دة بإعادة استخدام الشيفرات البرمجية المكتوبة في أكثر من ص نف‬
‫أساسي واحد‪ .‬وإذا تم تعريف التابع نفسه في أكثر من ص نف أساس ي واح د‪ ،‬فسيس تخدم الص نف‬
‫‪358‬‬
‫|‬
‫▲‬
‫مفهوم الوراثة في البرمجة‬
‫البرمجة بلغة بايثون‬
‫الف رعي الت ابع الخ اص بالص نف األساس ي ال ذي ظه ر أواًل في قائم ة األص ناف المُ م رَّ رة إلي ه‬
‫عند تعريفه‪.‬‬
‫أن علي ك ت وخي الح ذر في اس تخدام الوراث ة المُ تع ِّددة‪،‬‬
‫رغم فوائ دها الكث يرة وفعاليته ا‪ ،‬إال َّ‬
‫حتى ال ينتهي بك األمر بكتابة برامج مُ َّ‬
‫عقدة وغير مفهومة للمبرمجين اآلخرين‪.‬‬
‫‪ .7‬خالصة الفصل‬
‫وكيفية إع ادة تعري ف تواب ع‬
‫وفرعية‪،‬‬
‫كيفية إنش اء أص ناف أساس ية‬
‫تعلمن ا في ه ذا الفص ل‬
‫َّ‬
‫َّ‬
‫َّ‬
‫وخاص يات األص ناف األساس ية داخ ل األص ناف الفرعي ة باس تخدام الت ابع )(‪ ،super‬إض افة إلى‬
‫مفهوم الوراثة المتعددة‪.‬‬
‫الوراثة هي إحدى أهم ميزات البرمجة الكائنية ال تي تجعله ا متوافق ة م ع مب دأ ‪( DRY‬ال تك رر‬
‫نفسك) ‪ ،‬وهذا يحسن إنتاجية المبرمجين‪ ،‬ويساعدهم على تصميم برامج فعالة وواضحة‪.‬‬
‫‪359‬‬
‫|‬
‫▲‬
‫‪20‬‬
‫التعددية الشكلية‬
‫وتطبيقاتها‬
‫‪360‬‬
‫|‬
‫▲‬
‫التعددية الشكلية وتطبيقاتها‬
‫البرمجة بلغة بايثون‬
‫التعددية الشكلية (‪ )Polymorphism‬هي القدرة على اس تخدام واجه ة موح دة لع دة أش كال‬
‫مختلف ة‪ ،‬مث ل أن واع البيان ات أو األص ناف‪ ،‬وه ذا يس مح لل دوال باس تخدام كيان ات من‬
‫أن واع مختلف ة‪ .‬بالنس بة لل برامج الكائني ة في ب ايثون‪ ،‬ه ذا يع ني َّ‬
‫أنه يمكن اس تخدام ك ائن معين‬
‫عين كم ا ل و ك ان ينتمي إلى ص نف مختل ف‪ .‬تس مح التعددي ة الش كلية بكتاب ة‬
‫ينتمي إلى ص نف مُ َّ‬
‫شيفرات مرنة ومجرَّ َدة وسهلة التوسيع والصيانة‪.‬‬
‫سوف تتعلم في هذا الفصل كيفية تطبيق التعددية الشكلية على أصناف بايثون‪.‬‬
‫‪ .1‬ما هي التعددية الشكلية (‪)Polymorphism‬؟‬
‫التعددية الشكلية هي إحدى السمات األساسية لألصناف في بايثون‪ُ ،‬‬
‫وتستخ َدم عندما تك ون‬
‫هن اك تواب ع له ا نفس األس ماء في ع دة أص ناف‪ ،‬أو أص ناف فرعي ة‪ .‬يس مح ذل ك لل دوال باس تخدام‬
‫كائنات من أيٍّ من تلك األصناف والعمل عليها دون االكتراث لنوعها‪.‬‬
‫يمكن تنفي ذ التعددي ة الش كلية ع بر الوراث ة‪ ،‬أو باس تخدام تواب ِع األص ناف الفرعي ة‪ ،‬أو إع ادة‬
‫تعريفها (‪.)overriding‬‬
‫يس تخدم ب ايثون نظ ام أن واع (‪ )typing‬خ اص‪ ،‬يس مى «نظ ام التحق ق من األن واع‪ :‬البط ة‬
‫ً‬
‫نموذجا» (‪ ،)Duck Typing‬وه و حال ة خاص ة من أنظم ة التحق ق من األن واع الديناميكي ة‬
‫(‪ .)Dynamic Typing‬يس تخدم ه ذا النظ امُ التع ُّددي َة الش كلية‪ ،‬بم ا في ذل ك الرب ط المت أخر‬
‫(‪ ،)late binding‬واإليف اد ال ديناميكي (‪ .)Dynamic dispatch‬يعتم د ه ذا النظ ام على «نم وذج‬
‫اقتباس للكاتب جيمس ويتكومب رايلي‪:‬‬
‫بناء على‬
‫ً‬
‫البطة»‬
‫ٍ‬
‫«عن دما أرى ط ائ ًرا يمش ي مث ل بط ة‪ ،‬ويس بح مث ل بط ة‪ ،‬وص وته كص وت البط ة‪،‬‬
‫ً‬
‫بطة»‬
‫فسأع ُّد هذا الطائر‬
‫‪361‬‬
‫|‬
‫▲‬
‫التعددية الشكلية وتطبيقاتها‬
‫البرمجة بلغة بايثون‬
‫ُخ ِّ‬
‫صص ه ذا المفه وم من قب ل مهن دس الحاس وب اإليط الي أليكس م ارتيلي ( ‪)Alex Martelli‬‬
‫في رس الة إلى مجموع ة ‪ ،comp.lang.python‬يق وم نظ ام التحق ق من األن واع ه ذا ال ذي يعتم د‬
‫نموذج ا على تعري ف الك ائن من منظ ور مالءم ة الغ رض ال ذي ُأ ِ‬
‫ً‬
‫نش ئ ألجل ه‪ .‬عن د اس تخدام‬
‫البط ة‬
‫عين يتح دد بن وع الك ائن فق ط‪ ،‬ولكن في نم وذج‬
‫إن مالءم ة الك ائن لغ رض مُ َّ‬
‫نظ ام أن واع ع ادي‪ ،‬ف َّ‬
‫البط ة‪ ،‬يَ تح َّدد ذل ك بوج ود التواب ع والخاص يات الض رورية ل ذلك الغ رض ب داًل من الن وع الحقيقي‬
‫ُّ‬
‫التحقق مم ا إذا ك ان ذل ك‬
‫للك ائن‪ .‬بمع نى آخ ر‪ ،‬إذا أردت أن تع رف إن ك ان الك ائن بط ًة أم ال‪ ،‬فعلي ك‬
‫ً‬
‫بطة‪.‬‬
‫مشي البطة‪ ،‬وصوته كصوت البطة‪ ،‬بداًل من أن تسأل عما إذا كان الكائن‬
‫الكائن يمشي‬
‫َ‬
‫عندما تحتوي عدة أص ناف أو أص ناف فرعي ة على تواب ع له ا نفس األس ماء‪ ،‬ولكن بس لوكيات‬
‫إن تل ك األص ناف متع ِّددة األش كال ( ‪َّ )polymorphic‬‬
‫ألنه ا تس تعمل واجه ة موح دة‬
‫مختلفة‪ ،‬نق ول َّ‬
‫يمكن استخدامها مع كيانات من أنواع مختلفة‪ .‬يمكن للدوال تقييم ومعالجة هذه التواب ع متع ِّددة‬
‫األشكال دون معرفة أصنافها‪.‬‬
‫‪ .2‬إنشاء أصناف متعددة األشكال‬
‫لالس تفادة من التَع ُّددي ة الش كلية‪ ،‬سننش ئ ص نفين مختلفين الس تخدامهما م ع ك ائنين‬
‫مختلفين‪ .‬يحتاج هذان الصنفان المختلفان إلى واجه ة موح دة يمكن اس تخدامها بطريق ة تع ُّددي ة‬
‫ِّ‬
‫سنعرف فيهما توابع مختلفة‪ ،‬ولكن لها نفس االسم‪.‬‬
‫الشكل (‪ ،)polymorphically‬لذلك‬
‫نفا باس م ‪ Shark‬وص ُ‬
‫سننش ئ ص ً‬
‫نفا آخ ر باس م ‪ ،Clownfish‬وس ُي ِّ‬
‫عرف ك ل منهم ا التواب ع‬
‫)(‪ swim‬و )(‪ swim_backwards‬و )(‪.skeleton‬‬
‫‪362‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعددية الشكلية وتطبيقاتها‬
‫‪class Shark():‬‬
‫‪def swim(self):‬‬
‫)"‪.‬القرش يسبح"(‪print‬‬
‫‪def swim_backwards(self):‬‬
‫ال يمكن للقرش أن يسبح إلى الوراء‪ ،‬لكن يمكنه أن يغوص "(‪print‬‬
‫)"‪.‬إلى الوراء‬
‫‪def skeleton(self):‬‬
‫)"‪.‬هيكل القرش مصنوع من الغضروف"(‪print‬‬
‫‪class Clownfish():‬‬
‫‪def swim(self):‬‬
‫)"‪.‬سمكة المهرج تسبح"(‪print‬‬
‫‪def swim_backwards(self):‬‬
‫)"‪.‬يمكن لسمكة المهرج أن تسبح إلى الخلف"(‪print‬‬
‫‪def skeleton(self):‬‬
‫)"‪.‬هيكل سمكة المهرج مصنوع من العظام"(‪print‬‬
‫بي د‬
‫في الش يفرة أعاله‪ ،‬ل دى الص نفين ‪ Shark‬و ‪ Clownfish‬ثالث ة تواب ع تحم ل نفس االس م ْ‬
‫أن وظائف تلك التوابع تختلف من صنف آلخر‪.‬‬
‫َّ‬
‫دعنا نستنسخ (‪ )instantiate‬من هذين الصنفين كائنين‪:‬‬
‫‪...‬‬
‫)(‪sammy = Shark‬‬
‫)(‪sammy.skeleton‬‬
‫)(‪casey = Clownfish‬‬
‫)(‪casey.skeleton‬‬
‫‪363‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعددية الشكلية وتطبيقاتها‬
‫أن‬
‫عند تنفيذ البرن امج باس تخدام األم ر ‪ ،python polymorphic_fish.py‬يمكنن ا أن ن رى َّ‬
‫كل كائن يتصرف كما هو متوقع‪:‬‬
‫‪.‬هيكل القرش مصنوع من الغضروف‬
‫‪.‬هيكل سمكة المهرج مصنوع من العظام‬
‫اآلن وقد أصبح لدينا كائنين يستخدمان نفس الواجه ة‪ ،‬فبمق دورنا اس تخدام ه ذين الك ائنين‬
‫بنفس الطريقة بغض النظر عن نوعيهما‪.‬‬
‫‪ .3‬التعددية الشكلية في توابع األصناف‬
‫إلظه ار كي ف يمكن لب ايثون اس تخدام الص نفين المختلفين الل ذين عرَّ فناهم ا أعاله بنفس‬
‫الطريقة‪ ،‬سننشئ أوالً حلقة ‪ ،for‬والتي ستمر على صف من الكائنات‪ .‬ثم سنستدعي التواب ع بغض‬
‫النظر عن نوع الصنف الذي ينتمي إليه كل كائن‪ .‬إال َّ‬
‫أن تلك التواب ع موج ودة في ك ل‬
‫أننا سنفترض َّ‬
‫تلك األصناف‪.‬‬
‫‪...‬‬
‫)(‪sammy = Shark‬‬
‫)(‪casey = Clownfish‬‬
‫‪for fish in (sammy, casey):‬‬
‫)(‪fish.swim‬‬
‫)(‪fish.swim_backwards‬‬
‫)(‪fish.skeleton‬‬
‫ل دينا كائن ان‪ sammy ،‬من الص نف ‪ ،Shark‬و ‪ casey‬من الص نف ‪ .Clownfish‬تم ر حلق ة ‪for‬‬
‫‪364‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعددية الشكلية وتطبيقاتها‬
‫على ه ذين الك ائنين‪ ،‬وتس تدعي التواب ع )(‪ swim‬و )(‪ swim_backwards‬و )(‪ skeleton‬على‬
‫كل منها‪.‬‬
‫عند تنفيذ البرنامج‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫‪.‬القرش يسبح‬
‫‪.‬ال يمكن للقرش أن يسبح إلى الوراء‪ ،‬لكن يمكنه أن يغوص إلى الوراء‬
‫‪.‬هيكل القرش مصنوع من الغضروف‬
‫‪.‬سمكة المهرج تسبح‬
‫‪.‬يمكن لسمكة المهرج أن تسبح إلى الخلف‬
‫‪.‬هيكل سمكة المهرج مصنوع من العظام‬
‫مرت الحلق ة ‪ for‬على الك ائن ‪ sammy‬من الص نف ‪ ،Shark‬ثم على الك ائن ‪ casey‬المنتمي إلى‬
‫الص نف ‪ ،Clownfish‬ل ذلك ن رى التواب ع الخاص ة بالص نف ‪ Shark‬قب ل التواب ع الخاص ة‬
‫بالصنف ‪.Clownfish‬‬
‫ي ُّ‬
‫أن ب ايثون تس تخدم ه ذه التواب ع دون أن تع رف أو تعب أ بتحدي د ن وع الص نف‬
‫دل ه ذا على َّ‬
‫ِّ‬
‫الخاص بالكائنات‪ .‬وهذا مثال حي على استخدام التوابع بطريقة مُ‬
‫تعد َدة األشكال‪.‬‬
‫‪ .4‬التعددية الشكلية في الدوال‬
‫ً‬
‫أي شيء‪ ،‬وهذا سيسمح باستخدام التعددية الشكلية‪.‬‬
‫يمكننا‬
‫أيضا إنشاء دالة تقبل ٌّ‬
‫لننشئ دال ة تس مى )(‪ ،in_the_pacific‬وال تي تأخ ذ كائ ًن ا يمكنن ا تس ميته ‪ .fish‬رغم َّ‬
‫أنن ا‬
‫سنستخدم االسم ‪ ،fish‬إال َّ‬
‫أنه يمكننا استدعاء أي كائن في هذه الدالة‪:‬‬
‫…‬
‫‪def in_the_pacific(fish):‬‬
‫بع د ذل ك‪ ،‬س نجعل الدال ة تس تخدم الك ائن ‪ fish‬ال ذي مرَّ رن اه إليه ا‪ .‬وفي ه ذه الحال ة‪،‬‬
‫‪365‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
‫التعددية الشكلية وتطبيقاتها‬
‫ِّ‬
‫المعرف في كل من الصنفين ‪ Shark‬و ‪:Clownfish‬‬
‫سنستدعي التابع )(‪swim‬‬
‫‪...‬‬
‫‪def in_the_pacific(fish):‬‬
‫)(‪fish.swim‬‬
‫ِّ‬
‫ً‬
‫لنمررهم ا بع د‬
‫نسخا (‪ )instantiations‬من الص نفين ‪ Shark‬و ‪Clownfish‬‬
‫بعد ذلك‪ ،‬سننشئ‬
‫ذلك إلى نفس الدالة )(‪:in_the_pacific‬‬
‫‪...‬‬
‫‪def in_the_pacific(fish):‬‬
‫)(‪fish.swim‬‬
‫)(‪sammy = Shark‬‬
‫)(‪casey = Clownfish‬‬
‫)‪in_the_pacific(sammy‬‬
‫)‪in_the_pacific(casey‬‬
‫عند تنفيذ البرنامج‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫‪.‬القرش يسبح‬
‫‪.‬سمكة المهرج تسبح‬
‫عشوائيا (‪ )fish‬إلى الدالة )(‪ in_the_pacific‬عند تعريفها‪ ،‬إال َّ‬
‫أننا ما‬
‫رغم أننا مرَّ رنا كائنًا‬
‫ً‬
‫زلن ا ق ادرين على اس تخدامها اس تخدامً ا فع ااًل ‪ ،‬وتمري ر نس خ من الص نفين ‪ Shark‬و ‪Clownfish‬‬
‫ائن ‪ casey‬الت ابعَ )(‪ swim‬المُ ع رَّ ف في الص نف ‪ ،Clownfish‬فيم ا اس تدعى‬
‫إليه ا‪ .‬اس تدعى الك ُ‬
‫الكائن ‪ sammy‬التابعَ )(‪ swim‬المُ عرَّ ف في الصنف ‪.Shark‬‬
‫ُ‬
‫‪366‬‬
‫|‬
‫▲‬
‫التعددية الشكلية وتطبيقاتها‬
‫البرمجة بلغة بايثون‬
‫‪ .5‬خالصة الفصل‬
‫تس مح التع ُّددي ة الش كلية باس تخدام الكائن ات بغض النظ ر عن نوعه ا‪ ،‬وه ذا ي وفر لب ايثون‬
‫مرونة كبيرة‪ ،‬وقابلية لتوسيع الشيفرة الكائنية‪.‬‬
‫‪367‬‬
‫|‬
‫▲‬
‫‪21‬‬
‫تنقيح الشيفرات‪:‬‬
‫ِّ‬
‫منقح‬
‫استخدام‬
‫بايثون‬
‫‪368‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫التنقيح (‪– )debugging‬في تط وير البرمجي ات– هي عملي ة البحث عم ح ل المش اكل ال تي‬
‫تمن ع عم ل البرمجي ة عماًل س ليمً ا‪ .‬ي ِّ‬
‫وفر ِّ‬
‫منقح ب ايثون ( ‪ )Python Debugger‬بيئ ة متكامل ة لتنقيح‬
‫ب رامج ب ايثون‪ ،‬إذ ت دعم ض بط مواض ع التوق ف (‪ )breakpoints‬الش رطية‪ ،‬وتنفي ذ الش يفرات‬
‫ِّ‬
‫مكدس (‪ )stack‬االستدعاء‪ ،‬وخالف ذلك‪.‬‬
‫المصدرية سطرً ا بسطر‪ ،‬وتفحص‬
‫تفاعليا‬
‫‪ .1‬تشغيل منقح بايثون‬
‫ً‬
‫يأتي ِّ‬
‫جزءا من تث بيت ب ايثون القياس ي بش كل وح دة باس م ‪ .pdb‬يمكن توس عة‬
‫ً‬
‫منقح بايثون‬
‫ِّ‬
‫المنقح بمزيد من الوظائف‪ ،‬ويُ عرَّ ف بالصنف ‪ .Pdb‬يمكنك الع ودة إلى التوثي ق الرس مي للمنقح ‪pdb‬‬
‫امج قص ير يحت وي على متغ يرين ع امين‬
‫لمزي دٍ من المعلوم ات‪ .‬س نبدأ تجاربن ا م ع برن‬
‫ٍ‬
‫(‪ )global variables‬ودال ة (‪ )function‬ال تي تحت وي على حلق ة تك رار ‪ for‬متش ِّعبة‪ ،‬والبني ة‬
‫الشهيرة ‪ if __name__ == '__main__':‬التي تستدعي الدالة )(‪:nested_loop‬‬
‫]‪num_list = [500, 600, 700‬‬
‫]'‪alpha_list = ['x', 'y', 'z‬‬
‫‪def nested_loop():‬‬
‫‪for number in num_list:‬‬
‫)‪print(number‬‬
‫‪for letter in alpha_list:‬‬
‫)‪print(letter‬‬
‫‪if __name__ == '__main__':‬‬
‫)(‪nested_loop‬‬
‫‪369‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫يمكننا اآلن تشعيل البرنامج باستخدام منقح بايثون عبر األمر اآلتي‪:‬‬
‫‪python -m pdb looping.py‬‬
‫سيؤدي استخدام خي ار س طر األوام ر ‪ -m‬إلى اس تيراد أي وح دة ب ايثون تري دها‪ ،‬وفي حالتن ا‬
‫فسنستورد الوحدة ‪ ،pdb‬والتي س نمررها إلى الخي ار ‪ -m‬كم ا ه و م بيِّ ن في األم ر الس ابق‪ .‬ستحص ل‬
‫على الناتج اآلتي بعد تنفيذك لألمر السابق‪:‬‬
‫)(>‪> /Users/sammy/looping.py(1)<module‬‬
‫]‪-> num_list = [500, 600, 700‬‬
‫)‪(Pdb‬‬
‫الحظن ا في أول س طر من المخرج ات احت واءه على اس م الوح دة ال تي َّ‬
‫حالي ا (كم ا ه و‬
‫تنفذ‬
‫ً‬
‫موضح بالكلم ة <‪ >module‬م ع كام ل مس ار الس كربت‪ ،‬ويلي ه رقم الس طر ال تي ُن ِّفذ أول م رة (وفي‬
‫هذه الحالة سيكون الرقم ‪ ،1‬لكن ق د توج د تعليق ات أو أس طر غ ير قابل ة للتنفي ذ في بداي ة المل ف‪،‬‬
‫لذا قد يكون الرقم أكبر في بعض الحاالت)‪.‬‬
‫ظه ر الس طر الث اني م ا ه و الس طر الح الي ال ذي يُ َّ‬
‫حالي ا‪ ،‬ولمَّ ا كنَّا ق د ش غلنا المنقح ‪pdb‬‬
‫نفذ‬
‫ً‬
‫يُ ِ‬
‫تفاعلي ا فس يوفر لن ا س طر أوام ر تف اعلي للتنقيح‪ .‬ويمكن ك كتاب ة األم ر ‪ help‬للتع رف على األوام ر‬
‫ً‬
‫معين‪.‬‬
‫أمر‬
‫َّ‬
‫الخاصة بالمنقح‪ ،‬و ‪ help command‬لمزيد من المعلومات حول ٍ‬
‫أن منقح ب ايثون‬
‫الحظ أن سطر أوام ر ‪ pdb‬يختل ف عن الوض ع التف اعلي في ب ايثون‪ ،‬والح ظ َّ‬
‫تلقائيا؛ لذا يمكنك استخدام األم ر ‪ quit‬أو ‪exit‬‬
‫سيبدأ من جديد حين وصوله إلى نهاية البرنامج‬
‫ً‬
‫وقت تري د للخ روج من المنقح‪ .‬أمَّ ا إذا أردت إع ادة تش غيل المنقح من بداي ة البرن امج‬
‫ٍ‬
‫في أي‬
‫مجد ًدا‪ ،‬فيمكنك استعمال األمر ‪.run‬‬
‫‪370‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪ .2‬استخدام المنقح للتنقل ضمن البرنامج‬
‫من الش ائع أثن اء عمل ك م ع منقح ب ايثون أن تس تعمل األوام ر ‪ list‬و ‪ step‬و ‪ next‬للتح رك‬
‫ضمن الشيفرة‪ .‬سنشرح هذه األوامر في ه ذا القس م‪ .‬يمكنن ا كتاب ة األم ر ‪ list‬ض من منقح ب ايثون‬
‫التف اعلي للحص ول على الش يفرات المحيط ة بالس طر الح الي‪ ،‬فل و نف ذناه عن د الس طر األول من‬
‫برنامج ‪ looping.py‬فستبدو المخرجات كما يلي‪:‬‬
‫‪(Pdb) list‬‬
‫]‪-> num_list = [500, 600, 700‬‬
‫‪1‬‬
‫]'‪alpha_list = ['x', 'y', 'z‬‬
‫‪2‬‬
‫‪3‬‬
‫‪4‬‬
‫‪def nested_loop():‬‬
‫‪for number in num_list:‬‬
‫‪5‬‬
‫‪6‬‬
‫)‪print(number‬‬
‫‪7‬‬
‫‪for letter in alpha_list:‬‬
‫‪8‬‬
‫)‪print(letter‬‬
‫‪9‬‬
‫‪10‬‬
‫‪if __name__ == '__main__':‬‬
‫‪11‬‬
‫)‪(Pdb‬‬
‫يُ شار إلى السطر الحالي بالمحرفين >‪ -‬اللذين يشيران في حالتنا إلى أول سطر من البرنامج‪.‬‬
‫ولمَّ ا ك ان برنامجن ا قص ي ًرا‪ ،‬فسنحص ل على كام ل البرن امج عن د اس تخدام األم ر ‪ .list‬فحين‬
‫ً‬
‫محيط ا بالس طر الح الي‪ ،‬لكن‬
‫اس تخدام األم ر ‪ list‬دون أيَّ ة وس ائط‪ ،‬فس يعرض أح د عش ر س ط ًرا‬
‫يمكننا تحديد ما هي األسطر التي نريد عرضها كما يلي‪:‬‬
‫‪371‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪(Pdb) list 3, 7‬‬
‫‪3‬‬
‫‪4‬‬
‫‪def nested_loop():‬‬
‫‪for number in num_list:‬‬
‫)‪print(number‬‬
‫‪5‬‬
‫‪6‬‬
‫‪7‬‬
‫)‪(Pdb‬‬
‫طلبن ا في المث ال الس ابق أن يع رض المنقح األس طر ‪ 3‬إلى ‪ ،7‬وذل ك باس تخدام األم ر‬
‫‪ .list 3, 7‬للتنقل عبر البرنامج سط ًرا بسطر‪ ،‬فيمكننا استخدام األمر ‪ step‬أو ‪:next‬‬
‫‪(Pdb) step‬‬
‫)(>‪> /Users/sammy/looping.py(2)<module‬‬
‫]'‪-> alpha_list = ['x', 'y', 'z‬‬
‫)‪(Pdb‬‬
‫‪(Pdb) next‬‬
‫)(>‪> /Users/sammy/looping.py(2)<module‬‬
‫]'‪-> alpha_list = ['x', 'y', 'z‬‬
‫)‪(Pdb‬‬
‫أن ‪ step‬س تتوقف داخ ل دال ة ج رى اس تدعاؤها‪ ،‬أم ا ‪next‬‬
‫الف رق بين ‪ step‬و ‪ next‬ه و َّ‬
‫فس ِّ‬
‫تنفذ ال دوال وتتوق ف في الس طر الت الي من تنفي ذ الدال ة‪ .‬س نرى ه ذا الف رق رأي العين حين‬
‫نتعام ل م ع الدال ة الموج ودة في برنامجن ا‪ .‬األم ر ‪ step‬س يمر على الحلق ات خط ً‬
‫وة خط وة ح تى‬
‫ظه ر م ا ال ذي تفعل ه الحلق ة تمامً ا‪ ،‬إذ س نبدأ بطباع ة ال رقم‬
‫يص ل إلى نهاي ة الدال ة‪ ،‬مم ا يُ ِ‬
‫)‪ print(number‬ثم ننطلق إلى طباعة األحرف )‪ print(letter‬ثم نعود إلى الرقم وهكذا‪.‬‬
‫‪(Pdb) step‬‬
‫)(>‪> /Users/sammy/looping.py(5)<module‬‬
‫‪-> def nested_loop():‬‬
‫‪(Pdb) step‬‬
‫‪372‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) step
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb) step
--Call-> /Users/sammy/looping.py(5)nested_loop()
-> def nested_loop():
(Pdb) step
> /Users/sammy/looping.py(6)nested_loop()
-> for number in num_list:
(Pdb) step
> /Users/sammy/looping.py(7)nested_loop()
-> print(number)
(Pdb) step
500
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb) step
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb) step
x
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
(Pdb) step
> /Users/sammy/looping.py(9)nested_loop()
-> print(letter)
(Pdb) step
y
> /Users/sammy/looping.py(8)nested_loop()
-> for letter in alpha_list:
▲
|
373
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
(Pdb)
ِّ ‫ فس‬next ‫أمَّ ا األم ر‬
ً ‫ينفذ الدال ة بأكمله ا دون أن يرين ا العملي ة خط‬
‫ لنغل ق الجلس ة‬.‫وة بخط وة‬
ِّ
ِّ ‫ ثم ُن‬exit ‫الحالية باستخدام األمر‬
:‫المنقح مجد ًدا‬
‫شغل‬
python -m pdb looping.py
:next ‫يمكننا اآلن تجربة األمر‬
(Pdb) next
> /Users/sammy/looping.py(5)<module>()
-> def nested_loop():
(Pdb) next
> /Users/sammy/looping.py(11)<module>()
-> if __name__ == '__main__':
(Pdb) next
> /Users/sammy/looping.py(12)<module>()
-> nested_loop()
(Pdb) next
500
x
y
z
600
x
y
z
700
x
y
z
--Return-> /Users/sammy/looping.py(12)<module>()->None
▲
|
374
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫)(‪-> nested_loop‬‬
‫)‪(Pdb‬‬
‫ُّ‬
‫تفحص القيم المُ سنَدة إلى المتغيرات أثناء مرورك على الشيفرة‪ ،‬ويمكنك فع ل‬
‫قد ترغب في‬
‫ذلك باستخدام األمر ‪ ،pp‬والذي يطبع قيمة التعبير المُ مرَّ ر إليه باستخدام الوحدة ‪:pprint‬‬
‫‪(Pdb) pp num_list‬‬
‫]‪[500, 600, 700‬‬
‫)‪(Pdb‬‬
‫تمل ك أغلبي ة األوام ر في المنقح ‪ pdb‬اختص ارات له ا‪ ،‬فمثاًل الش كل المختص ر من األم ر ‪step‬‬
‫ه و ‪ ،s‬والمختص ر من ‪ next‬ه و ‪ .n‬س يعرض ل ك األم ر ‪ help‬قائم ة االختص ارات المتاح ة‪ .‬يمكن ك‬
‫ً‬
‫أيضا إعادة استدعاء آخر أمر ُن ِّفذ في المنقح بالضغط على زر اإلدخال ‪.Enter‬‬
‫‪ .3‬نقاط التوقف‬
‫من المرجح َّ‬
‫أنك ستعمل على برمجيات أكبر بكثير من المثال الس ابق‪ ،‬ل ذا ق د ت رغب بتفحص‬
‫دوال أو أس طر معين ة ب داًل من الم رور على كام ل البرن امج‪ ،‬ويمكن ك أن تض بط نق اط التوق ف‬
‫(‪ )breakpoints‬باس تخدام األم ر ‪ ،break‬فس يعمل البرن امج ح تى نقط ة التوق ف المح ددة‪ .‬عن دما‬
‫تضيف نقطة توق ف فسيس ند المنقح رقمً ا إليه ا‪ ،‬وه ذه األرق ام متتالي ة وتب دأ من ‪ ،1‬وال تي يمكن ك‬
‫االستفادة منها حين التعامل مع نقاط التوقف‪ .‬يمكن إضافة نقاط توقف في أسطر برمجية معين ة‬
‫باستخدام الصيغة اآلتية في منقح ‪ pdb‬على الشكل <‪:>program_file>:<line_number‬‬
‫‪(Pdb) break looping.py:5‬‬
‫‪Breakpoint 1 at /Users/sammy/looping.py:5‬‬
‫)‪(Pdb‬‬
‫اكتب ‪ clear‬ثم ‪ y‬إلزال ة جمي ع نق اط التوق ف الحالي ة‪ ،‬يمكن ك بع دها أن تض ع نقط ة توق ف‬
‫‪375‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫مكان تعريف الدالة‪:‬‬
‫‪(Pdb) break looping.nested_loop‬‬
‫‪Breakpoint 1 at /Users/sammy/looping.py:5‬‬
‫)‪(Pdb‬‬
‫إلزال ة نق اط التوق ف الحالي ة‪ ،‬اكتب ‪ clear‬ثم ‪ y‬مج د ًدا‪ .‬يج در بال ذكر َّ‬
‫أنك تس تطيع أن‬
‫ً‬
‫شرطا‪:‬‬
‫تضيف‬
‫‪(Pdb) break looping.py:7, number > 500‬‬
‫‪Breakpoint 1 at /Users/sammy/looping.py:7‬‬
‫)‪(Pdb‬‬
‫حينما نستعمل اآلن األمر ‪ continue‬فسيتوقف تنفيذ البرنامج عندما تكون قيمة الرقم أكبر‬
‫من ‪( 500‬أي عندما يكون مساويًا إلى ‪ ،600‬وذلك في الدورة الثانية لحلقة التكرار الخارجية)‪:‬‬
‫‪(Pdb) continue‬‬
‫‪500‬‬
‫‪x‬‬
‫‪y‬‬
‫‪z‬‬
‫)(‪> /Users/sammy/looping.py(7)nested_loop‬‬
‫)‪-> print(number‬‬
‫)‪(Pdb‬‬
‫لرؤي ة قائم ة من نق اط التوق ف ال تي ض بطت‪ ،‬فيمكن ك أن تس تعمل األم ر ‪ break‬دون أي‬
‫وسائط‪ ،‬وستحصل على معلومات حول نقاط التوقف جميعها التي ضبطتها‪:‬‬
‫‪(Pdb) break‬‬
‫‪Where‬‬
‫‪Disp Enb‬‬
‫‪Num Type‬‬
‫‪at /Users/sammy/looping.py:7‬‬
‫‪keep yes‬‬
‫‪1‬‬
‫‪breakpoint‬‬
‫‪stop only if number > 500‬‬
‫‪376‬‬
‫|‬
‫▲‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
breakpoint already hit 2 times
(Pdb)
ً
‫ إذ‬.‫ م ع رقم نقط ة التوق ف‬disable ‫أيض ا تعطي ل نقط ة توق ف باس تخدام األم ر‬
‫يمكن ك‬
ِّ ‫سنضيف في هذا المثال نقطة توقف جديدة ثم‬
:‫نعطل أول نقطة توقف‬
(Pdb) break looping.py:11
Breakpoint 2 at /Users/sammy/looping.py:11
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) break
Num Type
Disp Enb
Where
1
keep no
at /Users/sammy/looping.py:7
breakpoint
stop only if number > 500
breakpoint already hit 2 times
2
breakpoint
keep yes
at /Users/sammy/looping.py:11
(Pdb)
‫كلي ا فاس تخدم‬
ً ‫ وإلزال ة نقط ة التوق ف‬،enable ‫ اس تخدم األم ر‬،‫لتفعي ل نقط ة توق ف‬
:clear ‫األمر‬
(Pdb) enable 1
Enabled breakpoint 1 at /Users/sammy/looping.py:7
(Pdb) clear 2
Deleted breakpoint 2 at /Users/sammy/looping.py:11
(Pdb)
ً
‫ وهنال ك وظ ائف إض افية له ا‬،‫دقيق ا في عملي ة التنقيح‬
‫ تحكمً ا‬pdb ‫تمنحك نقاط التوقف في‬
‫ (كم ا في‬ignore ‫تتضمن تجاهل نقاط التوقف في الجلس ة الحالي ة من البرن امج باس تخدام األم ر‬
‫ (كم ا في األمر‬command ‫ وتشغيل إجراءات في نقاط التوقف باس تخدام األم ر‬،)ignore 1 ‫األمر‬
▲
|
377
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫َّ‬
‫مؤقت ة س ُت َ‬
‫تلقائي ا بع د الوص ول إليه ا وذل ك باس تخدام‬
‫حذف‬
‫‪ ،)command 1‬وإنش اء نق اط توق ف‬
‫ً‬
‫األمر ‪( tbreak‬فلو أردنا إنشاء نقطة توقف مؤقتة في السطر الثالث مثاًل ‪ ،‬نكتب ‪.)tbreak 3‬‬
‫‪ .4‬دمج ‪ pdb‬مع البرامج‬
‫يمكن ك أن تب دأ جلس ة التنقيح باس تيراد الوح دة ‪ pdb‬وإض افة الدال ة )(‪pdb.set_trace‬‬
‫قبل السطر الذي تريد بدء جلسة التنقيح منه‪ .‬إذ سنضيف في مثالن ا الس ابق عب ارة ‪ import‬ونب دأ‬
‫عملية التنقيح داخل الدالة قبل حلقة التكرار الداخلية‪:‬‬
‫اسيتراد الوحدة ‪#‬‬
‫‪import pdb‬‬
‫]‪num_list = [500, 600, 700‬‬
‫]'‪alpha_list = ['x', 'y', 'z‬‬
‫‪def nested_loop():‬‬
‫‪for number in num_list:‬‬
‫)‪print(number‬‬
‫تشغيل المنقح هنا ‪#‬‬
‫)(‪pdb.set_trace‬‬
‫‪for letter in alpha_list:‬‬
‫)‪print(letter‬‬
‫‪if __name__ == '__main__':‬‬
‫)(‪nested_loop‬‬
‫ِّ‬
‫المنقح إلى ش يفرتك‪ ،‬فلن تحت اج إلى تش غيل برنامج ك بطريق ة خاص ة‪ ،‬أو ت ذكر‬
‫بإض افة‬
‫ضبط نقاط التوقف‪ .‬يسمح لك اس تيراد الوح دة ‪ pdb‬واس تدعاء الدال ة )(‪ pdb.set_trace‬بب دء‬
‫‪378‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫ِّ‬
‫المنقح أثناء تنفيذ البرنامج‪.‬‬
‫برنامج مثل المعتاد‪ ،‬وتشغيل‬
‫‪ .5‬تعديل تسلسل تنفيذ البرنامج‬
‫يسمح لن ا منقح ب ايثون بتغي ير تسلس ل تنفي ذ البرن امج باس تخدام األم ر ‪ ،jump‬وه ذا يس مح‬
‫معينة‪ ،‬أو يمكنك العودة إلى الخلف وتنفي ذ‬
‫لك باالنتقال إلى األمام في تنفيذ البرنامج لمنع شيفرة‬
‫َّ‬
‫ً‬
‫مرة أخرى‪ .‬س نعمل هن ا م ع برن امج بس يط يُ ِ‬
‫نش ئ قائم ًة ‪ list‬من الح روف الموج ودة في‬
‫الشيفرة‬
‫المتغير "‪:sammy = "sammy‬‬
‫‪def print_sammy():‬‬
‫][ = ‪sammy_list‬‬
‫"‪sammy = "sammy‬‬
‫‪for letter in sammy:‬‬
‫)‪sammy_list.append(letter‬‬
‫)‪print(sammy_list‬‬
‫‪if __name__ == "__main__":‬‬
‫)(‪print_sammy‬‬
‫إذا شغلنا البرنامج بالشكل المعت اد باس تخدام األم ر ‪ python letter_list.py‬فسنحص ل‬
‫على الناتج اآلتي‪:‬‬
‫]'‪['s‬‬
‫]'‪['s', 'a‬‬
‫]'‪['s', 'a', 'm‬‬
‫]'‪['s', 'a', 'm', 'm‬‬
‫]'‪['s', 'a', 'm', 'm', 'y‬‬
‫أمَّ ا مع منقح بايثون‪ ،‬فس نرى كي ف يمكنن ا تغي ير ت رتيب التنفي ذ بتخطي أول دورة من تنفي ذ‬
‫تغير ترتيب تنفيذ الشيفرة‪:‬‬
‫حلقة التكرار‪ ،‬وعندما نفعل ذلك‪ ،‬فسنالحظ كيف َّ‬
‫‪379‬‬
‫|‬
‫▲‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
python -m pdb letter_list.py
> /Users/sammy/letter_list.py(1)<module>()
-> def print_sammy():
(Pdb) list
1
-> def print_sammy():
2
sammy_list = []
3
sammy = "sammy"
4
for letter in sammy:
5
sammy_list.append(letter)
6
print(sammy_list)
7
8
if __name__ == "__main__":
9
print_sammy()
10
11
(Pdb) break 5
Breakpoint 1 at /Users/sammy/letter_list.py:5
(Pdb) continue
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) pp letter
's'
(Pdb) continue
['s']
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) jump 6
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
'a'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/letter_list.py:5
▲
|
380
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪(Pdb) continue‬‬
‫]'‪['s‬‬
‫]'‪['s', 'm‬‬
‫]'‪['s', 'm', 'm‬‬
‫]'‪['s', 'm', 'm', 'y‬‬
‫جلسة التنقيح السابقة تضع نقطة توقف في السطر الخامس لمن ع المنقح من تنفي ذ الش يفرة‬
‫التي تلي هذه النقطة‪ ،‬ثم تكمل تنفيذ الشيفرة (مع طباعة قيمة ‪ letter‬لنرى ما الذي يحدث) ‪ ،‬ثمَّ‬
‫سنس تخدم األم ر ‪ jump‬للتخطي إلى الس طر الس ادس‪ ،‬وفي ه ذه النقط ة ك انت قيم ة‬
‫المتغير ‪ letter‬تساوي السلسلة النصية '‪ ،'a‬لكنن ا لمَّ ا تجاوزن ا الش يفرة‪ ،‬فلن تض اف ه ذه القيم ة‬
‫إلى القائم ة (‪ )list‬المس ماة ‪ ،sammy_list‬ومن بع دها عطلن ا نقط ة التوق ف لالس تمرار في تنفي ذ‬
‫ً‬
‫طبيعيا باستخدام األمر ‪ ،continue‬وكانت النتيجة هي عدم إض افة الح رف '‪'a‬‬
‫تنفيذا‬
‫البرنامج‬
‫ً‬
‫إلى القائمة ‪.sammy_list‬‬
‫يمكنن ا اآلن إع ادة تش غيل المنقح للع ودة إلى البرن امج وإع ادة تش غيل األم ر البرمجي ة ال تي‬
‫ِّ‬
‫ً‬
‫المنقح‪:‬‬
‫مسبقا‪ ،‬وفي هذه المرة سنشغل أول حلقة تكرار في ‪ for‬في‬
‫جرى تنفيذه‬
‫)(>‪> /Users/sammy/letter_list.py(1)<module‬‬
‫‪-> def print_sammy():‬‬
‫‪(Pdb) list‬‬
‫‪-> def print_sammy():‬‬
‫‪1‬‬
‫][ = ‪sammy_list‬‬
‫‪2‬‬
‫"‪sammy = "sammy‬‬
‫‪3‬‬
‫‪for letter in sammy:‬‬
‫‪4‬‬
‫)‪sammy_list.append(letter‬‬
‫‪5‬‬
‫)‪print(sammy_list‬‬
‫‪6‬‬
‫‪7‬‬
‫‪if __name__ == "__main__":‬‬
‫‪8‬‬
‫‪381‬‬
‫|‬
‫▲‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
9
print_sammy()
10
11
(Pdb) break 6
Breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb) continue
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
's'
(Pdb) jump 5
> /Users/sammy/letter_list.py(5)print_sammy()
-> sammy_list.append(letter)
(Pdb) continue
> /Users/sammy/letter_list.py(6)print_sammy()
-> print(sammy_list)
(Pdb) pp letter
's'
(Pdb) disable 1
Disabled breakpoint 1 at /Users/sammy/letter_list.py:6
(Pdb) continue
['s', 's']
['s', 's', 'a']
['s', 's', 'a', 'm']
['s', 's', 'a', 'm', 'm']
['s', 's', 'a', 'm', 'm', 'y']
‫ ثم «قفزن ا» إلى الس طر‬،‫أض فنا في جلس ة التنقيح الس ابقة نقط ة توق ف في الس طر الس ادس‬
‫' ق د أض يفت م رتين إلى القائم ة‬s' ‫ ورأين ا أن السلس لة النص ية‬،‫الخ امس بع د اإلكم ال‬
َّ ‫ ثم‬،sammy_list
‫ ورأين ا في‬،‫عطلن ا نقط ة التوق ف في الس طر الس ادس وأكملن ا تنفي ذ البرن امج‬
َ
.sammy_list ‫' مضافين إلى القائمة‬s' ‫حرفي‬
‫المخرجات وجود‬
▲
|
382
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫ِّ‬
‫المنقح بعض أن واع القف زات‪ ،‬مث ل القف ز داخ ل وخ ارج بني ة تحكم‪ ،‬فمثاًل ال‬
‫يمكن أن يمن ع‬
‫يمكن ك أن تقف ز إلى تنفي ذ دال ة قب ل تعري ف وس ائطها‪ ،‬وال يمكن ك أن تقف ز إلى داخ ل عب ارة‬
‫ً‬
‫أيض ا أن تقف ز خ ارج بني ة ‪ .finally‬تس مح لن ا عب ارة ‪ jump‬الموج ودة‬
‫‪ .try:except‬وال يمكن ك‬
‫في ِّ‬
‫منقح بايثون بتغيير تسلسل تنفيذ البرنامج أثن اء تنقيح ه ل نرى إن ك ان باإلمك ان تحس ين ه ذا‬
‫الجزء أو فهم سبب مشكلة معينة في الشيفرة‪.‬‬
‫‪ .6‬جدول بأوامر ‪ pdb‬الشائعة‬
‫الج دول الت الي في ه أوام ر ‪ pdb‬المفي دة م ع اختص اراتها لتبقيه ا في ذهن ك أثن اء تعامل ك م ع‬
‫منقح بايثون‪:‬‬
‫األمر‬
‫الوظيفة‬
‫االختصار‬
‫طباعة قائمة الوسائط للدالة‬
‫‪args‬‬
‫‪a‬‬
‫‪break‬‬
‫‪b‬‬
‫‪continue‬‬
‫‪ c‬أو ‪cont‬‬
‫إكمال تنفيذ البرنامج‪.‬‬
‫‪help‬‬
‫‪h‬‬
‫توفير قائمة األوامر‪ ،‬أو توفير‬
‫‪jump‬‬
‫‪j‬‬
‫‪list‬‬
‫‪l‬‬
‫الحالية‪.‬‬
‫إنشاء نقطة توقف أثناء تنفيذ‬
‫البرنامج (يتطلب وسيط)‬
‫مساعدة ألمر معين‪.‬‬
‫ضبط ما هو السطر القادم الذي‬
‫يجب تنفيذه‪.‬‬
‫طباعة الشيفرة المصدرية‬
‫المحيطة بالسطر الحالي‪.‬‬
‫‪383‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫األمر‬
‫البرمجة بلغة بايثون‬
‫الوظيفة‬
‫االختصار‬
‫إكمال التنفيذ حتى السطر التالي‬
‫‪next‬‬
‫‪n‬‬
‫‪step‬‬
‫‪s‬‬
‫‪pp‬‬
‫‪pp‬‬
‫طباعة قيمة التعبير‪.‬‬
‫‪ quit‬أو ‪exit‬‬
‫‪q‬‬
‫الخروج من البرنامج‪.‬‬
‫‪return‬‬
‫‪r‬‬
‫إكمال التنفيذ حتى تعيد الدالة‬
‫في الدالة‪ ،‬أو الخروج منها‪.‬‬
‫تنفيذ السطر الحالي‪ ،‬والتوقف‬
‫في أول فرصة ممكنة‪.‬‬
‫ً‬
‫قيمة ما‪.‬‬
‫يمكنك قراءة المزيد عن األوامر السابقة والتعامل مع المنقح عبر توثيق بايثون الرسمي‪.‬‬
‫‪ .7‬الوحدة ‪ :code‬تنقيح الشيفرات من سطر األوامر التفاعلي‬
‫الوح دة ‪ code‬هي إح دى األدوات المفي دة ال تي يمكن اس تخدامها لمحاك اة الم ترجم‬
‫ً‬
‫فرصة لتجربة الشيفرة التي تكتبها‪.‬‬
‫(‪ )interpreter‬التفاعلي‪ ،‬إذ توفر هذه الوحدة‬
‫تفحص الشيفرة باستخدام ِّ‬
‫ُّ‬
‫منقح‪ ،‬يمكن ك إض افة الوح دة ‪ code‬لوض ع نق اط إليق اف‬
‫بدالً من‬
‫ُّ‬
‫كيفية عم ل الش يفرة‪ .‬الوح دة‬
‫لتفحص ومتابع ة‬
‫تنفي ذ البرن امج‪ ،‬وال دخول في الوض ع التف اعلي‬
‫َّ‬
‫‪ code‬هي جزء من مكتبة بايثون القياسية‪.‬‬
‫ٌ‬
‫مفيدة َّ‬
‫ألنها ستمكنك من استخدام م ترجم دون التض حية بالتعقي د واالس تدامة‬
‫هذه الوحدة‬
‫ال تي توفره ا ملف ات البرمج ة‪ .‬فيمكن ك ع بر اس تخدام الوح دة ‪ code‬تجنب اس تخدام‬
‫الدال ة )(‪ print‬في ش يفرتك ألج ل التنقيح‪َّ ،‬‬
‫عملية‪ .‬الس تخدامها في تنقيح‬
‫ألنه ا طريق ة غ ير‬
‫َّ‬
‫‪384‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫الخاص ة بالوح دة ‪ ،code‬وال تي توق ف تنفي ذ‬
‫َّ‬
‫األخط اء‪ ،‬يمكن ك اس تخدام الدال ة )(‪interact‬‬
‫البرن امج عن د اس تدعائها‪ ،‬وت وفر ل ك س طر أوام ر تف اعلي ح تى تتمكن من فحص الوض ع‬
‫الحالي لبرنامجك‪.‬‬
‫ُتك َتب الدالة )(‪ interact‬بالشكل التالي‪:‬‬
‫‪code.interact(banner=None, readfunc=None, local=None,‬‬
‫)‪exitmsg=None‬‬
‫ُت ِّ‬
‫نفذ ه ذه الدال ة حلق ة اق رأ‪-‬قيِّ م‪-‬اطبع (تختص ر إلى ‪ ،REPL‬أي ‪،Read–eval–print loop‬‬
‫وتنش ئ نس خة من الص نف ‪ ،InteractiveConsole‬وال ذي يح اكي س لوك م ترجم‬
‫بايثون التفاعلي‪.‬‬
‫هذه هي المعامالت االختيارية‪:‬‬
‫•‬
‫‪ :banner‬يمكن أن تعطيه سلسلة نصية لتعيين موضع إطالق المترجم‪.‬‬
‫•‬
‫‪ :readfunc‬يمكن استخدامه مثل التابع )(‪.InteractiveConsole.raw_input‬‬
‫•‬
‫‪ :local‬س يعيِّ ن فض اء األس ماء (‪ )namespace‬االفتراض ي لحلق ة الم ترجم‬
‫(‪.)interpreter loop‬‬
‫•‬
‫‪ :exitmsg‬يمكن إعطاؤه سلسلة نصية لتعيين موضع توقف المترجم‪.‬‬
‫مثاًل ‪ ،‬يمكن استخدام المعامل ‪ local‬بهذا الشكل‪:‬‬
‫•‬
‫)(‪ - local=locals‬لفضاء أسماء محلي‬
‫•‬
‫)(‪ - local=globals‬لفضاء أسماء عام‬
‫‪385‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫•‬
‫البرمجة بلغة بايثون‬
‫))(‪ - local=dict(globals(), **locals‬الستخدام ك ل من فض اء األس ماء الع ام‪،‬‬
‫وفضاء األسماء المحلي الحالي‬
‫المعامل ‪ exitmsg‬جديد‪ ،‬ولم يظهر حتى إصدار بايثون ‪ ،3.6‬لذلك إن كنت تس تخدم إص دا ًرا‬
‫ِّ‬
‫فحدثه‪ ،‬أو ال تستخدم المعامل ‪.exitmsg‬‬
‫أقدم‪،‬‬
‫ضع الدالة )(‪ interact‬حيث تريد إطالق المترجم التفاعلي في الشيفرة‪.‬‬
‫ا‪ .‬كيفية استخدام الوحدة ‪code‬‬
‫ً‬
‫رفية يس مى‬
‫لتوض يح كيفي ة اس تخدام الوح دة ‪ ،code‬س نكتب ب‬
‫ُريمج ا عن الحس ابات المص َّ‬
‫محليا‪.‬‬
‫سنعين المعامل المحلي عند القيمة )(‪ locals‬لجعل فضاء األسماء‬
‫‪.balances.py‬‬
‫ًّ‬
‫ّ‬
‫استيراد الوحدة‬
‫‪# code‬‬
‫‪import code‬‬
‫‪bal_a = 2324‬‬
‫‪bal_b = 0‬‬
‫‪bal_c = 409‬‬
‫‪bal_d = -2‬‬
‫]‪account_balances = [bal_a, bal_b, bal_c, bal_d‬‬
‫‪def display_bal():‬‬
‫‪for balance in account_balances:‬‬
‫‪if balance < 0:‬‬
‫"‪print("Account balance of {} is below 0; add funds now.‬‬
‫))‪.format(balance‬‬
‫‪elif balance == 0:‬‬
‫‪386‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪print("Account balance of {} is equal to 0; add funds‬‬
‫"‪soon.‬‬
‫))‪.format(balance‬‬
‫‪else:‬‬
‫‪print("Account balance of {} is above‬‬
‫))‪0.".format(balance‬‬
‫استخدام )(‪ interact‬لبدء المترجم بفضاء أسماء محلي ‪#‬‬
‫))(‪code.interact(local=locals‬‬
‫)(‪display_bal‬‬
‫لق د اس تدعينا الدال ة )(‪ code.interact‬م ع المعام ل )(‪ local=locals‬الس تخدام فض اء‬
‫األسماء المحلي بوصفه قيمة افتراضية داخل حلقة المترجم‪.‬‬
‫ل ُن ِّ‬
‫نفذ البرن امج أعاله باس تخدام األم ر ‪ python3‬إذا لم نكن تعم ل في بيئ ة افتراض ية‪ ،‬أو‬
‫األمر ‪ python‬خالف ذلك‪:‬‬
‫‪python balances.py‬‬
‫بمجرَّ د تنفيذ البرنامج‪ ،‬سنحصل على المخرجات التالية‪:‬‬
‫)‪Python 3.5.2 (default, Nov 17 2016, 17:05:23‬‬
‫‪[GCC 5.4.0 20160609] on linux‬‬
‫‪Type "help", "copyright", "credits" or "license" for more‬‬
‫‪information.‬‬
‫)‪(InteractiveConsole‬‬
‫>>>‬
‫وضع المؤشر في نهاية السطر >>>‪ ،‬كما لو َّ‬
‫سي َ‬
‫أنك في سطر األوامر التفاعلي‪ .‬من هنا‪ ،‬يمكنك‬
‫ُ‬
‫استدعاء الدالة )(‪ print‬لطباعة المتغيرات والدوال وغير ذلك‪:‬‬
‫‪387‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫)‪>>> print(bal_c‬‬
‫‪409‬‬
‫)‪>>> print(account_balances‬‬
‫]‪[2324, 0, 409, -2‬‬
‫))(‪>>> print(display_bal‬‬
‫‪Account balance of 2324 is 0 or above.‬‬
‫‪Account balance of 0 is equal to 0, add funds soon.‬‬
‫‪Account balance of 409 is 0 or above.‬‬
‫‪Account balance of -2 is below 0, add funds now.‬‬
‫‪None‬‬
‫)‪>>> print(display_bal‬‬
‫>‪<function display_bal at 0x104b80f28‬‬
‫نرى َّ‬
‫أنه باستخدام فضاء األسماء المحلي‪ ،‬يمكننا طباعة المتغيرات‪ ،‬واس تدعاء الدال ة‪ .‬يُ ظه ر‬
‫أن الدالة ‪ display_bal‬موجودة في ذاكرة الحاسوب‪.‬‬
‫االستدعاء األخير للدالة )(‪َّ print‬‬
‫بعد أن تنتهي من العمل على المترجم‪ ،‬يمكنك الضغط على ‪ CTRL + D‬في األنظم ة المس تندة‬
‫إلى يونكس‪ ،‬أو ‪ CTRL + Z‬في أنظمة ويندوز لمغادرة سطر األوامر ومتابعة تنفيذ البرنامج‪.‬‬
‫إذا أردت الخروج من سطر األوامر دون تنفي ذ الج زء المتبقي من البرن امج‪ ،‬ف اكتب )(‪،quit‬‬
‫وسيتوقف البرنامج‪.‬‬
‫في المثال التالي‪ ،‬سنستخدم المُ عاملين ‪ banner‬و ‪:exitmsg‬‬
‫استخدم الدالة )(‪ interact‬لبدء المترجم ‪#‬‬
‫)"‪code.interact(banner="Start", local=locals(), exitmsg="End‬‬
‫)(‪display_bal‬‬
‫عند تنفيذ البرنامج‪ ،‬ستحصل على المخرجات التالية‪:‬‬
‫‪Start‬‬
‫‪388‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫>>>‬
‫ي تيح ل ك اس تخدام المعام ل ‪ banner‬تع يين ع َّدة نق اط داخ ل ش يفرتك‪ ،‬م ع الق درة على‬
‫تحدي دها‪ .‬على س بيل المث ال‪ ،‬يمكن أن يك ون ل ديك معام ل ‪ banner‬يطب ع السلس لة النص ية‬
‫"‪ "In for-loop‬م ع معام ل ‪ exmsg‬يطب ع "‪ ،"Out of for-loop‬وذل ك ح تى تع رف مكان ك‬
‫بالضبط في الشيفرة‪.‬‬
‫من هنا‪ ،‬يمكننا اس تخدام الم ترجم مث ل المعت اد‪ .‬بع د كتاب ة ‪ CTRL + D‬للخ روج من الم ترجم‪،‬‬
‫ستحصل على رسالة الخروج‪ ،‬وسيتم تنفيذ الدالة‪:‬‬
‫‪End‬‬
‫‪Account balance of 2324 is 0 or above.‬‬
‫‪Account balance of 0 is equal to 0, add funds soon.‬‬
‫‪Account balance of 409 is 0 or above.‬‬
‫‪Account balance of -2 is below 0, add funds now.‬‬
‫سيتم تنفيذ البرنامج بالكامل بعد الجلسة التفاعلية‪.‬‬
‫بمجرد االنتهاء من استخدام الوحدة ‪ code‬لتنقيح الش يفرة‪ ،‬يجب علي ك إزال ة دوال الوح دة‬
‫‪ code‬وعبارة االستيراد حتى يُ َّ‬
‫نفذ البرنامج مثل المعتاد‪.‬‬
‫‪ .8‬الوحدة ‪ :Logging‬التنقيح بالتسجيل وتتبع األحداث‬
‫الوح دة ‪ logging‬هي ج زء من مكتب ة ب ايثون القياس ية وال تي ت وفر تتبعً ا لألح داث ال تي‬
‫تحصل أثناء تش غيل البرن امج‪ ،‬ويمكنن ا إض افة اس تدعاءات للتس جيل ض من الش يفرة لإلش ارة إلى‬
‫معين‪ .‬تس مح الوح دة ‪ logging‬بالتس جيل ألغ راض استكش اف المش اكل وإص الحها‪،‬‬
‫ح دوث أم ر‬
‫َّ‬
‫وتس جيل األح داث المتعلق ة بتش غيل التط بيق‪ ،‬إض ً‬
‫افة إلى س جل األح داث ال ذي يس ِّجل تف اعالت‬
‫‪389‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫خصوصا لتسجيل األحداث إلى ملف‪.‬‬
‫ً‬
‫المستخدم لتحليلها‪ .‬وتستعمل الوحدة‬
‫تبقي الوح دة ‪ logging‬س جاًل باألح داث ال تي وقعت ض من البرن امج‪ ،‬مم ا يس مح برؤي ة‬
‫ُّ‬
‫التحقق‬
‫المخرجات المتعلقة بأي ح دث ال تي تح دث أثن اء تش غيل البرن امج‪ .‬ق د تك ون معت ا ًدا على‬
‫أن الدال ة ‪ print‬ت وفر طريق ة‬
‫ٌ‬
‫من األح داث باس تخدام الدال ة ‪ print‬في ش يفرتك‪ ،‬وص‬
‫حيح َّ‬
‫أساس ية لمحاول ة تنقيح الش يفرة وح ل المش كالت‪ .‬لكن اس تخدام ‪ print‬لتنقيح البرن امج وتتب ع‬
‫ٌ‬
‫ً‬
‫موازنة مع الوحدة ‪ِّ logging‬‬
‫لعدة أسباب‪:‬‬
‫صعبة صيانته‬
‫عملية التنفيذ وحالة التطبيق هو خيار‬
‫•‬
‫عبا التفري ق بين مخرج ات التنقيح والمخرج ات العادي ة للبرن امج‪ ،‬فس تختلط‬
‫سيصبح ص ً‬
‫المخرجات مع بعضها‪.‬‬
‫•‬
‫ال توج د طريق ة س هلة لتعطي ل ال دوال ‪ print‬عن د اس تخدامها متن اثرة في مواض ع‬
‫مختلفة في الشيفرة‪.‬‬
‫•‬
‫يصعب حذف جميع دوال ‪ print‬عند االنتهاء من التنقيح‪.‬‬
‫•‬
‫بموثوقية عالية‪.‬‬
‫ال يوجد سجل يوضح ما هي معلومات التشخيص واستكشاف ألخطاء‬
‫َّ‬
‫ل ذا من األفض ل أن نعت اد على اس تخدام الوح دة ‪ logging‬في الش يفرة َّ‬
‫ألنه ا أفض ل‬
‫وألن الس جالت‬
‫للتطبيقات التي تتعدى كونها سكربت بايثون قصير‪ ،‬وتوفر طريقة أنسب للتنقيح‪.‬‬
‫َّ‬
‫تعرض سلوك وأخطاء التطبيق على فترة من الزمن‪ ،‬فستحصل على صورة ش املة عمَّ ا يح دث في‬
‫عملية تطوير تطبيقك‪.‬‬
‫ا‪ .‬طباعة رسائل التنقيح إلى الطرفية‬
‫َ‬
‫كنت معتا ًدا على استخدام الدالة ‪ print‬لترى ماذا يحدث في تطبيق ك‪ ،‬فس تكون معت ا ًدا‬
‫إذا‬
‫ً‬
‫على رؤية تطبيق مثل المثال اآلتي الذي يُ ِّ‬
‫صنفا ويُ هيِّ ئ الكائنات فيه‪:‬‬
‫عرف‬
‫‪390‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
class Pizza():
def __init__(self, name, price):
self.name = name
self.price = price
print("Pizza created: {} (${})".format(self.name,
self.price))
def make(self, quantity=1):
print("Made {} {} pizza(s)".format(quantity, self.name))
def eat(self, quantity=1):
print("Ate {} pizza(s)".format(quantity, self.name))
pizza_01 = Pizza("artichoke", 15)
pizza_01.make()
pizza_01.eat()
pizza_02 = Pizza("margherita", 12)
pizza_02.make(2)
pizza_02.eat()
ِّ ُ‫__ الذي ي‬init__ ‫تحتوي الشيفرة السابقة على التابع‬
‫ لك ائن‬price ‫ و‬name ‫عرف المعاملين‬
‫ واآلخ ر باس م‬،‫ إلنش اء البي تزا‬make() ‫ أح دهما باس م‬،‫ ول دى الص نف ت ابعين‬.Pizza ‫من الص نف‬
.‫ بقيم ة ابتدائي ة تس اوي‬quantity ‫ ه ذان التابع ان يقبالن مع اماًل باس م‬:-p ‫ ألك ل البي تزا‬eat()
ِّ
:‫لنشغل البرنامج‬
python pizza.py
:‫سنحصل على المخرجات اآلتية‬
Pizza created: artichoke ($15)
▲
|
391
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫)‪Made 1 artichoke pizza(s‬‬
‫)‪Ate 1 pizza(s‬‬
‫)‪Pizza created: margherita ($12‬‬
‫)‪Made 2 margherita pizza(s‬‬
‫)‪Ate 1 pizza(s‬‬
‫صحيح أننا نستخدم الدالة ‪ print‬لرؤية كيف تعم ل الش يفرة‪ ،‬لكن يمكنن ا اس تخدام الوح دة‬
‫ٌ‬
‫‪ logging‬لفع‬
‫ل ذل‬
‫كب‬
‫داًل منه‬
‫ا‪ .‬ل‬
‫نزل الدال‬
‫ة ‪ print‬الموج‬
‫ودة في الش‬
‫يفرة‪،‬‬
‫ونضع ‪ import logging‬في بداية الملف‪:‬‬
‫‪import logging‬‬
‫‪class Pizza():‬‬
‫‪def __init__(self, name, value):‬‬
‫‪self.name = name‬‬
‫‪self.value = value‬‬
‫…‬
‫المس توى االفتراض ي للتس جيل في وح دة ‪ logging‬ه و ‪( WARNING‬تح ذير) وال ذي ه و‬
‫مس توى أعلى بدرج ة واح دة من ‪( DEBUG‬تنقيح)‪ ،‬ولمَّ ا كنَّا نري د اس تخدام الوح دة ‪logging‬‬
‫للتنقيح في هذا المثال‪ ،‬فعلينا تغي ير الض بط لكي يك ون مس توى التس جيل ه و ‪،logging.DEBUG‬‬
‫وذلك بإضافة السطر اآلتي بعد عبارة االستيراد‪:‬‬
‫‪import logging‬‬
‫)‪logging.basicConfig(level=logging.DEBUG‬‬
‫‪class Pizza():‬‬
‫‪392‬‬
‫|‬
‫▲‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
…
.10 ‫ هي‬DEBUG ‫ وقيم ة المس توى‬،‫ إلى قيم ة رقمي ة ثابت ة‬logging.DEBUG ‫تش ير القيم ة‬
‫ وعلى النقيض من‬،logging.debug() ‫ابع‬
‫ إلى الت‬print ‫دوال‬
‫ع ال‬
‫ِّدل اآلن جمي‬
‫لنب‬
ٌ
‫اص‬
‫ خ‬logging.debug() ‫إن الت ابع‬
َّ ‫ ف‬،‫ ال تي هي قيم ة عددي ة ثابت ة‬logging.DEBUG
‫ وعند التعامل م ع ه ذا الت ابع فيمكنن ا اس تخدام نفس السلس لة النص ية المُ م رَّ رة‬،logging ‫بالوحدة‬
:‫ كما هو موضح أدناه‬print ‫إلى‬
import logging
logging.basicConfig(level=logging.DEBUG)
class Pizza():
def __init__(self, name, price):
self.name = name
self.price = price
logging.debug("Pizza created: {} (${})".format(self.name,
self.price))
def make(self, quantity=1):
logging.debug("Made {} {} pizza(s)".format(quantity,
self.name))
def eat(self, quantity=1):
logging.debug("Ate {} pizza(s)".format(quantity,
self.name))
pizza_01 = Pizza("artichoke", 15)
pizza_01.make()
▲
|
393
‫البرمجة بلغة بايثون‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
pizza_01.eat()
pizza_02 = Pizza("margherita", 12)
pizza_02.make(2)
pizza_02.eat()
:‫ فسنحصل على الناتج اآلتي‬python pizza.py ‫عندما نشغل البرنامج باستخدام األمر‬
DEBUG:root:Pizza created: artichoke ($15)
DEBUG:root:Made 1 artichoke pizza(s)
DEBUG:root:Ate 1 pizza(s)
DEBUG:root:Pizza created: margherita ($12)
DEBUG:root:Made 2 margherita pizza(s)
DEBUG:root:Ate 1 pizza(s)
ً ‫ إض‬DEBUG ‫تمل ك رس ائل التس جيل المس توى األم ني‬
‫ وال تي تش ير إلى‬،root ‫افة إلى الكلم ة‬
‫ م ع هيكلي ة من‬logging ‫ إذ يمكن اس تخدام الوح دة‬،‫مس توى وح دة ب ايثون الخاص ة ب ك‬
‫) مختل ف لك ل وح دة من‬logger( ‫ لذا يمكنك استخدام مس ِّجل‬،‫المسجالت التي لها أسماء مختلفة‬
‫ يمكنن ا إس ناد أك ثر من مس ِّجل معً ا وإعطائه ا‬،‫ على س بيل المث ال‬.‫وح دات ب ايثون الخاص ة ب ك‬
:‫أسماء مختلفة‬
logger1 = logging.getLogger("module_1")
logger2 = logging.getLogger("module_2")
logger1.debug("Module 1 debugger")
logger2.debug("Module 2 debugger")
DEBUG:module_1:Module 1 debugger
DEBUG:module_2:Module 2 debugger
▲
|
394
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫كيفية اس تخدام الوح دة ‪ logging‬لطباع ة الرس ائل إلى الطرفي ة‪ ،‬فلننتق ل إلى‬
‫بع د أن فهمن ا‬
‫َّ‬
‫استخدام الوحدة ‪ logging‬لطباعة الرسائل إلى ملف‪.‬‬
‫ب‪ .‬تسجيل الرسائل إلى ملف‬
‫اله دف الرئيس ي من الوح دة ‪ logging‬هي تس جيل الرس ائل إلى مل ف ب داًل من طباعته ا إلى‬
‫الطرفية‪ ،‬إذ يؤدي وجود ملف يحت وي على البيان ات المُ َّ‬
‫خزن ة على ف ترة زمني ة طويل ة إلى إحص اء‬
‫وتق دير م ا هي التغي يرات ال تي يجب إجراؤه ا على الش يفرة أو البرن امج كك ل‪ .‬يمكنن ا تع ديل‬
‫الت ابع )(‪ logging.basicConfig‬لب دء التس جيل إلى مل ف‪ ،‬وذل ك بتمري ر المعام ل ‪،filename‬‬
‫وفي هذه الحالة سندعو الملف باسم ‪:test.log‬‬
‫‪import logging‬‬
‫)‪logging.basicConfig(filename="test.log", level=logging.DEBUG‬‬
‫‪class Pizza():‬‬
‫‪def __init__(self, name, price):‬‬
‫‪self.name = name‬‬
‫‪self.price = price‬‬
‫‪logging.debug("Pizza created: {} ($‬‬
‫))‪{})".format(self.name, self.price‬‬
‫‪def make(self, quantity=1):‬‬
‫‪logging.debug("Made {} {} pizza(s)".format(quantity,‬‬
‫))‪self.name‬‬
‫‪def eat(self, quantity=1):‬‬
‫‪logging.debug("Ate {} pizza(s)".format(quantity,‬‬
‫‪395‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫))‪self.name‬‬
‫)‪pizza_01 = Pizza("artichoke", 15‬‬
‫)(‪pizza_01.make‬‬
‫)(‪pizza_01.eat‬‬
‫)‪pizza_02 = Pizza("margherita", 12‬‬
‫)‪pizza_02.make(2‬‬
‫)(‪pizza_02.eat‬‬
‫الش يفرة الس ابقة مش ابهة كث يرًا للش يفرة الموج ودة في القس م الس ابق‪ ،‬باس تثناء أنن ا أض فنا‬
‫اس م المل ف ‪ filename‬لتخ زين مخرج ات الس جل‪ .‬وبع د تش غيل الس كربت باس تخدام األم ر‬
‫نشأ ٌ‬
‫‪ python pizza.py‬فمن المفترض أن يُ َ‬
‫ملف جدي ٌد في المجلد الخ اص بن ا باس م ‪.test.log‬‬
‫لنفتح الملف ‪ test.log‬باستخدام ‪( vi‬أو أي محرر تفضله)‪:‬‬
‫‪vi test.log‬‬
‫ُّ‬
‫تفحص محتويات الملف‪ ،‬فسنرى ما يلي‪:‬‬
‫عند‬
‫)‪DEBUG:root:Pizza created: artichoke ($15‬‬
‫)‪DEBUG:root:Made 1 artichoke pizza(s‬‬
‫)‪DEBUG:root:Ate 1 pizza(s‬‬
‫)‪DEBUG:root:Pizza created: margherita ($12‬‬
‫)‪DEBUG:root:Made 2 margherita pizza(s‬‬
‫)‪DEBUG:root:Ate 1 pizza(s‬‬
‫الناتج شبيه بمحتويات الطرفية ال تي رأيناه ا في القس م الس ابق‪ ،‬لكنَّه ا مُ َّ‬
‫خزن ة اآلن في مل ف‬
‫‪ .test.log‬لنع د إلى تع ديل المل ف ‪ pizza.py‬لتع ديل الش يفرة‪ ،‬س نبقي أغلبي ة الش يفرة على‬
‫حالتها‪ ،‬لكننا سنعدل معاملين في كائني ‪ pizza_01‬و ‪:pizza_02‬‬
‫‪396‬‬
‫|‬
‫▲‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
import logging
logging.basicConfig(filename="test.log", level=logging.DEBUG)
class Pizza():
def __init__(self, name, price):
self.name = name
self.price = price
logging.debug("Pizza created: {} ($
{})".format(self.name, self.price))
def make(self, quantity=1):
logging.debug("Made {} {} pizza(s)".format(quantity,
self.name))
def eat(self, quantity=1):
logging.debug("Ate {} pizza(s)".format(quantity,
self.name))
# ‫تعديل معامالت الكائن‬
pizza_01 = Pizza("Sicilian", 18)
pizza_01.make(5)
pizza_01.eat(4)
# ‫تعديل معامالت الكائن‬
pizza_02 = Pizza("quattro formaggi", 16)
pizza_02.make(2)
pizza_02.eat(2)
‫ بع د تش غيل‬.python pizza.py ‫ لنعد تشغيل البرنامج باألمر‬،‫بعد حفظ التعديالت السابقة‬
ِّ ُ‫ بالم‬test.log ‫ لنستعرض محتوى الملف‬،‫البرنامج‬
:‫حرر المفضل لديك‬
▲
|
397
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪vi test.log‬‬
‫وأن األس طر الس ابقة من‬
‫أن هنالك أسطر جديدة ق د أض يفت‪،‬‬
‫َّ‬
‫عندما ننظر إلى الملف‪ ،‬فسنرى َّ‬
‫ً‬
‫موجودة‪:‬‬
‫الماضية ما تزال‬
‫المرة‬
‫َّ‬
‫)‪DEBUG:root:Pizza created: artichoke ($15‬‬
‫)‪DEBUG:root:Made 1 artichoke pizza(s‬‬
‫)‪DEBUG:root:Ate 1 pizza(s‬‬
‫)‪DEBUG:root:Pizza created: margherita ($12‬‬
‫)‪DEBUG:root:Made 2 margherita pizza(s‬‬
‫)‪DEBUG:root:Ate 1 pizza(s‬‬
‫)‪DEBUG:root:Pizza created: Sicilian ($18‬‬
‫)‪DEBUG:root:Made 5 Sicilian pizza(s‬‬
‫)‪DEBUG:root:Ate 4 pizza(s‬‬
‫)‪DEBUG:root:Pizza created: quattro formaggi ($16‬‬
‫)‪DEBUG:root:Made 2 quattro formaggi pizza(s‬‬
‫)‪DEBUG:root:Ate 2 pizza(s‬‬
‫أن هذه المعلومات مفيدة بكل تأكيد‪ ،‬لكن يمكننا أن نجعل السجل مليًئا بالمعلومات‬
‫ٌ‬
‫وصحيح َّ‬
‫بإض افة خاص ية ‪ .LogRecord‬وأهم م ا نري د فعل ه ه و إض افة بص مة وقت قابل ة للق راءة بس هولة‬
‫ال تي تخبرن ا م تى ُأ ِ‬
‫نش ئ الس جل‪ .‬سنض يف ذل ك إلى المعام ل ‪ ،format‬إذا نض ع ‪%(asctime)s‬‬
‫إلض‬
‫افة ال‬
‫وقت‪ ،‬وإلبق‬
‫اء اس‬
‫م المس‬
‫توى (‪ )DEBUG‬فيجب تض‬
‫لة‬
‫مين السلس‬
‫النص ية‪ ،%(levelname)s‬ولإلبق اء على الرس ائل ال تي نطلب من المس جل أن يس جلها‪ ،‬فعلين ا‬
‫تض مين ‪ ،%(message)s‬ك ل سلس لة نص ية من الخاص يات الس ابقة مفص ولة عن بعض ها بنقط تين‬
‫رأسيتين ‪ :‬كما هو ظاهر في الشيفرة أدناه‪:‬‬
‫‪398‬‬
‫|‬
‫▲‬
‫البرمجة بلغة بايثون‬
ِّ ‫ استخدام‬:‫تنقيح الشيفرات‬
‫منقح بايثون‬
import logging
logging.basicConfig(
filename="test.log",
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s"
)
class Pizza():
def __init__(self, name, price):
self.name = name
self.price = price
logging.debug("Pizza created: {} ($
{})".format(self.name, self.price))
def make(self, quantity=1):
logging.debug("Made {} {} pizza(s)".format(quantity,
self.name))
def eat(self, quantity=1):
logging.debug("Ate {} pizza(s)".format(quantity,
self.name))
pizza_01 = Pizza("Sicilian", 18)
pizza_01.make(5)
pizza_01.eat(4)
pizza_02 = Pizza("quattro formaggi", 16)
pizza_02.make(2)
pizza_02.eat(2)
‫ فستحص ل على أس طر‬python pizza.py ‫عن د تش غيل الش يفرة الس ابقة باس تخدام األم ر‬
▲
|
399
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫جدي دة في المل ف ‪ test.log‬ال تي تتض من بص مة ال وقت ومس توى التس جيل (‪ )DEBUG‬والرس ائل‬
‫المرتبطة بها‪:‬‬
‫)‪DEBUG:root:Pizza created: Sicilian ($18‬‬
‫)‪DEBUG:root:Made 5 Sicilian pizza(s‬‬
‫)‪DEBUG:root:Ate 4 pizza(s‬‬
‫)‪DEBUG:root:Pizza created: quattro formaggi ($16‬‬
‫)‪DEBUG:root:Made 2 quattro formaggi pizza(s‬‬
‫)‪DEBUG:root:Ate 2 pizza(s‬‬
‫)‪2017-05-01 16:28:54,593:DEBUG:Pizza created: Sicilian ($18‬‬
‫)‪2017-05-01 16:28:54,593:DEBUG:Made 5 Sicilian pizza(s‬‬
‫)‪2017-05-01 16:28:54,593:DEBUG:Ate 4 pizza(s‬‬
‫‪2017-05-01 16:28:54,593:DEBUG:Pizza created: quattro formaggi‬‬
‫)‪($16‬‬
‫)‪2017-05-01 16:28:54,593:DEBUG:Made 2 quattro formaggi pizza(s‬‬
‫)‪2017-05-01 16:28:54,593:DEBUG:Ate 2 pizza(s‬‬
‫اعتم ا ًدا على احتياجات ك‪ ،‬ربم ا تس تعمل خاص يات ‪ LogRecord‬في ش يفراتك لتخصيص ها‪.‬‬
‫ِّ‬
‫كلي ا على م رور‬
‫تسجيل رسائل التنقيح وغيرها في ملفات منفصلة‬
‫يسهل عليك فهم تطبيقك فهمً ا ً‬
‫ً‬
‫فرصة لتصحيح وتعديل الشيفرات ببصيرة‪.‬‬
‫الزمن‪ ،‬مما يعطيك‬
‫ج‪ .‬جدول بمستويات التسجيل‬
‫يمكن ك إس ناد مس توى أهمي ة إلى الح دث باس تخدام مس تويات التس جيل‪ .‬مس تويات‬
‫دءا من‬
‫ً‬
‫التس جيل هي قيم عددي ة (ثابت ة)‪ ،‬وال تي تك ون من مض اعفات الع دد ‪ ،10‬ب‬
‫ً‬
‫أيض ا تعري ف المس تويات‬
‫المس توى ‪ NOTSET‬ال ذي يه يئ المس ِّجل بقيم ة عددي ة تس اوي ‪ .0‬يمكن ك‬
‫عرفت مستوى بقيمة عددية مساوية للقيمة العددية لمس توى موج ود مس ً‬
‫َ‬
‫بقا‪،‬‬
‫الخاصة بك‪ ،‬لكن إذا‬
‫فستعيد كتابة االسم المرتبط بتلك القيمة‪.‬‬
‫‪400‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫ظه ر الج دول اآلتي مختل ف مس تويات التس جيل م ع القيم العددي ة المرتبط ة به ا‪ ،‬وم ا هي‬
‫يُ ِ‬
‫الدالة التي يمكن استعمالها الستدعاء المستوى‪ ،‬وألي مستوى من الرسائل تستخدم‪:‬‬
‫المستوى‬
‫القيمة العددية‬
‫الغرض‬
‫الدالة‬
‫‪CRITICAL‬‬
‫‪50‬‬
‫)(‪logging.critical‬‬
‫‪ERROR‬‬
‫‪40‬‬
‫)(‪logging.error‬‬
‫عرض خطأ جاد‪.‬‬
‫‪WARNING‬‬
‫‪30‬‬
‫)(‪logging.warning‬‬
‫اإلشارة أن شيًئ ا غير متوقع قد‬
‫‪INFO‬‬
‫‪20‬‬
‫)(‪logging.info‬‬
‫‪DEBUG‬‬
‫‪10‬‬
‫)(‪logging.debug‬‬
‫عرض خطأ جاد‪ ،‬وقد ال يكون‬
‫البرنامج قاباًل لالستخدام‬
‫بعده‪.‬‬
‫حدث أو قد يحدث‪.‬‬
‫التأكيد أن األمور تسير على ما‬
‫يرام‪.‬‬
‫عرض معلومات تنقيحية‪.‬‬
‫تضبط وحدة ‪ logging‬المستوى االفتراض ي إلى ‪ ،WARNING‬ل ذا ُ‬
‫ستس َّجل رس ائل ‪WARNING‬‬
‫و ‪ ERROR‬و ‪ CRITICAL‬افتراض ًيا‪ .‬ففي المث ال اآلتي س نعدل الض بط لإلش ارة لتض مين‬
‫مستوى ‪:DEBUG‬‬
‫)‪logging.basicConfig(level=logging.DEBUG‬‬
‫يمكن ك التع رُّ ف على المزي د من األوام ر والتعام ل معه ا ب االطالع على توثي ق‬
‫‪ logging‬الرسمي‪.‬‬
‫‪401‬‬
‫|‬
‫▲‬
‫تنقيح الشيفرات‪ :‬استخدام ِّ‬
‫منقح بايثون‬
‫البرمجة بلغة بايثون‬
‫‪ .9‬خالصة الفصل‬
‫عملي ة التنقيح هي خط وة مهم ة في جمي ع مش اريع التط وير البرمجي ة‪ .‬وي وفر لن ا ِّ‬
‫منقح‬
‫بايثون ‪ pdb‬بيئة تنقيح تفاعلية يمكن استخدامها مع أي برنامج بايثون نكتبه‪ .‬باستفادتنا للميزات‬
‫التي تسمح لنا بتوقف عمل البرنامج مؤق ًت ا‪ ،‬وإلق اء نظ رة على المتغ يرات‪ ،‬وإكم ال تنفي ذ البرن امج‬
‫خط ً‬
‫وة بخط وة‪ ،‬مم ا يمكنن ا من فهم م اذا يفع ل البرن امج بالتفص يل ويس اعدنا على اكتش اف العل ل‬
‫وإصالح المشاكل المنطقية‪.‬‬
‫لتفحص الش يفرة خط ً‬
‫ُّ‬
‫وة بخط وة‬
‫ُتس تخ َدم الوح دة ‪ code‬إلطالق س طر األوام ر التف اعلي‬
‫بقص د فهم س لوكها‪ ،‬وتع ديل الش يفرة إن ل زم األم ر‪ .‬لق راءة المزي د ح ول ه ذا الموض وع‪ ،‬يمكن ك‬
‫مطالعة التوثيق الرسمي للوحدة ‪.code‬‬
‫تساعد الوحدة ‪– logging‬ال تي هي ج زء من مكتب ة ب ايثون القياس ية– بتتب ع األح داث ال تي‬
‫تحصل أثناء تش غيل البرن امج‪ ،‬ويمكن إخ راج ه ذه األح داث إلى ملف ات منفص لة للس ماح بتتب ع م ا‬
‫يحدث عن دما تعم ل الش يفرة‪ .‬وه ذا ي وفر لن ا الفرص ة لتنقيح الش يفرة اعتم ا ًدا على فهمن ا لمختل ف‬
‫األحداث التي تطرأ أثناء تشغيل البرنامج على فترةٍ من الزمن‪.‬‬
‫‪402‬‬
‫|‬
‫▲‬
‫‪22‬‬
‫إصدارات بايثون‪:‬‬
‫بايثون ‪ 3‬مقابل‬
‫بايثون ‪2‬‬
‫‪403‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫قبل أن ننظر إلى إمكانيات إصدارَ ي بايثون ‪ 2‬وبايثون ‪( 3‬مع االختالفات البرمجي ة الرئيس ية‬
‫بينهما) ‪ ،‬فلننظر إلى لمحة تاريخية عن اإلصدارات الرئيسية الحديثة من بايثون‪.‬‬
‫‪ .1‬بايثون ‪2‬‬
‫ُن ِش رَ ه ذا اإلص دار في أواخ ر ع ام ‪ ،2000‬وأص بحت ب ايثون ‪ 2‬لغ ة برمج ة ش املة موازن ًة‬
‫باإلص دارات ال تي تس بقها وذل ك بع د تط بيق اق تراح ‪،)Python Enhancement Proposal ( PEP‬‬
‫مواصفة (‪ )specification‬تقني ٌة ت ِّ‬
‫ٌ‬
‫يزات‬
‫ٍ‬
‫وفر معلوم ات إلى أعض اء مجتم ع ب ايثون أو تص ف م‬
‫وهو‬
‫يزات برمجي ة جدي دة مث ل‬
‫ٍ‬
‫جدي دة في اللغ ة‪ .‬باإلض افة إلى ذل ك‪ ،‬تض منت ب ايثون ‪ 2‬م‬
‫"‪ "cycle-detecting garbage collector‬ألتمتة عملية إدارة الذاكرة‪ ،‬وزيادة دعم يونيكود لت دعم‬
‫اللغة جميع المح ارف المعياري ة …إلخ‪ .‬وأثن اء عملي ة تط وير ب ايثون ‪ 2‬أض يفت م يزات جدي دة بم ا‬
‫في ذل ك توحي د األن واع واألص ناف في ب ايثون في بني ة هيكلي ة وحي دة (وذل ك في إص دار ‪2.2‬‬
‫من بايثون)‪.‬‬
‫‪ .2‬بايثون ‪3‬‬
‫ي ُن ِش ر في‬
‫تع ّد بايثون ‪ 3‬مستقبل لغة بايثون وهي قيد التطوير من اللغة‪ ،‬وه ذا إص دارٌ رئيس ٌ‬
‫أواخر عام ‪ 2008‬إلصالح بعض المشاكل الجوهرية في تصميم اإلصدارات السابقة من اللغ ة‪ ،‬وك ان‬
‫التركيز أثناء تطوير بايثون ‪ 3‬هو تحسين الشيفرات التي تبنى عليها اللغ ة وح ذف التك رارات‪ ،‬مم ا‬
‫معينة‪.‬‬
‫أن هنالك طريقة وحيدة فقط إلنجاز مهمَّ ة‬
‫َّ‬
‫يعني َّ‬
‫التع ديالت األساس ية ال تي ح دثت في ب ايثون ‪ 3.0‬تتض من تغي ير التعليم ة ‪ print‬إلى دال ة‬
‫مُ ضمَّ نة باللغة‪ ،‬وتحسين قسمة األعداد الصحيحة‪ ،‬وتوفير دعم إضافي ليونيكود‪.‬‬
‫‪404‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫أن على‬
‫في البداية‪ ،‬انتشرت بايثون ‪ 3‬ببطء نتيج ًة لع دم توافقيته ا م ع ب ايثون ‪ ،2‬مم ا يع ني َّ‬
‫المستخدمين اختي ار م ا ه و اإلص دار ال ذي عليهم اس تخدامه‪ .‬باإلض افة إلى ذل ك‪ ،‬ك انت الكث ير من‬
‫المكتب ات البرمجي ة متاح ًة فق ط لب ايثون ‪ ،2‬لكن بع د تقري ر فري ق تط وير ب ايثون ‪َّ 3‬‬
‫أنه يجب أن‬
‫التخلي عن دعم ب ايثون ‪ ،2‬فب دأت عملي ة تحوي ل المكتب ات إلى ب ايثون ‪ .3‬يمكنن ا معرف ة زي ادة‬
‫االعتماد على بايثون ‪ 3‬من خالل عدد الحزم البرمجية التي ت دعم ب ايثون ‪ ،3‬وال تي هي (في وقت‬
‫كتابة هذا الكتاب) ‪ 339‬من أصل ‪ 360‬من أشهر الحزم‪.‬‬
‫‪ .3‬بايثون ‪2.7‬‬
‫ُأ‬
‫بع د إص دار ب ايثون ‪ 3.0‬في ‪ ،2008‬ص دِ رَ ت نس خة ب ايثون ‪ 2.7‬في تم وز ‪ 2010‬وهي آخ ر‬
‫َّ‬
‫ممه ًدا أم ام مس تخدمي‬
‫إص دار من سلس لة ‪ ،2.x‬الغ رض من إص دار ب ايثون ‪ 2.7‬ه و جع ل الطري ق‬
‫ب ايثون ‪ 2.x‬لتحوي ل ب رامجهم إلى ب ايثون ‪ 3‬بتوف ير بعض التوافقي ة بينهم ا‪ .‬وه ذه التوافقي ة‬
‫حس نة في ‪ 2.7‬مث ل ‪ unittest‬ألتمت ة االختب ارات‪ ،‬و ‪argparse‬‬
‫تض منت دعم بعض الوح دات المُ ّ‬
‫لتفس ير خي ارات س طر األوام ر‪ ،‬وبعض الفئ ات في ‪ .collections‬ولخصوص ية ب ايثون ‪2.7‬‬
‫ولكونه ا جس رًا واص اًل بين اإلص دارات القديم ة من ب ايثون ‪ 2‬وبين ب ايثون ‪ ،3.0‬فأص بحت خي ا ًرا‬
‫شائعً ا بين المبرمجين بسبب توافقيتها مع الكثير من المكتبات‪.‬‬
‫ً‬
‫عادة إلى إص دار ب ايثون ‪َّ 2.7‬‬
‫ألنه أك ثر إص دار‬
‫عندما نتحدث اليوم عن بايثون ‪ ،2‬فنحن نشير‬
‫مستخدم؛ لكنه يُ ع ُّد َّ‬
‫أنه إصدارٌ قديم‪ ،‬وسيتوقف تطويره (التطوير الح الي ه و إص الح العل ل فق ط)‬
‫تمامً ا في ‪.2020‬‬
‫‪405‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫‪ .4‬االختالفات األساسية بين اإلصدارات‬
‫أن بايثون ‪ 2.7‬وب ايثون ‪ 3‬تتش اركان في الكث ير من األش ياء‪ ،‬لكن ال يج در ب ك أن‬
‫بغض النظر َّ‬
‫أنهم ا متماثلت ان ويمكن تب ديل الش يفرات بينهم ا‪ .‬ورغم َّ‬
‫تظن َّ‬
‫أنك تس تطيع كتاب ة ش يفرات جي دة‬
‫أن هنال ك بعض االختالف ات في بني ة‬
‫وب رامج مفي دة في ِّ‬
‫أي إص دار منهم ا‪ ،‬لكن من المهم أن تفهم َّ‬
‫الش يفرات وفي طريق ة تفس يرها‪ .‬س أعرض هن ا بعض األمثل ة‪ ،‬لكن علي ك أن تعلم َّ‬
‫أنك س تواجه‬
‫المزيد من االختالفات أثناء مسيرة تعلمك لبايثون‪.‬‬
‫ا‪print .‬‬
‫في ب ايثون ‪ُ ،2‬تعامَ ل ‪ print‬معامل ة التعليم ات البرمجي ة (‪ )statement‬ب داًل من كونه ا دال ة‪،‬‬
‫ً‬
‫ارتباكا‪ ،‬إذ تتطلب الكثير من األمور داخل بايثون تمرير وس ائط (‪ )arguments‬بين‬
‫وهذا كان يثير‬
‫فتحت مُ ِّ‬
‫َ‬
‫فسر بايثون ‪ 2‬لطباعة " ‪،"Sammy the Shark is my favorite sea creature‬‬
‫قوسين‪ ،‬إذا‬
‫فستكتب التعليمة ‪ print‬اآلتية‪:‬‬
‫"‪print "Sammy the Shark is my favorite sea creature‬‬
‫أمَّ ا في ب ايثون ‪ ،3‬فس ُتعامَ ل )(‪ print‬معامل ة ال دوال‪ ،‬ل ذا لطباع ة السلس لة النص ية الس ابقة‪،‬‬
‫فيمكننا استخدام شكل استدعاء الدوال التقليدي كما يلي‪:‬‬
‫)"‪print("Sammy the Shark is my favorite sea creature‬‬
‫ه ذا التع ديل جع ل من البني ة اللغويَّ ة في ب ايثون موح ً‬
‫دة وس َّهاًل من التب ديل بين مختل ف‬
‫أن الدالة )(‪ print‬متوافقة مع بايثون ‪ ،2.7‬لذا س تعمل ش يفرات‬
‫دوال الطباعة فيها‪ .‬يجدر بالذكر َّ‬
‫بايثون التي تستعمل )(‪ print‬عماًل‬
‫ً‬
‫أي اإلصدارَين‪.‬‬
‫صحيحا في ِّ‬
‫‪406‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫ب‪ .‬قسمة األعداد الصحيحة‬
‫أي ع ددٍ تكتب ه دون فواص ل عش رية س ُيعامَ ل على َّ‬
‫أنه من الن وع ‪،integer‬‬
‫في ب ايثون ‪ُّ ،2‬‬
‫كالية عن دما تح اول قس مة األع داد الص حيحة على بعض ها‪ ،‬فتتوق ع في بعض األحي ان‬
‫ت أتي اإلش‬
‫َّ‬
‫ً‬
‫أيض ا باألع داد ذات الفاص لة [‪ )]float‬كم ا في العملي ة‬
‫حص ولك على ع ددٍ عش ري (تس مى‬
‫الرياضية التالية‪:‬‬
‫‪5 / 2 = 2.5‬‬
‫العملية التي‬
‫لكن األعداد الصحيحة في بايثون ‪ 2‬لن تتحوَّ ل إلى أعداد عشريَّ ة عندما تتطلب‬
‫َّ‬
‫َّ‬
‫انبي معام ل القس مة ‪ /‬ع ددين‬
‫ُتج رَ ى عليه ا ذل ك‪ .‬عن دما يك ون الع ددان الموج ودان على ج َ‬
‫عملية القس م وس ُتنتِج ع د ًدا عش ريً ا إال َّ‬
‫ُ‬
‫أنه ا س ُتعيد الع دد الص حيح‬
‫فستجري بايثون ‪2‬‬
‫صحيحين‪،‬‬
‫َّ‬
‫األص غر أو المس اوي للن اتج‪ ،‬وه ذا يع ني َّ‬
‫َ‬
‫كتبت ‪ 5 / 2‬فس ُتعيد ب ايثون ‪ 2.7‬الع دد الص حيح‬
‫أنه ل و‬
‫األصغر أو المساوي للعدد ‪ ،2.5‬وهو في هذه الحالة ‪:2‬‬
‫‪a = 5 / 2‬‬
‫‪print a‬‬
‫‪2‬‬
‫إلع ادة ع دد عش ري‪ ،‬فيجب إض افة فواص ل عش ريَّ ة إلى األرق ام ال تي س ُتجري عليه ا عملي ة‬
‫القسمة كما في ‪ 5.0 / 2.0‬لكي تحص ل على النتيج ة المنطقي ة ‪ .2.5‬أم ا في ب ايثون ‪ ،3‬فقس مة‬
‫األعداد الصحيحة أصبحت كما نتوقع‪:‬‬
‫‪a = 5 / 2‬‬
‫‪# 2.5‬‬
‫‪print a‬‬
‫‪407‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫َ‬
‫أردت تق ريب ن اتج القس مة فاس تخدم‬
‫يمكن ك اس تخدام ‪ 5.0 / 2.0‬إلع ادة ‪ ،2.5‬لكن إن‬
‫المعامل ‪ //‬الموجود في بايثون ‪ ،3‬كاآلتي‪:‬‬
‫‪a = 5 // 2‬‬
‫‪print a‬‬
‫‪2‬‬
‫هذا التعديل في بايثون ‪ 3‬جعل من قسمة األعداد الصحيحة أمرًا سهاًل ‪ ،‬لكن ه ذه الم يزة غ ير‬
‫متوافقة مع بايثون ‪.2.7‬‬
‫ج‪ .‬دعم محارف يونيكود‬
‫ٌ‬
‫سلسلة من المحارف)‪،‬‬
‫عندما تتعامل لغات البرمجة مع السالسل النصية ( ‪ ،strings‬والتي هي‬
‫فهي تفعل ذلك بطرائق مختلفة لكي تتمكن الحواسيب من تحويل األعداد إلى أحرف ورموز‪.‬‬
‫تس تعمل ب ايثون ‪ 2‬مح ارف ‪ ASCII‬افتراض ًيا‪ ،‬ل ذا عن دما تكتب "!‪Sammy‬‬
‫‪"Hello,‬‬
‫فس تتعامل ب ايثون ‪ 2‬م ع السلس لة النص ية على َّ‬
‫أنه ا مجموع ٌة من مح ارف ‪ ،ASCII‬وال تي هي‬
‫ٌ‬
‫أن مح ارف ‪ ASCII‬هي طريق ة غ ير عملي ة لترم يز المح ارف‬
‫مح‬
‫دودة لح والي مئتَي مح رف‪ ،‬أي َّ‬
‫خصوصا المحارف غير الالتينية (مث ل العربي ة مثال)‪ .‬إن أردت اس تخدام ترم يز مح ارف يونيك ود‬
‫ً‬
‫(‪ )Unicode‬ال ذي ي دعم أك ثر من ‪ 128000‬مح رف ت ابع للكث ير من اللغ ات والرم وز‪ ،‬فعلي ك أن‬
‫تكتب "!‪ u"Hello, Sammy‬إذ ُتشير السابقة ‪ u‬إلى ‪.Unicode‬‬
‫تس تعمل ب ايثون ‪ 3‬مح ارف يونيك ود (‪ )Unicode‬افتراض يا‪ ،‬مم ا ي ِّ‬
‫وفر علي ك بعض ال وقت‬
‫ً‬
‫أثناء التطوير‪ ،‬ويمكن ك كتاب ة وع رض ع دد أك بر بكث ير من المح ارف في برنامج ك بس هولة‪ .‬ي دعم‬
‫يونيكود الكثير من المحارف بما في ذل ك الوج وه التعبيري ة (‪ ،)emojis‬واس تعمالها ترم يز مح ارف‬
‫‪408‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫أن‬
‫أن األجه زة المحمول ة س تكون مدعوم ًة في مش اريعك‬
‫تلقائي ا‪ .‬إذا كنت تحب َّ‬
‫افتراض ي يع ني َّ‬
‫ً‬
‫ً‬
‫متوافقة مع بايثون ‪ 2‬فضع الحرف ‪ u‬قبل السالسل النصية‪.‬‬
‫تكون شيفرات بايثون ‪ 3‬التي تكتبها‬
‫د‪ .‬استمرار التطوير‬
‫أن إص دار ب ايثون‬
‫الفارق الرئيسي بين بايثون ‪ 3‬وبايثون ‪ 2‬ليس في البني ة اللغوي ة وإنم ا في َّ‬
‫الح لمزي دٍ من العل ل‪.‬‬
‫ٍ‬
‫‪ 2.7‬توقف دعم ه في ‪ ،2020‬وسيس تمر تط وير ب ايثون ‪ 3‬بم‬
‫يزات جدي دة وإص ٍ‬
‫تخصيص ا أبس ط إلنش اء األص ناف‪ ،‬وطريق ًة أوض ح للتعام ل‬
‫ً‬
‫التطويرات األخ يرة في اللغ ة تتض من‬
‫أن المط ورين يمكن أن يعتم دوا على اللغ ة‪،‬‬
‫م ع المص فوفات… االس تمرار بتط وير ب ايثون ‪ 3‬يع ني َّ‬
‫أن المش اكل ال تي ق د تح دث فيه ا س ُت َحل في ف ترةٍ قريب ة‪ ،‬ويمكن أن تص بح ال برامج‬
‫وسيطمئنون َّ‬
‫أكثر كفاءة بإضافة المزيد من الميزات للغة‪.‬‬
‫‪ .5‬نقاط أخرى يجب أخذها بالحسبان‬
‫عليك أن تضع النقاط اآلتية بالحسبان عندما تبدأ مشوار البرمجة بلغة بايثون‪ ،‬أو عندما تبدأ‬
‫ِّ‬
‫َ‬
‫معين‪،‬‬
‫روع‬
‫تفكر بمش‬
‫كنت تأم ل بتعلم اللغ ة دون أن‬
‫بتعلم لغ ة ب ايثون بع د تعلم ك لغيره ا‪ .‬إذا‬
‫َّ‬
‫ٍ‬
‫فأنص حك ب التفكير بمس تقبل ب ايثون‪ ،‬فسيس تمر تط وير ودعم ب ايثون ‪ 3‬بينم ا س يوقف دعم‬
‫كنت ُت ِّ‬
‫َ‬
‫خطط لالنض مام لفري ق تط وير‬
‫ب ايثون ‪ 2.7‬عمَّ ا ق ريب (إن لم يكن ق د توق ف ‪ .) D-:‬أمَّ ا إذا‬
‫أحد المشاريع‪ ،‬فعليك أن تنظر ما هو إصدار بايثون المستخدم فيه‪ ،‬وكيف ي ؤدي اختالف اإلص دار‬
‫إلى اختالف طريق ة تعامل ك م ع الش يفرات‪ ،‬وإذا م ا ك انت المكتب ات البرمجي ة المس تعملة في‬
‫ً‬
‫مدعومة في مختلف اإلصدارات‪ ،‬وما هي تفاصيل المشروع نفسه‪.‬‬
‫المشروع‬
‫إذا كنت ُت ِّ‬
‫فكر بب دء أح د المش اريع‪ ،‬فيج در ب ك أن تنظ ر م ا هي المكتب ات المت وفرة وم ا هي‬
‫ً‬
‫توافقية أق ل م ع‬
‫األولية من ب ايثون ‪ 3‬له ا‬
‫سابقا‪ ،‬اإلص دارات‬
‫إصدارات بايثون المدعومة‪ .‬وكما قلنا‬
‫َّ‬
‫َّ‬
‫‪409‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫المكتب ات المبني ة لب ايثون ‪ ،2‬لكن الكث ير منه ا ق د ج رى تحويل ه إلى ب ايثون ‪ ،3‬وسيس تمر ذل ك في‬
‫السنوات األربع المقبلة‪.‬‬
‫‪ .6‬ترحيل شيفرة بايثون ‪ 2‬إلى بايثون ‪3‬‬
‫بع د أن تعرفن ا على إص دارات ب ايثون والف روق الجوهري ة فيم ا بينه ا‪ ،‬س نتعلم اآلن أفض ل‬
‫آليات وممارس ات ترحي ل الش يفرات من ب ايثون ‪ 2‬إلى ب ايثون ‪ ،3‬وم ا إن ك ان علي ك جع ل الش يفرة‬
‫متوافقة مع كال اإلصدارين‪.‬‬
‫أن اإلصدار ‪ 2‬من بايثون صدر عام ‪ُ 2000‬لي ِّ‬
‫ً‬
‫حقبة جدي ً‬
‫دة من التط وير تق وم على‬
‫دشن‬
‫وجدنا َّ‬
‫الش فافية والش مولية‪ ،‬إذ ش مل ه ذا اإلص دار العدي د من الم يزات البرمجي ة‪ ،‬واس تمر في إض افة‬
‫المزيد طوال مدة تطويره‪.‬‬
‫حالي ا‪ ،‬فج اء في أواخ ر‬
‫يُ ع ُّد إصدار بايثون ‪ 3‬مستقبل بايثون‪ ،‬وهو إصدار اللغة قي د التط وير‬
‫ً‬
‫عام ‪ ،2008‬ليعالج العديد من عيوب التصميم الداخلية ويُ ِّ‬
‫أن اعتماد بايثون ‪ 3‬ك ان بطيًئا‬
‫بيد َّ‬
‫عدلها‪ْ .‬‬
‫بسبب عدم توافقه مع بايثون ‪.2‬‬
‫في خض م ذل ك‪ ،‬ج اء اإلص دار ب ايثون ‪ 2.7‬في ع ام ‪ 2010‬ليك ون آخ ر إص دارات ب ايثون ‪2.x‬‬
‫ولي ِّسهل على مستخدمي ب ايثون ‪ 2.x‬االنتق ال إلى ب ايثون ‪ 3‬من خالل توف ير ق در من التواف ق بين‬
‫ُ‬
‫االثنتين‪ ،‬فهذا هو الهدف األساسي من إطالقه‪.‬‬
‫ا‪ .‬ابدأ ببايثون ‪2.7‬‬
‫أن ش يفرة‬
‫لالنتق ال إلى ب ايثون ‪ ،3‬أو ل دعم ب ايثون ‪ 2‬وب ايثون ‪ 3‬معً ا‪ ،‬يجب علي ك التأك د من َّ‬
‫بايثون ‪ 2‬متوافقة تمامً ا مع بايثون ‪.2.7‬‬
‫‪410‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫يعم ل العدي د من المط ورين حص ريًا بش يفرات ب ايثون ‪ ،2.7‬أمَّ ا الم برمجون ال ذي يعمل ون‬
‫أن الشيفرة تعمل جي ًدا مع بايثون ‪ ،2.7‬وتتوافق معه‪.‬‬
‫بشيفرات أقدم‪ ،‬فعليهم أن يتأكدوا من َّ‬
‫ُّ‬
‫األهمية َّ‬
‫ألنه اإلص دار الوحي د من ب ايثون ‪2‬‬
‫التأكد من توافق الشيفرة مع ب ايثون ‪ 2.7‬أم رٌ ب الغ‬
‫َّ‬
‫الذي ما يزال قيد الصيانة‪ُ ،‬‬
‫وت َّ‬
‫صح ُح ثغراته (قد توقف دعمه في وقت قراءت ك له ذا الكت اب)‪ .‬ف إذا‬
‫كنت تعم ل بإص دار س ابق من ب ايثون ‪ ،2‬فس تجد نفس ك تتعام ل م ع مش كالت في ش يفرة لم تع د‬
‫ً‬
‫أيض ا بعض األدوات ال تي ِّ‬
‫تس هل ترحي ل الش يفرة‪ ،‬مث ل‬
‫مدعوم ة‪ ،‬ولم تع د ثغراته ا ُتص َّحح‪ .‬هن اك‬
‫الحزم ة ‪ Pylint‬ال تي تبحث عن األخط اء البرمجي ة‪ ،‬لكن ال ت دعمها إص دارات ب ايثون الس ابقة‬
‫لإلصدار ‪.2.7‬‬
‫من المهم أن تض ع في حس بانك َّ‬
‫أن ب ايثون ‪ 2.7‬م ا زالت قي د ال دعم والص يانة في‬
‫أنه رغم َّ‬
‫الوقت الحالي‪ ،‬إال َّ‬
‫أنها ستموت في النهاية‪ .‬س تجد في ‪ PEP 373‬تفاص يل الج دول الزم ني إلص دار‬
‫ح ِّدد في ع ام ‪( 2020‬يحتم ل أن‬
‫إن أج ل ب ايثون ‪ُ 2.7‬‬
‫بايثون ‪ ،2.7‬وفي وقت ترجم ة ه ذا الكت اب‪ ،‬ف َّ‬
‫تكون قد ماتت وأنت تقرأ هذه السطور ‪.) (-:‬‬
‫ب‪ .‬االختبار‬
‫اختب ار الش يفرة ج ٌ‬
‫ي من عملي ة ترحي ل ش يفرة ب ايثون ‪ 2‬إلى ب ايثون ‪ .3‬ف إذا كنت‬
‫زء أساس ٌّ‬
‫ُّ‬
‫ً‬
‫أن أدوات االختب ار ال تي‬
‫أيض ا‬
‫تعم ل على أك ثر من إص دار واح د من ب ايثون‪ ،‬فعلي ك‬
‫التحقق من َّ‬
‫ُّ‬
‫للتأكد من َّ‬
‫أنها تعمل كما هو متوقع‪.‬‬
‫تستخدمها تغطي جميع اإلصدارات‬
‫يمكنك إضافة حاالت ب ايثون التفاعلي ة (‪ )interactive Python cases‬إلى السالس ل النص ية‬
‫التوثيقية (‪ )docstrings‬الخاص ة بكاف ة ال دوال والتواب ع واألص ناف والوح دات ثم اس تخدام‬
‫َّ‬
‫جزءا من عملية االختبار‪.‬‬
‫ً‬
‫الوحدة ‪ doctest‬المُ ضمَّ نة للتحقق من عملها كما هو موضح إذ يع ُّد ذلك‬
‫‪411‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫إلى جانب ‪ ،doctest‬يمكنك استخدام الحزمة ‪ package.py‬لتتبع وحدة االختبار‪ .‬ستراقب‬
‫هذه األداة برنامجك وتحدد األجزاء التي ُت ِّ‬
‫نفذها من الشيفرة‪ ،‬واألج زاء ال تي يمكن تنفي ذها ولكن‬
‫لم ُت َّ‬
‫نفذ‪ .‬يمكن أن تطب ع ‪ Cover.py‬تقري رًا في س طر األوام ر‪ ،‬أو تنتج مس تند ‪ُ .HTML‬تس تخدم‬
‫ع ً‬
‫ُ‬
‫اخت ِب رت‪ ،‬واألج زاء ال تي‬
‫ادة لقي اس فعالي ة االختب ارات‪ ،‬إذ توض ح األج زاء من الش يفرة ال تي‬
‫ختبر‪.‬‬
‫لم ُت َ‬
‫ذكر أنه ليس عليك اختبار كل شيء‪ ،‬لكن َّ‬
‫َت َّ‬
‫أي شيفرة غامض ة أو غ ير عادي ة‪.‬‬
‫تأكد من تغطية ّ‬
‫للحصول على أفضل النتائج‪ ،‬يُ نصح أن تشمل التغطية ‪ ٪80‬من الشيفرة‪.‬‬
‫‪ .7‬تعرف على االختالفات بين بايثون ‪ 2‬و بايثون ‪3‬‬
‫ِّ‬
‫سيمكنك التعرُّ ف على االختالف ات بين ب ايثون ‪ 2‬و ب ايثون ‪ 3‬من اس تخدام الم يزات الجدي دة‬
‫المتاحة‪ ،‬أو التي ستكون متاحة في بايثون ‪.3‬‬
‫ً‬
‫ً‬
‫أيض ا مراجع ة توثي ق‬
‫مسبقا إلى بعض االختالفات الرئيسية بين اإلصدارين‪ ،‬ويمكنك‬
‫تطرقنا‬
‫بايثون الرسمي لمزيد من التفاصيل‪.‬‬
‫عند البدء في ترحيل الشيفرة‪ ،‬فهناك بعض التغييرات في الصياغة عليك تعديلها فوريً ا‪.‬‬
‫•‬
‫‪ :Print‬حلت الدالة )(‪ print‬في بايثون ‪ 3‬مكان التعليمة ‪ print‬في بايثون ‪.2‬‬
‫بايثون ‪# 2‬‬
‫"!‪print "Hello, World‬‬
‫بايثون ‪# 3‬‬
‫)"!‪print("Hello, World‬‬
‫‪412‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫•‬
‫البرمجة بلغة بايثون‬
‫ً‬
‫دالة تسمح بتمرير متغيرات محلية‬
‫تغيرت التعليمة ‪ exec‬في بايثون ‪ 2‬وأصبحت‬
‫‪َّ :exec‬‬
‫(‪ )locals‬وعامة (‪ )globals‬صريحة في بايثون ‪.3‬‬
‫بايثون ‪# 2‬‬
‫‪# 1‬‬
‫‪exec code‬‬
‫‪# 2‬‬
‫‪exec code in globals‬‬
‫‪# 3‬‬
‫)‪exec code in (globals, locals‬‬
‫بايثون ‪# 3‬‬
‫•‬
‫‪# 1‬‬
‫)‪exec(code‬‬
‫‪# 2‬‬
‫)‪exec(code, globals‬‬
‫‪# 3‬‬
‫)‪exec(code, globals, locals‬‬
‫‪ /‬و ‪ُ ://‬تج ِري ب ايثون ‪ 2‬القس مة التقريبي ة (‪ )floor division‬بالعام ل ‪ ،/‬بينم ا تخص ص‬
‫بايثون ‪ 3‬العامل ‪ //‬إلجراء القسمة التقريبية‪.‬‬
‫بايثون ‪# 2‬‬
‫‪5 / 2 = 2‬‬
‫بايثون ‪# 3‬‬
‫‪5 / 2 = 2.5‬‬
‫‪5 // 2 = 2‬‬
‫الستخدام هذين العاملين في بايثون ‪ ،2‬استورد ‪ division‬من الوحدة __‪:__future‬‬
‫‪from __future__ import division‬‬
‫‪413‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫•‬
‫البرمجة بلغة بايثون‬
‫‪ :raise‬في ب ايثون ‪ ،3‬يتطلب إطالق االس تثناءات ذات الوس ائط اس تخدام األق واس‪،‬‬
‫كما ال يمكن استخدام السالسل النصية كاستثناءات‪.‬‬
‫بايثون ‪# 2‬‬
‫‪# 1‬‬
‫‪raise Exception, args‬‬
‫‪# 2‬‬
‫‪raise Exception, args, traceback‬‬
‫‪# 3‬‬
‫"‪raise "Error‬‬
‫بايثون ‪# 3‬‬
‫‪raise Exception‬‬
‫‪# 1‬‬
‫)‪raise Exception(args‬‬
‫•‬
‫‪# 2‬‬
‫)‪raise Exception(args).with_traceback(traceback‬‬
‫‪# 3‬‬
‫)"‪raise Exception("Error‬‬
‫تغير في‬
‫‪ :except‬في بايثون ‪ ،2‬كان من الصعب إدراج االس تثناءات المُ تع ِّددة لكن ذل ك َّ‬
‫ً‬
‫صراحة مع ‪ except‬في بايثون ‪:3‬‬
‫أن ‪ُ as‬تستخ َدم‬
‫بايثون ‪ .3‬الحظ َّ‬
‫بايثون ‪# 2‬‬
‫‪except Exception, variable:‬‬
‫بايثون ‪# 3‬‬
‫‪except AnException as variable:‬‬
‫‪except (OneException, TwoException) as variable:‬‬
‫•‬
‫‪ :def‬في ب ايثون ‪ ،2‬يمكن لل دوال أن تقب ل سالس ل مث ل الص فوف أو الق وائم‪ .‬أمَّ ا في‬
‫بايثون ‪ ،3‬فقد أزيل هذا األمر‪.‬‬
‫‪414‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫بايثون ‪# 2‬‬
‫‪def function(arg1, (x, y)):‬‬
‫بايثون ‪# 3‬‬
‫‪def function(arg1, x_y): x, y = x_y‬‬
‫•‬
‫‪ :expr‬لم تعد صياغة عالمة االقتب اس المائل ة `` في ب ايثون ‪ 2‬ص الحة‪ ،‬واس تخدم ب داًل‬
‫عنها )(‪ repr‬أو )(‪ str.format‬في بايثون ‪.3‬‬
‫بايثون ‪# 2‬‬
‫`‪x = `355/113‬‬
‫بايثون ‪# 3‬‬
‫‪x = repr(355/113):‬‬
‫•‬
‫تنس يق السالس ل النص ية (‪ :)String Formatting‬لق د تغ يرت ص ياغة تنس يق السالس ل‬
‫النصية من بايثون ‪ 2‬إلى بايثون ‪.3‬‬
‫بايثون ‪# 2‬‬
‫‪# 1‬‬
‫)‪"%d %s" % (i, s‬‬
‫‪# 2‬‬
‫)‪"%d/%d=%f" % (355, 113, 355/113‬‬
‫بايثون ‪# 3‬‬
‫‪# 1‬‬
‫)‪"{} {}".format(i, s‬‬
‫‪# 2‬‬
‫)‪"{:d}/{:d}={:f}".format(355, 113, 355/113‬‬
‫ت ذكر كيفي ة اس تخدام تنس يقات السالس ل النص ية من فص ل كيفي ة اس تخدام آلي ة تنس يق‬
‫السالسل النصية في بايثون ‪.3‬‬
‫•‬
‫‪ :class‬ليست هناك حاجة لتمرير ‪ object‬في بايثون ‪.3‬‬
‫‪415‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫بايثون ‪# 2‬‬
‫‪class MyClass(object):‬‬
‫‪pass‬‬
‫بايثون ‪# 3‬‬
‫‪class MyClass:‬‬
‫‪pass‬‬
‫ضبط األصناف العليا (‪ )metaclasses‬بالكلمة مفتاحية ‪.metaclass‬‬
‫في بايثون ‪ُ ،3‬ت َ‬
‫بايثون ‪# 2‬‬
‫‪class MyClass:‬‬
‫‪__metaclass__ = MyMeta‬‬
‫‪class MyClass(MyBase):‬‬
‫‪__metaclass__ = MyMeta‬‬
‫بايثون ‪# 3‬‬
‫‪class MyClass(metaclass=type):‬‬
‫‪pass‬‬
‫‪class MyClass(MyBase, metaclass=MyMeta):‬‬
‫‪pass‬‬
‫‪ .8‬تحديث الشيفرة‬
‫توافقيته ا م ع‬
‫تلقائيا إلى ب ايثون ‪ 3‬م ع الحف اظ على‬
‫رئيسيتان لتَحديث الشيفرة‬
‫َّ‬
‫هناك أ َداتان ّ‬
‫ً‬
‫آليتا عمل ه اتين األداتين‪ ،‬إذ تح اول ‪ future‬نق ل‬
‫بايثون ‪ 2‬وهما‪ future :‬و ‪ .modernize‬تختلف َ‬
‫أن ‪ modernize‬تس عى إلى إنش اء ش يفرات‬
‫أفض ل ممارس ات ب ايثون ‪ 3‬إلى ب ايثون ‪ ،2‬في حين َّ‬
‫َّ‬
‫التوافقية‪ .‬يمكن أن تس اعدك‬
‫موحدة لب ايثون تتواف ق م ع ‪ 2‬و ‪ 3‬وتس تخدم الوح دة ‪ six‬لتحس ين‬
‫َّ‬
‫هات ان األدات ان في إع ادة كتاب ة الش يفرة وتحدي د ورص د المش اكل المحتمل ة وتص حيحها‪ .‬يمكن ك‬
‫ُّ‬
‫أن‬
‫تش غيل األداة ع بر مجموع ة ‪ unittest‬لفحص الش يفرة‬
‫والتحقق منه ا بص ريً ا‪ ،‬والتأك د من َّ‬
‫‪416‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫ُأ‬
‫المراجع ات التلقائي ة ال تي ج ريَ ت دقيق ة‪ .‬وبمج رد انته اء االختب ارات‪ ،‬يمكن ك‬
‫تحويل الشيفرة‪.‬‬
‫بع د ه ذا‪ ،‬س تحتاج على األرجح إلى إج راء مراجع ة يدويَّ ة‪ ،‬وخاص ة اس تهداف االختالف ات‬
‫بين ب ايثون ‪ 2‬و ‪ 3‬الم ذكورة في القس م أعاله‪ .‬إن أردت اس تخدام ‪ ،future‬فعلي ك إض افة عب ارة‬
‫االستيراد التالية في جميع وحدات بايثون ‪:2.7‬‬
‫‪from __future__ import print_function, division,‬‬
‫‪absolute_imports, unicode_literals‬‬
‫أن ه ذا لن يعفي ك من إع ادة كتاب ة الش يفرة‪ ،‬إال َّ‬
‫أنه سيض من ل ك أن تتماش ى ش يفرة‬
‫رغم َّ‬
‫بايثون ‪ 2‬مع صياغة بايثون ‪.3‬‬
‫أخ يرًا‪ ،‬يمكن ك اس تخدام الحزم ة ‪ pylint‬لتحدي د ورص د أي مش كالت محتمل ة أخ رى في‬
‫الشيفرة‪ .‬تحتوي هذه الحزمة على مئات القواعد التي تغطي مجموعة واسعة من المش كالت ال تي‬
‫قد تطرأ‪ ،‬بما فيها قواعد الدليل ‪ ،PEP 8‬باإلضافة إلى أخطاء االستخدام‪.‬‬
‫أن بعض أج زاء ش يفرتك ترب ك ‪ pylint‬وأدوات الترحي ل التلق ائي األخ رى‪ .‬ح اول‬
‫ق د تج د َّ‬
‫تبسيطها‪ ،‬أو استخدم ‪.unittest‬‬
‫‪ .9‬التكامل المستمر (‪)Continuous Integration‬‬
‫إذا أردت أن تجع ل ش يفرتك متوافق ة م ع ع دة إص دارات من ب ايثون‪ ،‬فس تحتاج إلى تش غيل‬
‫اإلط ار ‪ unittest‬باس تمرار وف ق مب دأ التكام ل المس تمر (وليس ي دويًا)‪ ،‬أي أن تفع ل ذل ك أك بر ع دد‬
‫التوافقية بين‬
‫ممكن من الم رات أثن اء عملي ة التط وير‪ .‬إذا كنت تس تخدم الحزم ة ‪ six‬لص يانة‬
‫َّ‬
‫بايثون ‪ 2‬و ‪ ،3‬فستحتاج إلى استخدام ع َّدة بيئات عمل ألجل االختبار‪.‬‬
‫‪417‬‬
‫|‬
‫▲‬
‫إصدارات بايثون‪ :‬بايثون ‪3‬مقابل بايثون ‪2‬‬
‫البرمجة بلغة بايثون‬
‫إح دى ح زم إدارة البيئ ة ال تي ق د تك ون مفي دة ل ك هي الحزم ة ‪ ،tox‬إذ س تفحص تثبيت ات‬
‫الحزمة مع مختلف إصدارات بايثون‪ ،‬وإجراء االختبارات في كل بيئ ة من بيئ ات عمل ك‪ ،‬كم ا يمكن‬
‫أن تكون بمثابة واجهة عمل للتكامل المستمر‪.‬‬
‫‪ .10‬خالصة الفصل‬
‫ً‬
‫ً‬
‫ممتازا وسهلة التعلم‪ ،‬ومهما كان اختيارك (ب ايثون ‪ 2‬أو‬
‫توثيقا‬
‫لغة بايثون كبيرة ج ًدا وموثقة‬
‫أن هنالك بعض االختالفات‬
‫ٌ‬
‫حاليا‪.‬‬
‫بايثون ‪ )3‬فستتمكن من العمل على المشاريع الموجودة‬
‫صحيح َّ‬
‫ً‬
‫المحورية‪ ،‬لكن ليس من الصعب االنتقال من بايثون ‪ 3‬إلى ب ايثون ‪ ،2‬وس تجد ع ً‬
‫أن ب ايثون ‪2.7‬‬
‫ادة َّ‬
‫خصوص ا في ب دايات تعلم ك للغ ة‪ .‬من المهم أن تبقي ببال ك‬
‫ً‬
‫قادرة على تشغيل ش يفرات ب ايثون ‪،3‬‬
‫أن ترك يز المط ورين والمجتم ع أص بح منص ًّبا نح و ب ايثون ‪ ،3‬وستص بح ه ذه اللغ ة رائ ً‬
‫دة في‬
‫َّ‬
‫وأن دعم ب ايثون ‪ 2.7‬س يقل م ع م رور ال زمن‬
‫المس تقبل وس تلبي االحتياج ات البرمجي ة المطلوب ة‪،‬‬
‫َّ‬
‫إلى أن يزول في ‪( 2020‬قد زال لحظة ترجمة الكتاب ومراجعته)‪.‬‬
‫‪418‬‬
‫|‬
‫▲‬
Download