بايثون للجميع التعامل مع البيانات باستخدام لغة بايثون 3 تأليف :د .تشارلز سيفيرنس ترجمة :منصة الكترونكس غو منصة © Electronics Goالنسخة األولى 2023 َ هذا العمل مرخص بموجب رخصة املشاع اإلبداعي :عزو العمل األصلي إلى املؤلف -غيرتجاري - إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي مقدمة النسخة العربية ً انتشارا؛ وذلك لكونها برزت لغة بايثون في السنوات األخيرة كإحدى أهم لغات البرمجة وأكثرها ً َ حاليا الخيار األنسب للمبتدئين لالنطالق في عالم البرمجة ،باإلضافة لذلك لغة سهلة التعلم ،وتعد فهي مناسبة لالستخدام في مختلف املجاالت ومنها تعلم اآللة وتحليل البيانات وتطوير الويب .ومما يساهم في تبني بايثون من قبل الكثيرين هو توفر دعم هائل ًّ جدا في مجتمعات املبرمجين وامتالكها مجموعة واسعة من املكتبات التي تختصر الكثير من التحديات وتسهل عمل املبرمجين. إيمانا َّ منا بأهمية تعلم بايثون َ سعت منصة Electronics Goإلى إزالة حاجز اللغة من أمام العديد ُ اختيارنا على من املهتمين العرب عبر ترجمة كتاب " "Python for Everybodyإلى العربية ،وقد وقع هذا الكتاب -وهو من تأليف الدكتور تشارلز سيفيرنس من جامعة ميشيغان -لكونه من أهم الكتب، ُّ ويعد لبنة أساسية لكل باحث عن تعلم البرمجة بلغة بايثون مهما كان اختصاصه أو خلفيته العلمية. ُترجم الكتاب إلى عدة لغات منها األملانية واإلسبانيةُ ، واعتمد في عدة جامعات ومنصات تعليم كمرجع َّ أساس ي .يتميز الكتاب بأسلوبه َّ املبسط السلس ،فلم يقدم الكاتب إال كل مختصر مفيد ،وركز على مفاهيم البرمجة تركيزا ً َ الكتاب لن تجد صعوبة في تعلم أية لغة برمجية أخرى. عميقا؛ فبعد قراءتك َ مفاهيم أساسية كبنية الحاسوب ثم مفاهيم املتغيرات ،يليها الشروط الفصول العشر األولى تغطي فالحلقات فالتعامل مع السالسل النصية ،ثم ُبنى املعطيات كالقوائم والقواميس والصفوف ،ثم َّ يشرح التوابع ودورها في البرنامج .يتخلل كل فصل مجموعة كبيرة من التمارين العملية التي يمكنك ً تجربتها ،ومع ُّ تتدرج التمارين واألمثلة من البسيط َّ تقدمك من فصل إلى فصل َّ السهل إلى األكثر شموال ُّ وتقد ًما. َّ تركز الفصول املتبقية على مفاهيم ذات أهمية في مجال علوم البيانات ،كالتعابير النمطية والتعامل مع تطبيقات عبر الشبكة ،واستكشاف الويب ،واستخدام الواجهات البرمجية لتطبيقات مختلفة، ً ويعرفك بالبرمجية الكائنية الت ُّ وجه ،ثم يخصص الكاتب فصال عن استخدام قواعد البيانات في بايثون ً وأخرا لتمثيل البيانات وعرضها. ُ هدفنا أن تكون هذه النسخة العربية نقطة انطالق للشباب َّ الشغوف بالتعلم ،وتكون َّ مجرد بداية ً الطريق ملبرمجين سيحدثون فرقا في مجتمعاتهم والعالم. حول منصة Electronics Go منصة تقنية تعليمية ،انطلقت عام ،2016تعمل على تعزيز وتطوير املجتمع التقني الناطق بالعربية من خالل تغطية أبرز ما توصل إليه العلم في مجاالت :التحكم الصناعي ،واألنظمة َ املدمجة ،وإنترنت األشياء ،باإلضافة إلى تقديم تدريبات مهنية تساهم في تطوير وتعزيز مهارات املهتمين في هذه املجاالت. خدماتها: • نشر محتوى علمي تخصص ي باللغة العربية. • التنظيم واملشاركة في الفعاليات واملسابقات العلمية. • تقديم التدريبات املهنية للمهتمين في هذه املجاالت. • تقديم استشارات ودعم للمشاريع التقنية والصناعية. • تجهيز املخابر التدريبية للمعاهد والجامعات. يعمل في Electronics Goفريق من عدة دول عربية ،ويمكن معرفة املزيد عن َّ املنصة والخدمات التي تقدمها عبر زيارة الرابطwww.electronics-go.com : املساهمون في النسخة العربية: الترجمة :آالء محمد أغا ،حنين غالية ،سها أديب ،قاهر اليتيم ،قحطان غانم ،لؤي ديب. املراجعة :سلمى الحافي ،عبد الرحمن صابر ،عدي ناصر ،علي العلي. التدقيق اللغوي :حنين غالية ،رنيم العلي ،سالم أحمد ،محمد بابكر. التدقيق العلمي :هزار غانم. تصميم الغالف :رؤى غانم. -التحريرواإلشراف العام :علي العلي. اإلسهامات التحرير :إيليوت هوزير ( ،)Elliott Hauserوسو بلومينبيرغ ()Sue Blumenberg تصميم الغالف :إيمي أندريون ()Aimee Andrion الطبعات الطبعة األولى الكاملة لإلصدار الثالث من لغة بايثون في 05تموز /يوليو .2016 -الطبعة األولية للتحول إلى اإلصدار الثالث من لغة بايثون في 20كانون األول /ديسمبر .2015 حقوق النشر الحقوق محفوظة للدكتور تشارلز سيفيرنس 2009 العمل مرخص وفق رخصة املشاع اإلبداعي من النمط )استخدام غير تجاري -إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي( اإلصدار الثالث. ملعلومات حول الرخصةhttp://creativecommons.org/licenses/by-nc-sa/3.0/ : استخداما ً ً تجاريا وغيره من االستثناءات في الرخصة ،اطلع على امللحق ب ملزيد حول ما يعتبره الكاتب املعنون "حقوق النشر". املقدمة يسعى املتخصصون األكاديميون ً دوما لكتابة ونشر مؤلفات جديدة باملطلق ،حيث يخضعون لضغط ٍ َ ً اعتمادا على مؤلفات ف مستمر لنشر املؤلفات .على عكس ذلك ،كان هذا الكتاب تجربة كتابة ٌمؤل ٍ أخرى ،حيث عملنا على إعادة ترتيب كتاب "فكر بطريقة بايثون :كيف تفكر كعالم حاسوب" ( Think كل من آلن دوني ()Allen B. Downey )Python: How to Think Like a Computer Scientistتأليف ٍ وجيف أيلكنر ( ،)Jeff Elknerوآخرون. في كانون األول/ديسمبر عام 2009كنت أجهز لتدريس مقرر برمجة الشبكات في جامعة ميشيغان للفصل الخامس على التوالي ،وقررت وقتها أنه حان الوقت املناسب لكتابة كتاب للغة بايثون والذي ً يركز على استكشاف البيانات بدال من فهم الخوارزميات واألفكار املجردة ،وهدفي في املقرر هو إكساب الطلبة مهارات التعامل مع البيانات باستخدام لغة بايثون مدى الحياة. ً لم يخطط العديد من طالبي ليصبحوا مبرمجين محترفين ،بدال من ذلك خططوا ليصبحوا أمناء مكتبات ومدراء ومحاميين وعلماء أحياء واقتصاديين ،لكنهم رغبوا أن يستخدموا التكنولوجيا بمهارة في مجال عملهم. ٌ لم يقع بين يدي ٌ مخصص لتعليم التعامل مع البيانات باستخدام بايثون العتمده كمرجع كتاب مثالي في مقرري الدراس ي ،لذلك شرعت في كتابة هذا الكتاب ،ومن حسن الحظ أنه في إحدى اجتماعات الكلية ،وقبل ثالثة أسابيع من بدئي في تأليف الكتاب من الصفر في عطلة األعياد ،عرض لي د.آتول براكاش ( )Dr. Atul Prakashكتاب "فكر بطريقة بايثون" والذي اعتاد أن يدرس به طالبه خالل ذلك الفصل ،وهو كتاب صيغ بطريقة مناسبة لطالب علوم الحاسوب ليقدم املختصر املفيد الواضح ويركز على تبسيط التعليم. غيرنا ترتيب الكتاب بحيث يتعلم الطالب حل مشكالت تحليل البيانات بأسرع وسيلة ممكنة ،فهو يحوي على سلسلة من األمثلة العملية وعلى تمارين حول تحليل البيانات من الفصول األولى. الفصول من 2إلى 10متشابهة مع كتاب "فكر بطريقة بايثون" مع إضافة تغيرات ،حيث استبدلت كل من األمثلة والتمارين املتعلقة بالحساب بتمارين متعلقة بالبيانات ،واملحاور مرتبة بشكل مناسب ً لبناء حلول ملسائل تحليل البيانات األكثر تعقيدا. نقلت بعض املحاور مثل بنية try/exceptإلى الفصل املتعلق بالبنى الشرطية ،وطرحت التوابع بشكل ً مبسط في البداية إلى حين ظهرت الحاجة عند التعامل مع البرامج املعقدة بدال من طرحها كمحور منفصل .كما حذفنا أغلب التوابع املعرفة من قبل املستخدم من األمثلة والتمارين خارج نطاق الفصل الرابع ،ولم نتعامل مع االستدعاء الذاتي أو العودية ( )recursionفي هذا الكتاب ً مطلقا. ٌ ُ جديد ك ًليا ويركز على استخدامات واقعية وأمثلة املحتوى في الفصل 1والفصول من 11إلى 16 بسيطة للغة بايثون في تحليل البيانات مثل التعابير النمطية في عمليات البحث والتحليل ،وأتمتة املهام على الحاسوب ،واسترجاع البيانات عبر الشبكة ،وتعقب صفحات الويب ،والبرمجة كائنية التوجه ،واستخدام خدمات الويب ،وتفسير بيانات XMLو ،JSONوإنشاء واستخدام قواعد بيانات باستخدام لغة االستعالمات البنيوية ،SQLوتمثيل البيانات (.)Visualization Data ً الهدف األساس ي من هذه التغييرات هو التحول من تعلم علم الحاسوب ً مجردا إلى التركيز على تعلما التطبيقات املعلوماتية ولتضمين فقط املواضيع التي تفيد الطالب حتى إن لم يختر الفرد منهم أن ً ً مبرمجا محترفا. يصبح أنصح الطالب الذين يستمتعون بقراءة هذا الكتاب ويريدون تعلم املزيد أن يقرؤوا كتاب "فكر ً بطريقة بايثون" ملؤلفه آلن دوني نظرا للتشابه بين الكتابين ،فبذلك سيتعلم الطالب املهارات في نواحي إضافية تم التطرق لها في ذلك الكتاب منها البرمجة التقنية والخوارزميات ،وبما أن الكتابين متشابهين من حيث األسلوب ،سيتمكن الطالب من االطالع بسرعة وسالسة على األفكار في كتاب "فكر بطريقة بايثون". منحني مؤلف الكتاب وصاحب حقوق النشر آلن اإلذن لتغيير رخصة الجزء املشابه لكتابه من رخصة جي إن يو GNUإلى رخصة املشاع اإلبداعي األكثر حداثة وهي رخصة من النمط "إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي ". وهذا يتبع التحول العام في الرخص املفتوحة أي التحول من GFDLإلى CC-BY-SAمثل "ويكيبيديا"، حيث يحافظ استخدام رخصة CC-BY-SAعلى ُعرف حقوق امللكية للكتاب ً وأيضا يجعله مناسب ُ أكثر للكتاب الجدد إلعادة استخدام املادة كما يرغبون. ً أعتقد أن هذا الكتاب هو خير مثال على األهمية الكبيرة للمواد املشاعة في التعليم مستقبال ،أود أن أشكر آلن دوني ودار جامعة كامبريدج للنشر لقرارهم ذي النظرة البعيدة لجعل هذا الكتاب ً متاحا تحت حقوق ملكية مفتوحة ،وأتمنى أن يكونوا راضيين عن ثمرة جهودي .كما أتمنى لك ،عزيزي ً اض عن هذه الجهود مجتمعة. القارئ ،أن تكون ر ٍ أود أن أشكر آلن دوني ولورين كوليس ( (Lauren Cowlesعلى مساعدتهم وصبرهم وإرشادهم في حل أمور حقوق نشر هذا الكتاب. تشارلز سيفيرنس ()Charles Severance www.dr-chuck.com مدينة أن أربور في والية ميشيغان في الواليات املتحدة األميركية 9أيلول /سبتمبر 2013 األستاذ تشارلز سيفيرانس أستاذ في جامعة ميشيغان في كلية املعلوماتية. الفهرس ّ البمجة؟ 2 ................................................................................................................. لماذا نتعلم ر 1 1.1 اإلبداع والحافز 3.......................................................................................................................... 2.1 بنية الحاسوب 4........................................................................................................................... 3.1 البمجة 6............................................................................................................................. فهم ر ُ مفردات بايثون وجملها 6................................................................................................................ 5.1 مخاطبة بايثون 7.......................................................................................................................... ر ِ والمب ِجم 10..................................................................................................................... المفّس 7.1 كتابة برنامج 12........................................................................................................................... 8.1 البنامج؟ 12....................................................................................................................... ما هو ر ّ ّ للبامج 14......................................................................................................... المكونات األساسية ر ما األخطاء ر الت يمكن أن نواجهها؟ 15................................................................................................. 4.1 6.1 9.1 10.1 11.1 التنقيح 16.................................................................................................................................. ّ رحلة التعلم 18............................................................................................................................ 13.1 فهرس المصطلحات18.................................................................................................................. 14.1 تمارين 20................................................................................................................................... 12.1 ر والتعابب والتعليمات 23 ................................................................................................... المتغبات ّ ّ 2 1.2 القيم وأنواع البيانات 23................................................................................................................. ّ المتغبات 24.............................................................................................................................. ّ ّ ّ المتغبات والكلمات المفتاحية 25............................................................................................. أسماء ّ 4.2 التعليمات 26.............................................................................................................................. 5.2 العوامل والمعامالت 27................................................................................................................. 6.2 التعابب 28.................................................................................................................................. ّ ّ تر ّ العمليات 28....................................................................................................................... اتبية 8.2 عامل ر باق القسمة 29..................................................................................................................... العمليات عىل السالسل ّ ّ النص ّية 30.................................................................................................... 10.2 إدخال البيانات من المستخدم 30..................................................................................................... 11.2 التعليقات 31.............................................................................................................................. ّ اختيار أسماء ّ متغبات سهلة التذكر 32............................................................................................... ّ 13.2 التنقيح 34.................................................................................................................................. 14.2 فهرس المصطلحات35.................................................................................................................. 15.2 تمارين 37................................................................................................................................... 2.2 3.2 7.2 9.2 12.2 ّر ر الش ر ط 39 ...................................................................................................................... التنفيذ 3 1.3 ّ ّ المنطقية 39..................................................................................................................... عابب الت ّ 2.3 ّ المنطقية 40..................................................................................................................... العوامل ّ ر التنفيذ المّسوط 40..................................................................................................................... ّ التنفيذ البديل 42......................................................................................................................... رّ الّسوط المتسلسلة 43.................................................................................................................. رّ الّسوط المتداخلة45.................................................................................................................... ّ التعامل مع االستثناء باستخدام بنية TRYو46............................................................................ EXCEPT ّ ُّ ّ ّ المنطقية 49.............................................................................................. عابب تجاوز التحقق من الت ّ ّ التنقيح 51.................................................................................................................................. 10.3 فهرس المصطلحات51.................................................................................................................. 11.3 تمارين 53................................................................................................................................... 3.3 4.3 5.3 6.3 7.3 8.3 9.3 التوابع 56 ................................................................................................................................. 4 1.4 استدعاء التوابع 56....................................................................................................................... 2.4 التوابع الجاهزة 56........................................................................................................................ 3.4 توابع تحويل النوع 57.................................................................................................................... ّ الرياضية 58....................................................................................................................... التوابع 5.4 ّ العشوائية 59..................................................................................................................... األعداد 6.4 إضافة توابع جديدة 61.................................................................................................................. 7.4 التعاريف واستخداماتها 63.............................................................................................................. 8.4 تسلسل التنفيذ 64........................................................................................................................ ُ المعامالت والوسائط 64................................................................................................................ 10.4 التوابع ُ المنتجة والتوابع الخالية 66.................................................................................................... 11.4 لماذا نستخدم التوابع 67................................................................................................................ ّ التنقيح 68.................................................................................................................................. 13.4 فهرس المصطلحات69.................................................................................................................. 14.4 تمارين 70................................................................................................................................... 4.4 9.4 12.4 التكرار 74 ................................................................................................................................. 5 1.5 المتغبات74............................................................................................................... تحديث قيم ّ 2.5 حلقة 74........................................................................................................................... WHILE 3.5 الحلقات الالنهائية 75.................................................................................................................... 4.5 إنهاء التكرار باستخدام تعليمة 77....................................................................................... CONTINUE 5.5 الحلقات المحددة باستخدام 78.................................................................................................FOR 6.5 أنماط كتابة الحلقات 79................................................................................................................ 1.6.5 حلقات العد والجمع 80........................................................................................................... 2.6.5 الكبى والصغرى 81....................................................................................... حلقات إيجاد القيم ر 7.5 التنقيح 83.................................................................................................................................. 8.5 فهرس المصطلحات83.................................................................................................................. 9.5 تمارين 84................................................................................................................................... السالسل النصية 86 .................................................................................................................... 6 1.6 السلسلة النصية ه سلسلة من المحارف 86........................................................................................ 2.6 الحصول عىل طول السلسلة النصية باستخدام التابع 87.................................................................... LEN 3.6 التعامل مع محارف السلسة النصية باستخدام الحلقات 88...................................................................... 4.6 تجزئة السالسل النصية 89.............................................................................................................. 5.6 غب قابلة للتعديل 90............................................................................................... السالسل النصية ّ ّ استخدام الحلقات والعد 90............................................................................................................ 7.6 العامل 91............................................................................................................................... IN 8.6 مقارنة السالسل النصية 91............................................................................................................. 9.6 توابع السالسل النصية 92............................................................................................................... 10.6 تحليل السالسل النصية 95............................................................................................................. 11.6 عامل التنسيق 96......................................................................................................................... 12.6 التنقيح 97.................................................................................................................................. 13.6 فهرس المصطلحات99.................................................................................................................. 14.6 تمارين 100................................................................................................................................. 6.6 الملفات 102 ............................................................................................................................. ِ 7 1.7 اإلرصار عىل التعلم 102.................................................................................................................. 2.7 الملفات 103......................................................................................................................... فتح ِ 3.7 ِملفات النصوص واألسطر 104........................................................................................................ 4.7 الملفات 105........................................................................................................................ قراءة ِ 5.7 البحث خالل ِملف 107................................................................................................................. 6.7 الملف 110.............................................................................................. السماح للمستخدم باختيار ِ 7.7 استخدام TRYو EXCEPTو111.................................................................................................. OPEN 8.7 الملفات 113....................................................................................................................... كتابة ِ 9.7 التنقيح 114................................................................................................................................ 10.7 فهرس المصطلحات115................................................................................................................ 11.7 تمارين 116................................................................................................................................. القوائم 119 .............................................................................................................................. 8 1.8 القائمة ه سلسلة 119.................................................................................................................. 2.8 القوائم قابلة للتعديل 119.............................................................................................................. 3.8 المرور عىل عنارص قائمة 121.......................................................................................................... ّ العمليات عىل القوائم 122.............................................................................................................. 5.8 تجزئة القوائم 122........................................................................................................................ توابع ّ خاصة بالقوائم 123............................................................................................................... 7.8 حذف العنارص 124...................................................................................................................... 8.8 القوائم والتوابع125...................................................................................................................... 4.8 6.8 9.8 القوائم والسالسل ّ النص ّية 127......................................................................................................... 10.8 التعامل مع األسطر ق الملفات 128.................................................................................................. َ والقيم 129...................................................................................................................... الكائنات 12.8 التسمية البديلة 131..................................................................................................................... 13.8 وسائط القائمة 131...................................................................................................................... 14.8 التنقيح 133................................................................................................................................ 15.8 فهرس المصطلحات138................................................................................................................ 16.8 تمارين 139................................................................................................................................. 11.8 القواميس 143 ........................................................................................................................... 9 1.9 استخدام القواميس ق العد 145....................................................................................................... 2.9 القواميس والملفات 147................................................................................................................ 3.9 الحلقات والقواميس 149............................................................................................................... 4.9 التعامل مع النصوص 150............................................................................................................... 5.9 التنقيح 152................................................................................................................................ 6.9 فهرس المصطلحات153................................................................................................................ 7.9 تمارين154................................................................................................................................ : الصفوف 157 ............................................................................................................................ 10 1.10 غب قابلة للتعديل 157...................................................................................................... الصفوف ّ 2.10 مقارنة الصفوف 159..................................................................................................................... 3.10 إسناد الصفوف 160...................................................................................................................... 4.10 القواميس والصفوف 162............................................................................................................... 5.10 اإلسناد المتعدد مع القواميس 163.................................................................................................... الكلمات األكب تكر ًارا 164............................................................................................................... 7.10 استخدام الصفوف كمفاتيح ضمن القواميس 166.................................................................................. 8.10 السالسل :النصوص والقوائم والصفوف 166....................................................................................... 9.10 التنقيح 167................................................................................................................................ 10.10 فهرس المصطلحات167................................................................................................................ 11.10 تمارين 168................................................................................................................................. 6.10 التعابب النمطية 172 ................................................................................................................... ّ 11 1.11 التعابب النمطية 173............................................................................................ مطابقة المحارف ق ّ 2.11 التعابب النمطية 175................................................................................. استخراج البيانات باستخدام ّ 3.11 ر عمليت البحث واالستخراج معا 178.......................................................................................... تنفيذ 4.11 محرف الهروب 183...................................................................................................................... 5.11 ملخص 184............................................................................................................................... 6.11 معلومات إضافية لمستخدم نظام UNIXو 185......................................................................... LINUX 7.11 التنقيح 186................................................................................................................................ 8.11 فهرس المصطلحات187................................................................................................................ 9.11 تمارين 187................................................................................................................................. البامج المرتبطة بالشبكات 190 ...................................................................................................... ر 12 1.12 ّ التشع رت 190............................................................................................. HTTP برتوكول نقل النص ّ ُمتصفح الويب األبسط ق العالم 191................................................................................................. 3.12 استعادة صورة عن طريق بروتوكول 194.................................................................................... HTTP 4.12 استعادة صفحات الويب باستخدام مكتبة 198........................................................................... URLLIB ُ ّ شفرة ً ثنائيا باستخدام 199............................................................................... URLLIB قراءة الملفات الم 6.12 تحليل واستخراج البيانات من صفحات 201.............................................................................. HTML 7.12 التعابب النمطية 201......................................................................... تحليل صفحات HTMLباستخدام ّ 8.12 تحليل صفحات HTMLباستخدام مكتبة 204.............................................................. BEAUTIFULSOUP ُ مبات خاصة ُ لمستخدم أنظمة لينكس أو يونيكس209.......................................................................... ّ 10.12 فهرس المصطلحات209................................................................................................................ 11.12 تمارين 210................................................................................................................................. 2.12 5.12 9.12 استخدام خدمات الويب213 ......................................................................................................... 13 1.13 لغة التوصيف الموسعة 213.................................................................................................... XML 2.13 تحليل نصوص 214.............................................................................................................. XML 3.13 استخدام الحلقات للمرور عىل العقد 215........................................................................................... 4.13 217................................................................................................................................ JSON 5.13 تحليل نصوص 218............................................................................................................. JSON 6.13 واجهات برمجة التطبيقات219........................................................................................................ 7.13 األمان واستخدام واجهات برمجة التطبيقات 221.................................................................................. 8.13 فهرس المصطلحات221................................................................................................................ ر مب الجغراق من غوغل222............................................................................ : التطبيق األول :خدمة الب ّ التطبيق الثان :ر تويب 227................................................................................................................ 9.13 10.13 البمجة الكائنية التوجه 235 .......................................................................................................... ر 14 1.14 الكببة 235................................................................................................................. البامج ّ إدارة ر 2.14 مقدمة 235................................................................................................................................ 3.14 استخدام الكائنات 236.................................................................................................................. 4.14 البامج 237..................................................................................................................... البدء مع ر 5.14 تقسيم المشكلة 239..................................................................................................................... 6.14 إنشاء كائن ق لغة بايثون 240........................................................................................................... 7.14 الصنف كنوع بيانات 243............................................................................................................... 8.14 دورة حياة الكائن244..................................................................................................................... 9.14 تعدد الكائنات 245....................................................................................................................... 10.14 الوراثة 247................................................................................................................................. 11.14 ملخص 248............................................................................................................................... 12.14 فهرس المصطلحات249................................................................................................................ استخدام قواعد البيانات ولغة 252 ........................................................................................... SQL 15 1.15 ما ه قاعدة البيانات؟ 252............................................................................................................. 2.15 مفاهيم ق قواعد البيانات 252......................................................................................................... 3.15 متصفح قاعدة البيانات ق253.............................................................................................. SQLITE 4.15 إنشاء جدول قاعدة بيانات 253........................................................................................................ ّ البنيوية 257........................................................................................SQL ملخص عن لغة االستعالم 6.15 استكشاف ر تويب باستخدام قواعد البيانات 258.................................................................................... 7.15 نمذجة البيانات 266..................................................................................................................... 8.15 برمجة قاعدة البيانات ذات الجداول المتعددة 268................................................................................ 5.15 1.8.15 القيود ق قواعد البيانات273..................................................................................................... 2.8.15 استعادة أو إضافة سجل ق قاعدة البيانات 274.............................................................................. تخزين عالقة الصداقة ّبي مستخدم ر تويب 275............................................................................. 3.8.15 9.15 أنواع المفاتيح الثالثة 277............................................................................................................... 10.15 استخدام عبارة JOINالستعادة البيانات 277....................................................................................... 11.15 الملخص 281.............................................................................................................................. 12.15 التنقيح 281................................................................................................................................ 13.15 فهرس المصطلحات282................................................................................................................ ر المرئ للبيانات 285 ........................................................................................................... العرض 16 1.16 عرض خريطة باستخدام بيانات جغر ّ افية من غوغل 285.......................................................................... 2.16 ّ المرن للشبكات واالرتباطات288............................................................................................ العرض ر البيد اإللكب ّ ون 293............................................................................ تحليل وعرض البيانات الواردة ق ر 3.16 الفصل األول ملاذا نتعلم البرمجة؟ الفصل األول :ملاذا نتعلم البرمجة؟ 2 ّ 1ملاذا نتعلم البرمجة؟ ُّ البرمجة نشاط ممتع ،وعملية إبداعية مذهلة .تختلف األسباب التي تدفع الناس لتعلم البرمجة، فمنهم من يتعلمها لكسب الرزق ،أو لتحليل البيانات املعقدة ،أو للتطوع لحل مشكالت اآلخرين ،أو حتى للتسلية. بحاجة إلى تعلم البرمجة حتى إن لم ندرك الغاية منها في البداية ،فنحن نعيش اليوم في أن الجميع ٍ عالم مليء باألجهزة الحاسوبية ،مثل الحواسيب املحمولة والهواتف الذكية ،وهي رهن إشارتنا ،وكأن ُ هذا العتاد الصلب قد ُ صم َم خص ً يصا ليقول لنا" :رغباتك أوامر". ما األمر التالي؟ ما األمر التالي؟ ما األمر التالي؟ ما األمر التالي؟ ما األمر التالي؟ ما األمر التالي؟ الشكل :1املساعد الشخص ي الرقمي مساعد يزود املبرمجون هذا العتاد بنظام تشغيل ومجموعة من التطبيقات ،فنحصل بذلك على ٍ قادر على مساعدتنا في تأدية مختلف املهام. رقمي ٍ شخص ٍي ٍ ُ حواسيبنا اليوم سريعة ،ولها ذاكرة بحجم كبير ،ويمكن أن تساعدنا في أداء مهامنا الكثيرة واملتكررة إذا ما حدثناها بلغتها ،فهي قادرة على إنجاز املهام التي يعتبرها البشر ممل ٍة للغاية .على سبيل املثال، ٌ صحيح اقرأ أول مقطعين من هذا الفصل ،واستخرج الكلمة األكثر تكر ًارا ،مع ذكر عدد مرات تكرارها. َّ تتمكن من قراءة وفهم هذه الكلمات بسرعة كبيرة ،إال أن َّ عدها مزعج لدماغك الذي لم يصمم أنك س ً ُ ً لحل مثل هذه املسائل ،خالفا للحواسيب التي ت َع ُّد القراءة والفهم عملية صعبة عليها ،إال أنها تستطيع ُ بسهولة أن تعد مرات تكرار كلمة ما ،وتظهر الكلمة األكثر تكر ًارا: python words.py Enter file: words.txt to 16 الفصل األول :ملاذا نتعلم البرمجة؟ 3 َ أخبرنا مساعدنا املخلص بكل سهولة أن الكلمة " "toتكررت ست عشرة مرة في أول ثالث فقرات في ً حافزا لك لتعلم لغة الحاسوب ،فهي مناسبة لتأدية امللف .word.txtأتمنى أن تجد في هذا املثال املهام الصعبة واململة بالنسبة للبشر ،مما يوفر لك الوقت والجهد الذي تحتاجه للتفكير واإلبداع. 1.1اإلبداع والحافز هذا الكتاب ليس َّ موج ًها للمبرمجين املحترفين ،مع العلم أن البرمجة االحترافية تعود بالنفع على ًّ صاحبها ،سواء ًّ شخصيا ،فبناء برامج ذكية ومفيدة هو نشاط إبداعي بامتياز .يحتوي ماليا أو ً عادة ،أو ُ لنقل املساعد الشخص ي الرقمي ) ،PDA (Personal Digital Assistantعلى برامج الحاسوب متنوعة صممها مبرمجون مختلفون ،وتتنافس فيما بينها للحصول على انتباهنا واهتمامنا لتلبية ً ً وعادة ما َّ يتربح هؤالء املبرمجون مباشرة عند استخدامك لبرامجهم. احتياجاتنا وتوفير تجربة رائعة، وإن عرفنا البرامج بأنها نتاج إبداع عدة مبرمجين ،فيمكننا أن نتخيل مساعدنا الشخص ي كاآلتي: اخترني اخترني اخترني اشتري خدمتي اخترني اخترني الشكل :2كيف يخاطب املبرمجون املستخدم عبر تطبيقاتهم فليكن دافعنا ًّ حاليا أن نتعامل مع البيانات واملعلومات التي نواجهها في حياتنا بفاعلية أكبرُ ، ولنترك فكرة كسب املال أو إرضاء املستخدمين ً جانبا ،ففي البداية ستكون املبرمج واملستخدم في ٍآن واحد، ُ وبمرور الوقت ،ستكتسب مهارات أكثر ،وستصبح البرمجة عملية ممتعة ،حينها يمكنك تطوير البرامج لآلخرين ومساعدتهم. الفصل األول :ملاذا نتعلم البرمجة؟ 4 2.1بنية الحاسوب ً نحتاج أوال إلى معرفة مكونات الحاسوب نفسه قبل البدء بتعلم اللغة التي تسمح لنا بإعطاء األوامر والتعليمات له ،فإذا فككت ً ً حاسوبا ،ستجد فيه العناصر اآلتية: هاتفا أو ما األمر التالي؟ الشبكة البرمجيات وحدة املعالجة املركزية الذاكرة الثانوية أجهزة الدخل والخرج الذاكرة الرئيسية الشكل :3بنية الحاسوب ُ فلنتناول ك َّل عنصر باختصار: ّ املركزية (أو املعالج) :CPUهذا الجزء مسؤول خص ً يصا عن سؤال "ماذا • وحدة املعالجة ُ أنفذ؟" ،وإذا كانت سرعة معالج الجهاز 3جيجا هرتز ،فسيتساءل ثالثة مليارات مرة في ُّ الثانية عن املهمة التالية ،لذلك يجب تعلم كيفية التواصل مع وحدة املعالجة املركزية بسرعة كبيرة. ّ ُ الرئيسية :تستخدم لتخزين املعلومات التي يحتاج أن يصل إليها املعالج بسرعة، • الذاكرة لذا فسرعتها تقارب سرعة املعالج ،إال أن املعلومات تزول منها عند إطفاء تشغيل الحاسب. الثانويةُ :تستخدم ً ّ أيضا لتخزين املعلومات ،إال أنها أبطأ بكثير من الذاكرة • الذاكرة الرئيسية ،وتبرز فائدتها في قدرتها على تخزين املعلومات حتى عند عدم تشغيل الحاسب. ومنها :أقراص التخزين أو الذاكرة الومضية ) (flash memoryاملوجودة في وحدات تخزين متنقلة USBومشغالت املوسيقى املحمولة. • أجهزة اإلدخال واإلخراج :كالشاشة ،ولوحة املفاتيح ،والفأرة ،وامليكروفون ،ومكبر الصوت ،ولوحة اللمس ،وغيرها من األجهزة التي تساعدنا في التفاعل مع الحاسب. الفصل األول :ملاذا نتعلم البرمجة؟ 5 ً ًّ • تملك معظم الحواسيب ًّ شبكيا لتبادل البيانات عبر الشبكة .يمكن اعتبار حاليا اتصاال مكانا ً هذه الشبكة ً بطيئا ًّ جدا في تخزين وتبادل البيانات الفائضة ،وبذلك قد تعمل الشبكة كذاكرة ثانوية ،ولكن بصورة أبطأ وأقل ً أمانا من الذاكرة الثانوية. تلك كانت نبذة عن مختلف عناصر الحاسب التي ستساعدنا عند كتابتنا للبرامج في الفصول التالية، إال أننا لم نشغل بالنا بتفاصيل آلية عمل هذه العناصر ،وتركنا ذلك ملصممي الحواسيب ،فوظيفتك كمبرمج تتمثل في استخدام أجزاء الحاسوب املختلفة ،والتنسيق بينها لحل املشكلة املطروحة، وتحليل البيانات الناتجة عن هذا الحلً . غالبا ما ستتعامل مع املعالج بإعطائه أوامر معينة لتأدية املهام التي تريدها ،كاستخدام الذاكرة الرئيسية ،أو الثانوية ،أو الشبكة ،أو أجهزة اإلدخال واإلخراج. ما األمر التالي؟ الشبكة الذاكرة الثانوية البرمجيات وحدة املعالجة املركزية أجهزة الدخل والخرج الذاكرة الرئيسية الشكل : 4املبرمج داخل الحاسوب! ً أي أنك أنت من سيأمر املعالج ،ولكنك قد تتضايق قليال إن قلصنا حجمك إلى 5مليمترات، ووضعناك داخل الحاسوب إلعطاء أوامر للمعالج بسرعة ثالث مليارات مرة في الثانية ،لذا ستضطر ً مسبقا ،وتخزينها في ذاكرة الحاسوب؛ ليستدعيها املعالج في الوقت املناسب .تدعى إلى كتابة أوامرك هذه التعليمات َّ املخزنة البرنامج ،في حين ُت َّ سمى كتابة تلك التعليمات والحصول على تنفيذ صحيح لها البرمجة. الفصل األول :ملاذا نتعلم البرمجة؟ 6 3.1فهم البرمجة ً مبرمجا في النهاية .قد سنحاول األخذ بيدك نحو إتقان فن البرمجة في بقية فصول الكتاب ،وستصير ً ً مبرمجا محترفا ،إال أنك ستملك الفكر واملهارات الالزمة التي تؤهلك ملعاينة املشكلة وتحليل ال تصبح برمجي لها .وفي سبيل هذا ستحتاج إلى مهارتين أساسيتين ،وهما: حل بياناتها ومعلوماتها ثم إيجاد ٍ ٍ ً ُّ ُّ للغة بشرية، • أوال ،تعلم لغة البرمجة (بايثون) بمصطلحاتها وقواعدها ،وهذا أشبه بتعلمك ٍ ً ً حيث تتعلم تهجئة كلماتها أوال حتى تصيغ منها جمال صحيحة. ً ً • ً ثانيا ،اكتب قصة باستخدام البرمجة ،فعندما تكتب قصة معينة تستخدم جمال وعبارات إليصال فكرتك إلى القارئ ،فالقصة مزيج من الفن واملهارة ،وتتطور هذه املهارة بالتمرن والحصول على آراء .ينطبق هذا على البرمجة ،فالقصة هنا هي البرنامج ،والفكرة هي ُّ املشكلة املطلوب حلها. ٌ لغة واحدة لغة برمجية أخرى ،مثل C++وجافا سكربت ،بعد تعلم ٍ وجدير بالذكر أنه من السهل تعلم ٍ مثل بايثون ،فمهارة حل املسائل واملشكالت هي نفسها مهما اختلفت لغات البرمجة في تعليماتها وطرق استخدامها. في حين ُيعتبر تعلم لغة بايثون نفسها عملية سهلة وسريعة ،لكن ستحتاج ً وقتا أطول حتى تستطيع كتابة برنامج قادر على حل مشكلة معقدة .ستتعلم معنا البرمجة بذات الطريقة التي تعل َ مت بها ً فبداية سنقرأ ونشرح بعض البرامج ،وبعدها ننتقل إلى كتابة بر َ امج بسيطة ،ثم إلى كتابة الكتابة؛ ً تعقيدا في النهاية .بعد فترة من التعلم ،ستصبح البرمجة عملية ممتعة وإبداعية ،وستبدأ برامج أكثر بتطوير طريقة تفكير خاصة لتفكيك املسائل التي تواجهك ومن ثم كتابة بر َ امج لحلها. سنبدأ أوًال بتعليمات وبنية بايثونَّ . تحل بالصبر ،وركز على األمثلة في البداية كما لو أنك تلميذ يتعلم الكتابة والقراءة للمرة األولى. ُ 4.1مفردات بايثون وجملها ُ على خالف اللغات البشرية ،تتكون لغة بايثون من عدد قليل ًّ جدا من املفردات ،وتسمى هذه املفردات ٍ ٍ واحدا فقط بالنسبة لبايثون .أما ً ً الحقا عند كتابة برامجك، "الكلمات املحجوزة" ألن لها معنى الفصل األول :ملاذا نتعلم البرمجة؟ 7 فستستطيع إنشاء مفرداتك الخاصة ،والتي تدعى "املتغيرات" ،ولك حرية اختيار األسماء لهذه املتغيرات بشرط أال تكون من الكلمات املحجوزة. لنشبه األمر بالتعامل مع الحيوانات األليفة ،حيث نخاطبها بكلمات مثل" :اجلس" أو َ "ابق مكانك" أو "أحضر ً شيئا ما" ،ولكن إذا استخدمت كلمات غير محجوزة (أي أن الحيوان األليف غير َّ مدرب َ ً مثال" :أتمنى لو أن ً عددا عليها) ،فسيرمقك بنظرة متعجبة حتى تستخدم كلمة محجوزة .فإن قلت أكبر من الناس يمشون ليحافظوا على صحتهم العامة" ،فكل ما سيفهمه الحيوان األليف هو "املش ي" ،ألنها كلمة محجوزة في لغته. إليك ً بعضا من الكلمات املحجوزة في لغة بايثون: with yield not or pass raise return try while global if import in is lambda nonlocal del elif else except finally for from and as assert break class continue def ً مسبقا هذه الكلمات ،وعند كل استخدام لكلمة " "tryستحاول بايثون تنفيذ التعليمات بايثون تعرف املطلوبة دون أن يتوقف البرنامج أو يفشل .ال تشغل بالك في دالالت هذه الكلمات وسبل استخدامها، إذ سنتعلم ذلك في وقت الحق .أما اآلن ،فلنبدأ بأمر بسيط ،هذا األمر يشبه أن تقول َّ "تحدث" ،حيث ٍ بإمكاننا إخبار بايثون بما عليها أن تقوله بوضعه ضمن عالمة اقتباس ،مثل: )'!print ('Hello World ً ًّ متبوعا بنص قواعديا في بايثون ،والتي بدأت بالتابع print وبهذا نكون قد كونا أول جملة صحيحة من اختيارنا ضمن عالمتي االقتباس ،مع مراعاة أن كل جمل التابع مكتوبة ضمن عالمتي اقتباس، سواء املفردة ' ' أو املزدوجة " "ُ ،ويفضل معظم الناس اإلشارة املفردة ،إال في حال كان املطلوب ُ حينئذ تستخدم اإلشارة ظهورها نفسها في النص (كفاصلة عليا في اللغة اإلنكليزية ،)apostrophe ٍ املزدوجة. 5.1مخاطبة بايثون سنحتاج اآلن إلى تعلم كيفية مخاطبة بايثون بعد أن تعلمنا كلمة وجملة بسيطة منها ،ولكن قبل ذلك ُّ سنحتاج إلى تنصيب برنامج بايثون على الحاسوب ،وتعلم طريقة تشغيله .تتضمن هذه الخطوة تفاصيل عديدة ،لذلك نقترح عليك زيارة موقع /https://electronics-go.com/install-pythonأو ،www.py4e.comحيث َّ وضحنا اإلجراءات الالزمة للتنصيب والتشغيل على أنظمة ماكنتوش ملاذا نتعلم البرمجة؟:الفصل األول 8 ً َ command أثناء ذلك ستصل إلى مرحلة تستخدم فيها نافذة األوامر.وويندوز ُمرفقة بلقطات شاشة ويعرض،( بالعملinterpreter) ويبدأ ُمفسر بايثون،"python" لتكتب كلمةterminal أوwindow :لك ما يأتي Python 3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> ."هذه الرموز >>> هي طريقة ُمفسر بايثون ليسألك "ماذا تريدني أن أفعل اآلن؟ فلتحاول كتابة السطر الذي،لنفترض أنه ال علم لك حتى بأبسط مفردات وتعليمات لغة بايثون :كوكب مجهول عند هبوطهم على سطحه يستخدمه رواد الفضاء للتواصل مع سكان ٍ >>> I come in peace, please take me to your leader File "<stdin>", line 1 I come in peace, please take me to your leader ^ SyntaxError: invalid syntax >>> ويثبتونك، فقد يطعنك سكان الكوكب برماحهم، وإن لم تتصرف بسرعة،ال يبدو هذا الوضع مبش ًرا َ وبإمكانك، أنت تملك نسخة من هذا الكتاب، ولكن لحسن الحظ،ليتناولوك على العشاء سيخ ٍ على :أن تفتح هذه الصفحة لتحاول مجد ًدا >>> print )'Hello world! ') Hello world! : لذا ستحاول التحدث معهم أكثر،يبدو هذا أفضل بكثير >>> print('You must be the legendary leader that comes from the sky') You must be the legendary leader that comes from the sky >>> print('We have been waiting for you for a long time') We have been waiting for you for a long time >>> print('Our legend says you will be very tasty with mustard') Our legend says you will be very tasty with mustard >>> print 'We will have a feast tonight unless you say الفصل األول :ملاذا نتعلم البرمجة؟ 9 File "<stdin>", line 1 print 'We will have a feast tonight unless you say ^ 'SyntaxError: Missing parentheses in call to 'print >>> ً ً صغيرا في بايثون ،مما جعل سكان الكوكب كانت هذه املحادثة تسير على ما يرام حتى اقترفت خطا ً يرفعون رماحهم مرة أخرى .ضع في الحسبان أن لغة بايثون ليست ذكية كفاية لألسف ،فعلى الرغم ً تعقيدا ً كبيرا ،إال أنها غير مرنة عند ارتكاب األخطاء القواعدية )،(syntax errors من أنها معقدة فحديثك مع بايثون كحديثك مع نفسك ،إنما باستخدام قواعد لغوية صارمة. استخدامك لبرنامج َك َتبه سواك يشبه ً ُ نوعا ما أن تتحدث مع مبرمجي هذا البرنامج ،حيث تلعب ٍ بايثون دور وسيط بينكم ،أي أن بايثون هي طريقة املبرمجين للتعبير عن مجرى املحادثة ،وبعد بضعة فصول من هذا الكتاب ستصبح أحد أولئك املبرمجين ،وستتواصل مع مستخدمي برامجك عن طريق بايثون. ً "وداعا": أما اآلن ،فلعله من غير الالئق أن نترك سكان كوكب بايثون دون أن نقول لهم >>> good-bye Traceback (most recent call last): >File "<stdin>", line 1, in <module NameError: name 'good' is not defined >>> if you don’t mind, I need to leave File "<stdin>", line 1 if you don’t mind, I need to leave ^ SyntaxError: invalid syntax )(>>> quit كما تالحظ ،فالخطأ في أول محاولة يختلف عن ثاني خطأ :كلمة ifمن الكلمات املحجوزة ،مما جعل ُ َّ ً ً وأخيرا نجحنا في قول "وداعا" املسكينة بايثون تعتقد أننا نحاول قول ش ٍيء ،ولكننا لم نوفق في قوله. لبايثون بكتابة )( quitبعد شارة التلقين <<< ،وبما أنك ما كنت ُلتخمن هذه الكلمة من تلقاء نفسك، ُ أمرا ً بدليل للغة (مثل هذا الكتاب) ً مفيدا. تعتبر االستعانة ٍ الفصل األول :ملاذا نتعلم البرمجة؟ 10 ّ واملترجم املفسر 6.1 ِّ ِّ ُت ُّ عد بايثون لغة عالية املستوى ،أي أنها ُ صممت لتكون واضحة ًّ نسبيا للبشر ،وللحواسيب في الوقت نفسه لتقرأها وتعالجها ،ومن اللغات عالية املستوى ً أيضاC++, PHP, Basic, Ruby, Perl, : JavaScriptوغيرها الكثير. ال تفهم وحدة املعالجة املركزية )ًّ (CPUأيا من هذه اللغات ،بل تفهم فقط لغة واحدة ندعوها لغة اآللة ،وهي لغة بسيطة ًّ جدا كاآلتي: 001010001110100100101010000001111 11100110000011101010010101101101 ... كلمة "بسيطة" هنا قد تكون خادعة ،فهي بسيطة في بنيتها ،إذ إنها تتألف من واحد وصفر ،لكن ً ستجد أنها صعبة ومعقدة ًّ ً برنامجا بواسطتها ،لذا يبرمج جدا مقارنة مع بايثون حين تحاول أن تكتب قلة قليلة من املبرمجين بلغة اآللة وألغراض َّ محددة .أنشأت العديد من املترجمات حتى نستطيع البرمجة بلغات عالية املستوى كبايثون وجافا سكربت ،وتحول هذه املترجمات تلك البرامج إلى لغة اآللة ،حيث تنفذها وحدة املعالجة ).(CPU وباعتبار أن لغة اآللة مرتبطة بعتاد الحاسوب الصلب ،فما من طريقة لنقلها بين مختلف أنواع ً تعقيدا باستخدام ُمفس ٍر مختلف آللة أخرى، العتاد ،بينما من املمكن نقل البرامج املكتوبة بلغة أكثر نسخة من البرنامج بلغة اآللة من أجل آلة أخرى. أو إعادة جمع الشيفرة إلنشاء ٍ وتتم هذه العملية عبر املفسرات ( (interpretersواملترجمات ).(compilers َ يقرأ املفسر البرنامج املصدري كما كتبه املبرمج ،ويحلله ،ويفسر تعليماته مباشرة لآللة .تستخدم برمجي لتعالجه بايثون هذه التقنية ،فعند تشغيلنا لبايثون بشكل تفاعلي ،نستطيع كتابة سطر ٍ ً سطر آخر. بايثون مباشرة ،ثم تنتظر كتابة ٍ قد نحتاج لتذكر قيم معينة الستخدامها ً ً أسماء لتلك القيم لنتمكن من الحقا في البرنامج ،فنختار حفظها واسترجاعها حين نحتاجها ،وندعو هذه األسماء "املتغيرات". >>> x = 6 )>>> print(x 6 >>> y = x * 7 الفصل األول :ملاذا نتعلم البرمجة؟ 11 )>>> print(y 42 >>> في هذا املثال ،طلبنا من بايثون تخزين القيمة ،6وحفظناها في متغير اسمه xلنتمكن من استرجاعها ً الحقا ،وتأكدنا من أن بايثون قد تذكرت ذلك عندما استخدمنا تابع الطباعة .printبعد ذلك ،طلبنا من بايثون استعادة تلك القيمة لضربها بالعدد 7لنحفظ الناتج في املتغير ،yثم طلبنا من بايثون أن تطبع قيمة .y قيما َّ تعامل بايثون هذه األوامر كسلسلة مترابطة من التعليمات ،حيث تسترجع ً مخزنة من تعليمات سابقة مع أننا كتبنا كل سطر بمفرده ،وبذلك نكون قد كتبنا برنامجنا األول البسيط ،وهو مكون من أربع عبارات مرتبة ً ًّ منطقيا. ترتيبا يميل املفسر إلى نمط املحادثة التفاعلية كما في املثال السابق ،في حين يحتاج املترجم أن يستلم ً لينفذ ً كامال في ملف ،حيث يحوله إلى لغة اآللة ،ثم يحفظ البرنامج الناتج في ملف َّ الحقا. البرنامج وهذه البرامج املكتوبة بلغة اآللة ،والقابلة للتنفيذً ، غالبا ما تحمل الالحقة " ".exeأو " ".dllعلى نظام ويندوز ،والتي ترمز إلى " "executableو" ،"dynamic link libraryبينما ال توجد لواحق مشابهة في بشكل غير أنظمة لينوكس وماكنتوش ،وإن حاولت فتح ملف تنفيذ في محرر النصوص ،فسيظهر ٍ مقروء كاآلتي: ^?ELF^A^A^A^@^@^@^@^@^@^@^@^@^B^@^C^@^A^@^@^@\xa0\x82^D^H @^4^@^@^@\x90^]^@^@^@^@^@^@4 ^@^G^@(^@$^@!^@^F^@^@^@4^@^@^@4\x80^D^H4\x80^D^H\xe0^@^@^@\x e0^@^@^@^E^@^@^@^D^@^@^@^C^@^@^@^T^A^@^@^T\x81^D^H^T\x81^D ^H^S^@^@^@^S^@^@^@^D^@^@^@^A^@^@^@^A\^D^HQVhT\x83^D^H\xe8 …. ليس من السهل القراءة والكتابة بلغة اآللة ،فمن حسن حظنا أننا نملك املفسرات واملترجمات ،مما يسمح لنا بالبرمجة بلغات عالية املستوى مثل بايثون وس ي .C لعلك تتساءل اآلن :ماذا عن مفسر بايثون؟ وبأي لغة ُكتب؟ وما الذي يحدث ً تماما عندما نكتب ""Python؟ ُ ٌ مفسر بايثون مكتوب بلغة عالية املستوى تدعى س ي " ،"Cويمكنك رؤية الشيفرة البرمجية املصدرية له بالبحث عنه في موقع ُ .www.python.orgت ُّ برنامجا َ ً عد لغة بايثون يترجم بدوره إلى لغة اآللة ،لذلك الفصل األول :ملاذا نتعلم البرمجة؟ 12 فإن تنصيبك لبايثون على حاسوبك يعني أنك قد نقلت نسخة من برنامج بايثون َ املترجم إلى لغة اآللة ً موجودا ً غالبا تحت االسم التالي: إلى نظامك ،وفي ويندوز يكون ملف التنفيذ C:\Python35\python.exe ُ قد ال تحتاج هذه املعلومات لتبرمج بلغة بايثون ،لكن من املفيد اإلجابة عن هذه األسئلة امللحة منذ البداية. 7.1كتابة برنامج ً ُ تعتبر كتابة األوامر في مفسر بايثون طريقة رائعة الختبار بعض مميزات بايثون ،ولكن ال يوص ى بها عند محاولة حل مشكالت معقدة ،لذلك سنستخدم محرر نصوص عند البرمجة لنكتب تعليمات بايثون في ملف يدعى ًّ ًّ َ املتعارف عليه أن تملك النصوص البرمجية في بايثون برمجيا ( ،)scriptومن نصا الالحقة ".".py لتنفيذ النص البرمجي ،يجب أن تخبر مفسر بايثون باسم امللف ،حيث نكتب في نافذة األوامر python hello.pyما يأتي: $ cat hello.py )' !print ('Hello world $ python hello.py !Hello world ُ تعبر عالمة الدوالر $عن إشارة نظام التشغيل ،ويخبرنا األمر cat hello.pyأن امللف hello.pyيحوي ً برنامجا ذا سطر واحد يطبع ًّ نصا ،ثم نستدعي مفسر بايثون لنطلب منه قراءة الشيفرة املصدرية َ ً بدال من أن نكتبه ًّ يدويا ،وكما تالحظ ،فإن بايثون تعلم أن عليها التوقف عن من امللف hello.py التنفيذ عند الوصول إلى نهاية امللف الذي تقرأ منه برنامجك ،لذلك لسنا مضطرين الستخدام )( quitفي نهاية البرنامج في امللف. 8.1ما هو البرنامج؟ ُ ُ َّ أمر ما، يعرف البرنامج في بايثون باختصار على أنه :سلسلة من تعليمات بلغة بايثون ،وضعت لتنفيذ ٍ ً برنامجا ذا سطر واحد ،على الرغم من أنه غير مفيد ًّ عمليا، وحتى النص البرمجي ُ hello.pyيعتبر ٍ ُ نطرحها للتغلب على املشكلة التي تواجهنا. فالبرنامج هو طريقة الحل التي الفصل األول :ملاذا نتعلم البرمجة؟ 13 ً اجتماعي يتناول منشورات ببحث القيام تريد ك أن ولنفترض الواقع، أرض من مثاال لنتناول اآلن ٍ فيسبوك ،وتريد معرفة الكلمة األكثر تكر ًارا في مجموعة معينة من املنشورات .يمكنك ً طبعا طباعة شيوعا ،لكن هذه العملية ستستغرق ً ً كل تلك املنشورات وفحصها ًّ وقتا يدويا إليجاد الكلمة األكثر ً طويال ،وقد ال تصل إلى الناتج الصحيح في النهاية ،لكنك باستخدام بايثون ستنجز هذه العملية بدقة وقت ممتع في عطلة نهاية األسبوع. وسرعة ،مما يسمح لك بقضاء ٍ ً انظر مثال إلى النص أدناه ،والذي يدور حول مهرج وسيارة ،واستخرج منه الكلمة األكثر تكر ًارا وعدد مرات تكرارها: The clown ran after the car and the car ran into the tent and the tent fell down on the clown and the car َّ ثم تخيل أنك تستخرج الكلمة األكثر تكر ًارا من نص مؤلف من ماليين األسطر .لعلك اقتنعت اآلن أنه ً برنامج ُيحص ي لك عدد مرات تكرار الكلمات ،بدال من تنفيذ من األسرع تعلم لغة بايثون ثم كتابة ٍ ً هذا ًّ يدويا .أما إذا أردت َّ برنامجا قد حل هذه املسألة اآلن ،فأنت محظوظ ألن هذا الكتاب يقدم لك ُكت َب ُ واختبرُ ،ونقدمه لك على طبق من ذهب لترى بعينك ً بعضا من عظمة بايثون: )' name = input ('Enter file: )'handle = open (name, 'r )(counts = dict for line in handle: )(words = line.split for word in words: counts[word] = counts.get(word, 0) + 1 bigcount = None bigword = None for word, count in list(counts.items()): if bigcount is None or count > bigcount: bigword = word bigcount = count )print(bigword, bigcount # Code: http://www.py4e.com/code3/words.py الفصل األول :ملاذا نتعلم البرمجة؟ 14 تستطيع استخدام هذا البرنامج حتى لو لم تكن تعلم لغة بايثون ،ولكنك ستحتاج أن تصبر حتى الفصل العاشر من هذا الكتاب لفهم طريقة عمله ،أما اآلن فأنت مستخدم للبرنامج وحسب، وبإمكانك أن تستخدمه وترى مدى ذكائه ومقدار الوقت الذي وفره .كل ما عليك فعله هو أن تكتب ً هذا البرنامج في ملف ،ثم أن تسميه words.pyمثال ،أو أن تنزل البرنامج األصلي من املوقع: /http://www.py4e.com/code3ثم تشغله. وهو مثال جيد ليؤكد على دور بايثون كوسيط بينك كمستخدم ،وبين املبرمج .صار بوسعنا تبادل عدة تعليمات مفيدة (أي برامج) باستخدام لغة شائعة يستطيع ُّ شخص استخدامها بمجرد أي ٍ تنصيب بايثون على حاسوبه ،فنحن ال نكلم بايثون مباشرة ،بل نتواصل فيما بيننا بواسطتها. ّ ّ األساسية للبرامج املكونات 9.1 في الفصول القادمة سنتعلم أكثر حول مفردات بايثون ،وبنيتها ،وكيف ندمج بينها لبناء برامج مفيدة، َ املستخدمة لكتابة البرامج ،وهي ليست خاصة لكن قبل ذلك ،لنتعرف إلى بعض املفاهيم األساسية ببايثون ،بل هي جزء من كل لغة برمجة ،سواء كانت عالية املستوى أم لغة آلة ،وهي: الدخل :الحصول على البيانات من العالم الخارجي ،كقراءة بيانات معينة من ملف ما ،أو حساس كاملايكروفون ،أو نظام تحديد املواقع .GPSسيكون ُ دخل برامجنا األولى عبر لوحة مفاتيح يتحكم بها املستخدم. الخرج :ويتمثل في عرض نتائج البرنامج على شاشة ما ،أو تخزينها في ملف ،أو إرسالها إلى جهاز خرج كمكبر الصوت لعرض موسيقى معينة أو قراءة نص. التسلسلي :تنفيذ األوامر ت ً ّ باعا. التنفيذ تفقد ُّ الشرطيُّ : تحقق شروط معينة وتنفيذ أو تخطي سلسلة من التعليمات ً ّ بناء على تلك التنفيذ الشروط. ً التنفيذ التكرار ّي :تنفيذ عدد معين من التعليمات بشكل متكرر ،ويتضمن هذا عادة بعض التغييرات. إعادة االستخدام :كتابة عدد معين من التعليمات ،ثم تسميتها باسم َّ محدد الستدعائها عند اللزوم خالل البرنامج. ُ لعلك تجد هذه املفاهيم ساذجة ،كأننا نعرف املش ي على أنه عملية وضع قدم أمام األخرى ،لكن إليك السر :البرمجة فن ندمج فيه بين تلك العناصر األساسية بطريقة تجعلها مفيدة وفعالة. الفصل األول :ملاذا نتعلم البرمجة؟ 15 10.1ما األخطاء التي يمكن أن نواجهها؟ يجب التزام الدقة عند التواصل مع بايثون كما أينا ً سابقا ،فأصغر خطأ سيدفع بايثون للتوقف عن ر تنفيذ البرنامج ،لذلك يظن بعض املبرمجين املبتدئين أن هذا ٌ دليل على أن بايثون تكرههم وتبغضهم، في حين أنها تفضل املبرمجين اآلخرين عليهم ،لذا فهي ترفض برامجهم املثالية ،وتعتبرها غير صحيحة، ً متقصدة إحراجهم. ' !>>> primt 'Hello world File "<stdin>", line 1 ' !primt 'Hello world ^ SyntaxError: invalid syntax )’>>> primt (‘Hello world Traceback (most recent call last): >File "<stdin>", line 1, in <module NameError: name 'primt' is not defined !>>> I hate you Python File "<stdin>", line 1 !I hate you Python ^ SyntaxError: invalid syntax >>> if you come out of there, I would teach you a lesson File "<stdin>", line 1 if you come out of there, I would teach you a lesson ^ SyntaxError: invalid syntax >>> َّ مستعدة لخدمتك متى احتجتها، لن يفيد الجدال مع بايثون ،فهي مجرد أداة بال مشاعر ،ومع ذلك هي وإن بدت التحذيرات التي تظهرها قاسية ،فهي في الواقع تطلب مساعدتك ،وكل ما في األمر أنها َّ تفحصت ما َ كتبته لها ،إال أنها لم تتمكن من فهمه ،إذ إنها أشبه بحيوان أليف مدلل يحب َك بشدة، منتظرا إياك أن تكتب ً ً شيئا يفهمه، إال أنه ال يفهم إال بضع كلمات مفتاحية ،ويرمقك بنظرة بريئة <<< الفصل األول :ملاذا نتعلم البرمجة؟ 16 وعندما تقول بايثون ،SyntaxError: Invalid syntax :فهي ببساطة تهز ذيلها وتقول" :يبدو أنك أردت أن تقول ً شيئا ،إال أني ال أفهمه ،ولكن أرجو أن تواصل التحدث إلي <<< ". ستواجهك ثالثة أخطاء رئيسية عند البرمجة باستخدام بايثون: ّ ً إصالحا ،وتعني أنك القواعدية ) :(Syntax errorsوهي أول األخطاء التي سترتكبها ،وأسهلها األخطاء أخطأت في "القواعد اللغوية" لبايثون ،وستحاول بايثون اإلشارة إلى السطر والحرف الذي الحظت ُ وجود الخطأ فيه .قد تخدعك بايثون بأن تشير إلى وجود خطأ في موضع معين ،في حين أن الخطأ ً الفعلي يقع قبل ذلك ،لذا ابدأ من حيث أشارت بايثون صعودا حتى تجد ذلك الخطأ. ّ املنطقية ( :)Logic errorsوتحدث عندما ال توجد أخطاء قواعدية ،إنما مشكلة في ترتيب األخطاء بعض التعليمات أو الربط بينها ،كأن يخبرك أحدهم أنه فتح زجاجة املاء ليشرب منها ،ثم وضعها في حقيبته وتابع سيره ،وبعد ذلك أغلق الزجاجة. أخطاء ّ داللية ( :)Semantic errorsوتحدث عندما تكون قواعد برنامجك صحيحة ومرتبة ً ترتيبا ًّ منطقيا دون أن يؤدي املطلوب منه ،فلو أردت أن تعطي أحدهم التوجيهات للذهاب إلى أحد املطاعم ً ً فقلت له" :اتجه ً واحدا وستجد يسارا عندما تصل إلى التقاطع عند محطة البنزين ،ثم سر ميال ً مطعما ذا لو ٍن أحمر إلى يسارك" ،ثم بعد فترة يتصل بك هذا الشخص ليخبرك بأنه وصل إلى مزرعة مطعما ،فستسأله" :هل اتجهت ً ً يمينا أم ً يسارا عند محطة البنزين؟" ،ليجيبك" :لقد اتبعت وليس توجيهاتك بحذافيرها ،بل إني كتبتها على ورقة حتى ال أنساها" ،ثم تفكر للحظة وتحك رأسك ثم تقول: ً "أنا آسف يا صديقي ،فقد كانت توجيهاتي صحيحة من حيث القواعد ،إال أن خطا في دالالتها قد فاتني". فما تقوم به بايثون في كل تلك الحاالت هو تنفيذ ما تطلبه منها قدر استطاعتها. 11.1التنقيح ً عندما تعلن بايثون عن وجود خطا ،أو حتى عندما تمنحك نتيجة مختلفة عما أردت ،تبدأ عملية تنقيح البرنامج .والتنقيح هو عملية اكتشاف أسباب األخطاء في برنامجك. ً إليك أربعة أساليب لتستخدمها خاصة مع األخطاء صعبة املالحظة: القراءة :افحص برنامجك واقرأه وتأكد من أنه مكتوب كما َ أردت ً تماما. التجريب :جرب بعض التغييرات ،ثم شغل البرنامج مرة أخرى ،وستظهر املشكلة إذا تأكدت من أن وقتا ً كل ش يء في مكانه الصحيح ،لكن قد يستغرق األمر ً أحيانا. الفصل األول :ملاذا نتعلم البرمجة؟ 17 ُّ التريثَّ : تمهل وفكر واسأل نفسك حول نوع الخطأ الذي يواجهك :قواعدي ،أم خطأ أثناء التشغيل، أم داللي؟ وما هي املعلومات التي ستحصل عليها من رسائل األخطاء أو خرج البرنامج؟ وما التغيير األخير الذي أجريته على البرنامج قبل ظهور املشكلة؟ التراجع :عند نقطة معينة ،سيكون أفضل ما تستطيع فعله هو التراجع وإلغاء التغييرات التي أجريتها ً برنامج يعمل وبإمكانك فهمه ،ومن ثم تستطيع أن تعيد بناءه ثانية. حتى تحصل على ٍ يقع املبرمجون املبتدئون في خطأ االعتماد على إحدى هذه الطرق دون غيرها ،إال أن إيجاد خطأ صعب ً وأحيانا التراجع ،فإن لم تنجح ُ املالحظة يتطلب القراءة والتنفيذ ُّ أحدها ،جرب األخرى. والتريث، ًّ قواعديا ،ولكنها لن تفيد في حالة األخطاء فعلى سبيل املثال ،قد تنجح طريقة القراءة إن كان الخطأ الداللية ،فالخطأ هنا موجود داخل رأسك ،ولن تكتشفه إن كنت ال تفهم ما يفعله برنامجك حتى ولو قرأت البرنامج مائة مرة. تجارب على البرنامج ،إال أن ذلك غير ممكن دون قراءة وفهم قد يساعد في حل املشكلة إجر ُاء ٍ برنامجك ،وإال ستقع فيما نسميه في هذا الكتاب بنمط "البرمجة العشوائية" ،وهو عملية تنفيذ ً تغييرات عشوائية على البرنامج حتى ينفذ املطلوب ،وهو نمط يستلزم ً وقتا طويال بالطبع. ستحتاج ً وقتا للتفكير في كل األحوال ،فالتنقيح كالتجارب العملية ،حيث تبدأ بوضع فرضية واحدة على األقل حول ماهية املشكلة ،وفي حال وجود احتمالين أو أكثر ،تحاول وضع اختبار يستبعد أحد تلك االحتماالت. استرخ ،ثم حاول مرة أخرى .تحدث مع اآلخرين ،أو حتى مع نفسك ،وحاول شرح املشكلة لعلك تجد الحل بمجرد عرض املشكلة. ً ً فغالبا لن تنفع معك أفضل تقنيات التنقيح، ضخما ومعق ًدا، إن كان برنامجك مليء باألخطاء ،أو برنامج فعال تستطيع فهمه. وعندها يكون الحل األفضل هو التراجع وتبسيط البرنامج لتحصل على ٍ ً لكن عادة ما يتجنب املبرمجون املبتدئون عملية التراجع ،حيث يعز عليهم حذف سطر من برنامجهم ً َ ً ملف آخر قبل تجزئته، حتى وإن كان خاطئا .إن شعرت بذلك مستقبال ،فبإمكانك نسخ برنامجك إلى ٍ ثم تستطيع إعادة لصق كل جزء على حدة. الفصل األول :ملاذا نتعلم البرمجة؟ 18 ّ 12.1رحلة التعلم َ نفسك ال تقلق إن شعرت أن املفاهيم غير مترابطة جي ًدا أثناء قراءتك األولى لهذا الكتاب ،وتذكر ً َ عندما بدأت تتعلم التحدث ،حينما َ استغرقت أصواتا طفولية ظريفة في البداية ،ثم كنت تصدر حوالي ستة أشهر لتعلم تكوين جمل بسيطة من املفردات القليلة التي تعرفها ،وبعد خمس أو ست َ َ واحتجت بضع سنوات أخرى لتكتب قصة قصيرة كاملة انتقلت من الجمل إلى فقرا ٍت كاملة، سنوات ومثيرة لالهتمام بمفردك. نطمح لتعليمك بايثون خالل وقت أقصر بكثير ،لذلك سنكثف املحتوى في الفصول التالية .وكما في ُّ ً حال تعلمك لغة جديدة ،ستحتاج بعض الوقت الستيعابها وفهمها قبل أن تعتاد عليها ،ومن الطبيعي أن تشعر ببعض االرتباك أثناء طرحنا ملواضيع تتعرف عليها للمرة األولى ،حيث نحاول شرح تفاصيل ًّ تدريجيا ،إال أنك غير مضطر لدراسة الكتاب بشكل منظم ،وتستطيع التقدم الصورة العامة بالقراءة ،ومن ثم العودة إلى الفصول السابقة ،فمجرد تعرضك لتلك املواضيع املتقدمة يزيد من استيعابك للبرمجة بشكل كبير ،حتى وإن لم تتعمق في تفاصيلها ،وعند مراجعتك ملا سبق وإعادة حل ُّ مسائله ستدرك قدرتك على التعلم. ستمر ببعض لحظات اإلبداع التي يشعر بها فنان يطرق بمطرقته وإزميله ،ثم يتوقف لينظر إلى جمال صنعه وعجيب نحته ،وإن واجهت معضلة صعبة ،فال فائدة من التحديق بها طوال الليل ،بل خذ استراحة أو غفوة ،أو تناول وجبة خفيفة ،واشرح ألحدهم مشكلتك (أو حتى لحيوانك األليف)، ثم بإمكانك العودة للدراسة مجد ًدا بذهن متيقظ .نضمن لك أنك حين تعود للفصول األولى في هذا ً ً الكتاب بعد أن تتمكن من البرمجة ،ستجد أن األمر كان بسيطا وسهال ،وكل ما كان يلزمك هو بعض الوقت لتستوعبه. 13.1فهرس املصطلحات • الخطأ ( :)Bugخطأ في البرنامج. ّ املركزية ( :)central processing unitقلب الحاسوب الذي يشغل • وحدة املعالجة البرنامج الذي كتبناه ،كما ُيدعى " "CPUأو "املعالج". • الترجمة ) :)compileترجمة برنامج مكتوب بلغة عالية املستوى إلى لغة منخفضة املستوى تجهيزا لتنفيذه ً ً الحقا. دفعة واحدة الفصل األول :ملاذا نتعلم البرمجة؟ 19 • لغة عالية املستوى ( :)high-level languageلغة برمجية ،مثل بايثونَّ ، مصممة لتكون سهلة القراءة والكتابة للبشر. ّ التفاعلي ( :)interactive modeطريقة الستخدام مفسر بايثون عبر كتابة األوامر • النمط والتعليمات بعد إشارة التلقين. • التفسير( :(interpretتنفيذ برنامج مكتوب بلغة عالية املستوى بترجمة أسطره الواحد تلو اآلخر. َّ مصممة لتكون سهلة • لغة منخفضة املستوى ) :(low-level languageلغة برمجة التنفيذ على الحاسوب ،وتدعى ً أيضا بلغة اآللة أو لغة التجميع. • شيفرة اآللة ) :(machine codeأقل مستوى من لغات البرمجة ،وهي اللغة التي تنفذها وحدة املعالجة املركزية بشكل مباشر. الرئيسية ) :(main memoryتخزن البرامج واملعلومات ،وتفقد البيانات َّ ّ املخزنة • الذاكرة فيها عند انقطاع الطاقة عنها. • • • • برنامج ما وتحليل بنيته القواعدية. التحليل ) :)parseفحص ٍ ّ قابلية النقل ( :(portabilityميزة للبرنامج تسمح له بالعمل على عدة أنواع من الحواسيب. ً تابع :printتعليمة تجعل مفسر بايثون يعرض قيمة ما على الشاشة. ّ املشكلة وإيجاد حل لها والتعبير عنه. حل املشاكل ) :(problem solvingعملية تحليل ٍ • البرنامج ) :(programمجموعة من التعليمات تنفذ عملية حاسوبية. ّ ً منتظرا املستخدم ليدخل موجه األوامر ) :(promptعندما يعرض برنامج ما رسالة معينة • ِّ قيمة إلى البرنامج. ّ الثانوية ) :(secondary memoryتخزن البرامج واملعلومات وتحتفظ بها حتى إن • الذاكرة ُ قطعت عنها الكهرباء ،ولكنها أبطأ من الذاكرة الرئيسية ،مثل :أقراص التخزين ،والذواكر املتنقلة .USB • دالالت ) :(semanticsمعنى وهدف البرنامج. داللي ( :)semantic errorخطأ في البرنامج يجعله ينفذ ً ً • خطأ ّ مختلفا عما أراده املبرمج. شيئا • البرنامج املصدر ّي ) :)source codeبرنامج مكتوب بلغة عالية املستوى. الفصل األول :ملاذا نتعلم البرمجة؟ 20 14.1تمارين • التمرين األول :ما وظيفة الذاكرة الثانوية في الحاسوب؟ oتنفيذ كل العمليات الحاسوبية واملنطقية في برنامج ما. oاستدعاء صفحات الويب عبر اإلنترنت. oتخزين املعلومات ملدة طويلة حتى بعد انقطاع الكهرباء. o استالم الدخل من املستخدم. • التمرين الثاني :ما تعريف البرنامج؟ • التمرين الثالث :ما الفرق بين املفسر واملترجم؟ • التمرين الرابعٌّ : أي مما يأتي يتضمن شيفرة اآللة؟ oمفسر بايثون. oلوحة املفاتيح. oامللف املصدري لبايثون. oملف نص ي. • التمرين الخامس :ما الخطأ في البرنامج التالي: ' !>>> primt 'Hello world File "<stdin>", line 1 ' !primt 'Hello world ^ SyntaxError: invalid syntax >>> • التمرين السادس :بعد تنفيذ السطر البرمجي التالي ،أين َّ يخزن املتغير " "xفي الحاسب؟ X = 123 oوحدة املعالجة املركزية. oالذاكرة الرئيسية. oالذاكرة الثانوية. oأجهزة الدخل. oأجهزة الخرج. الفصل األول :ملاذا نتعلم البرمجة؟ 21 • التمرين السابع :ما هي نتيجة البرنامج اآلتي؟ x = 43 x=x+1 )print(x 43 o 44 o x+1 o ً رياضيا oخطأ ألن x=x+1غير صحيحة ً ً ًّ ذاكرا مثاال عن القدرة البشرية املكافئة: • التمرين الثامن :اشرح كال مما يأتي oوحدة املعالجة املركزية. oالذاكرة الرئيسية. oالذاكرة الثانوية. oأجهزة الدخل. oأجهزة الخرج. على سبيل املثال :ما هو املقابل البشري لوحدة املعالجة املركزية؟ • التمرين التاسع :كيف تصحح الخطأ القواعدي؟ الفصل الثاني املتغيرات والتعابير والتعليمات الفصل الثاني :املتغيرات والتعابير والتعليمات 23 ّ املتغيرات والتعابيروالتعليمات 2 1.2القيم و أنواع البيانات ُ تعد القيمة ) (valueواحدة من املفاهيم األساسية التي يتعامل معها البرنامج ،فالحروف واألرقام هي بعض األمثلة عن القيم ،مثل 1و 2و" ."Hello worldتنتمي هذه القيم إلى َ نوعين مختلفين من أنواع البيانات ،فالقيمة 2هي عدد صحيح ،integerأما " ،"Hello worldفهي سلسلة نصية ،string ً ُ وسميت بذلك ألنها تحوي سلسلة من املحارف .يمكن تمييز السلسلة النصية من عالمة االقتباس املزدوجة " ". تتعامل تعليمة الطباعة printمع كل من السالسل النصية واألعداد الصحيحة. ليبدأ املفسر بالعمل ،علينا كتابة األمر pythonكما يلي: python )>>> print(4 4 إذا لم تكن متأك ًدا من نوع القيمة ،فاملفسر سيخبرك بذلك: )' !>>> type ('Hello, World > '<class 'str )>>> type(17 >'<class 'int للتوضيح ،فالقيمة " "Hello Worldتنتمي إلى نوع السلسة النصيةُ ،وي َّ عبر عنها برمز .strوباملثل ،تنتمي القيمة 17إلى األعداد الصحيحة ،intأما األرقام التي تحوي فاصلة عشرية ،فهي تنتمي إلى نوع األعداد ذات الفاصلة العشرية ،floatوتأتي التسمية من طريقة تمثيل هذه األعداد ،والتي تدعى floating .point )>>> type(3.2 >'<class 'float ُ أما القيم مثل " "17و" ،"3.2فهي تبدو كأرقام ،ولكن بسبب وجود عالمة االقتباس تعتبر سالسل نصية. الفصل الثاني :املتغيرات والتعابير والتعليمات 24 )'>>> type('17 >'<class 'str )'>>> type('3.2 >'<class 'str قد يلجأ البعض عند كتابة عدد صحيح كبير إلى وضع فواصل بين خانة العشرات واملئات واأللوف... ً ً خاطئا للعدد الصحيح ،ولكن في نفس الوقت إلخ ،مثل ،1,000,000لكن لغة بايثون تعتبر هذا تمثيال ستتعامل معه في تعليمة الطباعة كما يلي: )>>> print(1,000,000 100 ٌ َّ نتيجة غير متوقعة ،فلغة بايثون تفسر 1,000,000على أنها مجموعة أعداد صحيحة مستقلة ُ تفصل بينها فاصلة ،فيظهر على الخرج األعداد املبينة وبينها فراغات .تمثل هذه الحالة ما ُيعرف بالخطأ الداللي ( ،)semantic errorحيث َّ تنفذ الشيفرة البرمجية دون رسالة خطأ ،لكنها ال تعطي َّ الخرج أو النتيجة الصحيحة املتوقعة. ّ املتغيرات 2.2 ُ تعد القدرة على التالعب باملتغيرات أحد أقوى ميزات لغة البرمجة ،واملتغير هو اسم يشير إلى قيم. تنش ئ تعليمة اإلسناد ) )assignment statementمتغيرات جديدة ،وتعطيها قيم: '>>> message = 'And now for something completely different >>> n = 17 >>> pi = 3.1415926535897931 نالحظ في املثال ثالث عمليات إسناد :األولى إسناد سلسلة نصية إلى متغير جديد ُيسمى ،message أما الثانية ،فإسناد العدد الصحيح 17للمتغير ،nأما الثالثة ،فإسناد القيمة التقريبية لـ πللمتغير .pi إلظهار قيمة املتغير بإمكانك استخدام تعليمة الطباعة :print )>>> print(n 17 )>>> print(pi 3.141592653589793 الفصل الثاني :املتغيرات والتعابير والتعليمات 25 ُ نوع املتغير هو نوع القيمة التي يمثلها: )>>> type(message >'<class 'str )>>> type(n >'<class 'int )>>> type(pi >'<class 'float ّ ّ املفتاحية املتغيرات والكلمات 3.2أسماء يختار املبرمجون عادة أسماء املتغيرات ) (variablesبحيث تكون ذات معنى وتعكس الهدف من استخدامها. ًّ يمكن ألسماء املتغيرات أن تكون ذات أطوال مختلفة ،وقد تتضمن كال من األحرف واألرقام ،لكن ال يمكن أن يبدأ اسم املتغير برقم ،كما ُيسمح باستخدام الحروف الكبيرة ،ولكن من األفضل أن يبدأ اسم املتغير بحروف صغيرة (سنرى السبب ً الحقا). ُيسمح بوجود رمز الشرطة السفلية _ في اسم املتغيرُ ،وتستخدم ً غالبا في أسماء املتغيرات التي تحوي العديد من الكلمات ،مثل ،my_name :أو .air_speed_of_unladen_swallow َ ُ وقد تبدأ أسماء املتغيرات بالشرطة السفلية _ ،لكن بشكل عام نتجنب ذلك إن لم نكن نكتب شيفرة ملكتبة برمجية قد يستخدمها اآلخرون. إذا اخترت ً اسما غير مسموج ملتغير ،فستتلقى رسالة خطأ قواعدي ).(syntax error '>>> 76trombones = 'big parade SyntaxError: invalid syntax >>> more@ = 1000000 SyntaxError: invalid syntax '>>> class = 'Advanced Theoretical Zymurgy SyntaxError: invalid syntax ُ اسم املتغير 76trobonesغير مسموح ألنه يبدأ برقم ،واسم املتغير @ moreغير مسموح ألنه يحتوي على رمز @ غير املسموح ،لكن ما املشكلة في اسم املتغير class؟ كلمة classهي إحدى الكلمات املفتاحية ( )keywordsفي لغة بايثون ،فاملفسر يستخدم الكلمات الفصل الثاني :املتغيرات والتعابير والتعليمات 26 املفتاحية للتعرف على بنية البرنامج ،وبالتالي ال يمكن استخدامها كأسماء متغيرات .تخزن لغة بايثون 35كلمة مفتاحية: True None from del and try nonlocal global elif as while not if else assert with or import except break yield pass in False class async raise is finally continue await return lambda for def ُي َّ فضل أن تحتفظ بهذه القائمة أعاله ،وإذا أعطى املفسر تنبيه ًًا حول أحد أسماء املتغيرات ولم تعرف السبب ،فانظر إن كانت إحداها في تلك القائمة. 4.2التعليمات التعليمة هي ٌ جزء من الشيفرة البرمجية يستطيع مفسر بايثون تنفيذها. رأينا ساب ًقا نوعين من التعليمات :تعليمة printبوصفها تعليمة تعبير )،(expression statement وتعليمة اإلسناد (.)assignment ُ عندما تكتب تعليمة في الوضع التفاعلي )ُ ،)interactive modeينفذها املفسر ويعرض النتيجة كما لو أن هناك تعليمة واحدة فقط. ً بينما يتضمن النص البرمجي عادة سلسلة من التعليمات ،فتظهر النتائج واحدة تلو األخرى أثناء ً تنفيذ التعليمات .ففي النص البرمجي التالي مثال: )print(1 x=2 )print(x سيظهر الخرج بالترتيب: الفصل الثاني :املتغيرات والتعابير والتعليمات 27 1 2 ُ وال تظهر تعليمة اإلسناد أي خرج. 5.2العوامل واملعامالت العوامل (ٌ (operators موز خاصة بالعمليات الحسابية ،مثل الجمع والضرب. ر ُتسمى القيم التي ُت َّ طبق العوامل عليها باملعامالت (.(operands ُ العوامل ** / * - +تمثل الجمع والطرح والضرب والقسمة والرفع إلى قوة ،كما في األمثلة التالية: 20+32 hour-1 hour*60+minute minute/60 5**2 )(5+9)*(15-7 وقد حصل ٌ تغيير في عامل القسمة بين نسخة Python2.xونسخة ،Python3.xففي ،Python3.x ً تحوي نتيجة عملية القسمة التالية فاصلة عشرية: >>> minute = 59 >>> minute/60 0.9833333333333333 أما العامل ذاته في Python2.0فيقسم العددين الصحيحين ُويقرب النتيجة لعدد صحيح فقط: >>> minute = 59 >>> minute/60 0 استخدم عامل القسمة ذي التقريب لألدنى ( )//للحصول على نفس اإلجابة في .Python3.0 >>> minute = 59 >>> minute//60 0 تعمل توابع قسمة العدد الصحيح في Python3.0كما لو أنك تستخدم آلة حاسبة لحساب ناتج الفصل الثاني :املتغيرات والتعابير والتعليمات 28 القسمة. 6.2التعابير ُي َعد التعبير ً مزيجا من القيم واملتغيرات والعواملُ ،وت َع ُّد القيمة بمفردها ً تعبيرا ،وينطبق األمر ذاته ُ ُ على املتغير .وفي املثال التالي ،تعد جميع التعابير التالية صحيحة (على فرض أن املتغير xقد أسند إلى قيمة): 17 x x + 17 إذا كتبت تعبي ًرا في الوضع التفاعلي ( ،)interactive modeفسيفسره املفسر ويعرض النتيجة: >>> 1 + 1 2 إال أن التعبير لوحده ال يقوم بش يء في النص البرمجي ،وهذا أحد األمور الشائعة التي تحير املبتدئين. التمرين :1اكتب التعليمات التالية في مفسر بايثون لترى ما تقوم به: 5 x =5 x +1 ّ ّ العمليات تراتبية 7.2 عندما يظهر أكثر من عامل في التعبير ،تعتمد تراتبية الحل على قواعد األسبقية ،ففي العمليات الرياضية ،تتبع بايثون االصطالحات الرياضية املعروفة. ُيشكل االختصار PEMDASطريقة مفيدة لتذكر القواعد التالية: األقواس ( )Parenthesesلها األسبقية ،ويمكن استخدامها للحل بالترتيب الذي تريده .بما أنً ُ التعبيرات بين قوسين ت َحل أوال ،فالعملية الرياضية ) 2*(3-1تعطي ،4والعملية الرياضية ) (1+1)**(5-2تعطي . 8 ويمكن استخدام األقواس لتسهيل قراءة التعبير ،كما في املثال ،(minute*100)/60حتى لو لم تغير النتيجة. الفصل الثاني :املتغيرات والتعابير والتعليمات 29 يمثل عامل الرفع إلى قوة ( )Exponentiationاألسبقية التالية بعد األقواس ،فالعملية الرياضية 2**1+1ناتجها ،3وليس ،4و 3*1**3ناتجها 3وليس .27 أما الضرب ( )Multiplicationوالقسمة ( ،)Divisionفلهما نفس األسبقية ،والتي تسبق عمليتاالجمع ( )Additionوالطرح ( )Subtractionاللتان لهما نفس األولوية ،لذلك 2*3-1ناتجها ،5وليس ،4و 6+4/2ناتجها ،8وليس .5 ُت َّ قيم العوامل التي تملك نفس األولوية من اليسار إلى اليمين ،لذلك ناتج التعبير 5-3-1يساوي ،1 ً ً أقواسا في تعبيراتك وليس ،3ألن 5-3تحدث أوال ،ثم 1مطروح من .2لتجنب الشك في األولوية ،ضع دائما للتأكد من أن إجراء الحسابات يحدث بالترتيب الذي ُ ً تريده. 8.2عامل باقي القسمة يعمل مع األعداد الصحيحة ،ويعطي باقي قسمة املعامل األول على الثاني. َّ ُيمثل في لغة بايثون عامل باقي القسمة بإشارة ،%والقواعد هي نفسها بالنسبة ألي عامل آخر. >>> quotient = 7 // 3 )>>> print(quotient 2 >>> remainder = 7 % 3 )>>> print(remainder 1 أي 7مقسومة على 3يساوي 2مع الباقي .1 ً على عكس ما يبدو ،يملك عامل باقي القسمة فائدة كبيرة ،إذ يمكنك مثال التحقق من قابلية قسمة أحد األرقام على رقم آخر ،فإذا كانت ( X%Yأي باقي قسمة Xعلى )Yتساوي الصفر ،يكون الرقم X ً قابال للقسمة على .Y ً كما يمكن استخراج رقم أو عدة أرقام موجودة في أقص ى يمين عدد ،فمثال العملية X%10تعطي الرقم املوجود أقص ى اليمين من Xفي األساس ( 10على سبيل املثال 115%10تعطي )5وكذلك تعطي من أجل 100%قيمة آخر رقمين ( 15في حالة العدد .)115 الفصل الثاني :املتغيرات والتعابير والتعليمات 30 العمليات على السالسل ّ ّ النص ّية 9.2 يعمل العامل +مع السالسل النصية ،لكنه ال يعني الجمع بمعناه الرياض ي ،بل يجري تجميع ،والذي يعني ضم السالسل ً معا ،مثل: >>> first = 10 >>> second = 15 )>>> print(first+second 25 '>>> first = '100 '>>> second = '150 )>>> print(first + second 100150 كما يعمل العامل * مع السالسل النصية عبر تكرار محتوى السلسلة ً ً صحيحا من املرات ،مثل: عددا ' >>> first = 'Test >>> second = 3 )>>> print(first * second Test Test Test 10.2إدخال البيانات من املستخدم ً أحيانا إلى أخذ قيمة متغير ما من املستخدم عبر لوحة املفاتيح ،وتوفر لغة بايثون ً تابعا قد نحتاج ٍ ً جاهزا يدعى ،inputوالذي يقبل ً قيما من لوحة املفاتيح( .كان هذا التابع يدعى raw_inputفي Python )2.0 يتوقف البرنامج وينتظر املستخدم لكتابة ش يء ما عندما ُيستدعى هذا التابع ،وعندما يضغط املستخدم مفتاح اإلدخال ) )enterأو العودة ) ،(returnيستأنف البرنامج ،ويعيد التابع inputما كتبه املستخدم بشكل سلسلة نصية. )(>>> inp = input Some silly stuff )>>> print(inp Some silly stuff الفصل الثاني :املتغيرات والتعابير والتعليمات 31 ُ من األفضل طباعة عبارة تخبر املستخدم بما عليه إدخاله قبل الحصول على مدخالت منه. ُ يمكنك تمرير سلسلة نصية إلى التابع inputكي تعرض للمستخدم قبل التوقف املؤقت بانتظار الدخل. )'>>> name = input('What is your name?\n ?What is your name Chuck )>>> print(name Chuck ً جديدا ،وهي ٌ ً رمز خاص يتسبب في فصل األسطر. سطرا تضيف السلسلة \nفي نهاية موجه األوامر لهذا السبب يظهر دخل املستخدم أسفل العبارة ،وليس على نفس السطر. إذا كنت تتوقع أن يكتب املستخدم عدد صحيح ،فيمكنك تحويل القيمة املعادة لعدد صحيح int باستخدام التابع )(:int '>>> prompt = 'What... is the airspeed velocity of an unladen swallow?\n )>>> speed = input(prompt ?What... is the airspeed velocity of an unladen swallow 17 )>>> int(speed 17 >>> int(speed) + 5 22 لكن إذا كتب املستخدم ً شيئا آخر غير سلسلة نصية من األرقام ،فستظهر رسالة خطأ: )>>> speed = input(prompt ?What... is the airspeed velocity of an unladen swallow ?What do you mean, an African or a European swallow )>>> int(speed ValueError: invalid literal for int() with base 10: سنرى كيفية التعامل مع األخطاء من هذا النوع ً الحقا. 11.2التعليقات ً وغالبا ما يكون من الصعب قراءة جزء من تزداد صعوبة قراءة البرامج مع ازدياد حجمها وتعقيدها، الفصل الثاني :املتغيرات والتعابير والتعليمات 32 شيفرة برمجية ومعرفة ما يفعله البرنامج وملاذا ،لذلك َّ يفضل إضافة مالحظات إلى برامجك لتشرح فيها باللغة الطبيعية ما يفعله هذا البرنامج .تسمى هذه املالحظات التعليقات ( ،(commentsوفي لغة بايثون يبدأ التعليق بالرمز :# # compute the percentage of the hour that has elapsed percentage = (minute * 100) / 60 في هذه الحالة ،سيظهر تعليق على سطر بمفرده ،كما يمكنك وضع التعليقات في نهاية السطر: percentage = (minute * 100) / 60 # percentage of an hour ُي َت َ جاهل كل ش يء من الرمز #إلى نهاية السطر ،وال يكون له أي تأثير على البرنامج. تبرز فائدة التعليقات عندما توثق ميزات غير واضحة للشيفرة البرمجية ،وبما أنه من املنطقي افتراض أن القارئ قادر على معرفة ما تفعله الشيفرةُ ،يعد التعليق أكثر فائدة عندما يشرح السبب. داع لهذا التعليق غير مفيد: ما من ٍ v = 5 # assign 5 to v أما هذا التعليق ،فيحوي معلومة مفيدة غير موجودة في الشيفرة: v = 5 # velocity in meters/second. تقلل أسماء املتغيرات الجيدة من الحاجة إلى التعليقات ،لكن األسماء الطويلة قد تعطي تعابير معقدة تصعب قراءتها ،لذلك تجب املحافظة على التوازن بينهما. ّ 12.2اختيارأسماء ّ متغيرات سهلة التذكر باتباعك لقواعد تسمية املتغيرات البسيطة ،وتجنب الكلمات املحجوزة ،ستجد أمامك العديد من الخيارات لتسمية املتغيرات الخاصة بك. ً ً ً برنامجا بنفسك .فعلى سبيل املثال، برنامجا ،وحين تكتب في البداية قد يكون الخيار مربكا حين تقرأ البرامج الثالثة التالية متطابقة من حيث الفعل ،ولكنها مختلفة ج ًدا عندما تقرؤها وتحاول فهمها: a = 35.0 b = 12.50 c=a*b )print(c الفصل الثاني :املتغيرات والتعابير والتعليمات 33 hours = 35.0 rate = 12.50 pay = hours * rate )print(pay x1q3z9ahd = 35.0 x1q3z9afd = 12.50 x1q3p9afd = x1q3z9ahd * x1q3z9afd )print(x1q3p9afd َيعتبر مفس ُر لغة البايثون البرامج الثالثة متطابقة ً تماما ،لكن اإلنسان يرى ويفهم هذه البرامج بطريقة مختلفة للغاية ،إذ سيفهم اإلنسان الهدف من البرنامج الثاني على الفور ألن املبرمج يملك ُ َ أسماء متغيرات مختارة تعكس َ ستخ َّزن. القيم التي ُ تدعى أسماء املتغيرات املختارة بحكمة "أسماء املتغيرات سهلة التذكر" ( mnemonic variable .)namesالكلمة mnemonicاختصار لـ ،memory aidأي "مساعد للذاكرة" ،ونستخدم هذا النوع من املتغيرات للمساعدة في تذكر سبب إنشائنا للمتغير في األصل .وعلى الرغم من أن كل ذلك يبدو ومفيدا ،إال أنه قد يشكل ً ً عائقا أمام املبرمجين املبتدئين في القدرة على تحليل وفهم نوع جي ًدا الشيفرة ،وذلك ألن املبرمجين املبتدئين لن يكونوا قد حفظوا الكلمات املحجوزة بعد (توجد 35منها ً فقط) .وقد تبدو املتغيرات ذات األسماء الوصفية وكأنها ٌ أسماء جزء من اللغة في بعض األحيان ،ال مختارة بعناية وحسب. انظر إلى النموذج التالي الذي يمثل شيفرة برمجية بلغة البايثون ،ويتعامل مع بيانات ضمن حلقة تكرارية .سوف نناقش موضوع الحلقات ً قريبا ،لكن فلنحاول اآلن اكتشاف معنى هذه الحلقة: for word in words: )print(word وأي من تلك الرموز ( forو wordو inوغيرها ...إلخ) ُيمثل كلمات محجوزة؟ ٌّ ماذا يحصل هنا؟ ٌّ وأي منها ُيمثل أسماء متغيرات؟ وهل تفهم بايثون مفهوم الكلمات ً أساسا؟ يواجه املبرمجون املبتدئون صعوبة في تمييز أجزاء الشيفرة التي اختارها املبرمج. تشابه الشيفرة البرمجية التالية الشيفرة التي ذكرناها أعاله: الفصل الثاني :املتغيرات والتعابير والتعليمات 34 for slice in pizza: )print(slice ُ من األسهل للمبرمج املبتدئ النظر إلى هذه الشيفرة البرمجية ومعرفة أية أجزاء منها تمثل كلمات محجوزة محددة من قبل لغة بايثونُّ ، وأي األجزاء هي أسماء متغيرات اختارها املبرمج. ًّ قادر على فهم الكلمتين pizzaو ،slicesأو حقيقة أن البيتزا تتكون من الواضح جدا أن بايثون غير ٍ من مجموعة واحدة أو أكثر من الشرائح ( ،)slicesلكن إذا كان برنامجنا متعل ًقا بقراءة البيانات والبحث عن الكلمات في البيانات ،فمن الصعب تذكر أسماء متغيرات مثل Pizzaو ،Slicesواختيار ً ضياعا عن معنى البرنامج. أسماء متغيراتك على هذا النحو سيسبب ًّ تلقائيا. بعد فترة قصيرة سوف تتعلم أكثر عن الكلمات املحجوزة الشائعة ،وستتذكرها أجزاء الشيفرة البرمجية التي تحددها لغة بايثون هي ( ،): ، print ، in ، forأما املتغيرات التي اختارها املبرمج فهي wordو.words تتعامل العديد من برامج تحرير النصوص مع قواعد لغة بايثون ،لذا تلون تلك الكلمات بألوان مختلفة إلعطاء دليل يميز املتغيرات عن الكلمات املحجوزة. ستبدأ بعد فترة بقراءة شيفرات برمجية مكتوبة بلغة بايثونُ ، وستميز بسرعة بين الكلمات املحجوزة واملتغيرات. 13.2التنقيح في هذه املرحلة ستواجه الخطأ القواعدي ً غالبا بسبب تسمية متغير غير مسموح ،مثل classو،yield والتي تمثل كلمات مفتاحية ،أو odd~jobو ،U$والتي تحوي ً رموزا غير جائزة. ً إذا َوضعت فراغا في اسم متغير ،فستعتقد لغة بايثون أنهما معامالن دون عامل: >>> bad name = 5 SyntaxError: invalid syntax >>> month = 09 File "<stdin>", line 1 month = 09 ^ SyntaxError: invalid token الفصل الثاني :املتغيرات والتعابير والتعليمات 35 ً عندما تواجهك األخطاء القواعدية ،فرسالة الخطأ ال تساعد ً شيوعا هي "أخطاء كثيرا .أكثر الرسائل قواعدية لقواعد غير صالحة" ( ،)SyntaxError: invalid syntaxو"أخطاء قواعدية لرموز غير صالحة" (.)SyntaxError: invalid token الخطأ الذي يرجح أن ترتكبه أثناء التشغيل ) (runtime errorهو عند محاولتك استخدام متغي ٍر قبل إسناده إلى قيمة. ويحدث إذا َ كتبت اسم املتغير بشكل خاطئ: >>> principal = 327.68 >>> interest = principle * rate NameError: name 'principle' is not defined مع مراعاة أن أسماء املتغيرات حساسة لحالة األحرف ،فعلى سبيل املثال LaTeXغير .latex ً السبب األكثر احتماال لوقوعك في خطأ داللي ) (semantic errorفي هذه املرحلة هو ترتيب العمليات. ً فمثال إليجاد ،1/2πقد تكتب: >>> 1.0 / 2.0 * pi ً لكن القسمة ستحدث أوال ،لذلك تحصل على ،π/2وهي مختلفة عما كنت تقصده. ال توجد طريقة ملعرفة ما كنت تقصد كتابته في لغة بايثون ،لذلك لن تحصل على رسالة خطأ في هذه الحال ،بل ستحصل على إجابة خاطئة. 14.2فهرس املصطلحات • اإلسناد ( :(assignmentالتعليمة التي تسند قيمة ملتغير. • التجميع ) :(concatenateضم معاملين ً معا. ٌ معلومات توضيحية في البرنامج موجهة ألي مبرمج أو قارئ للشيفرة • التعليق ):(comment البرمجية بحيث ال تؤثر على تنفيذ الشيفرة. • تقييم ) :(evaluateلتبسيط التعبير عبر إجراء العمليات بالترتيب للحصول على قيمة واحدة. • التعبير ) :(expressionمجموعة من املتغيرات والعوامل والقيم التي تمثل قيمة نتيجة الفصل الثاني :املتغيرات والتعابير والتعليمات 36 واحدة. ّ العشرية ) :(floating pointنوع بيانات يمثل األرقام ذات الفاصلة العشرية. • الفاصلة • العدد الصحيح ) :(integerنوع بيانات يمثل األعداد الصحيحة. َ ّ مستخدمة من املترجم للتعامل مع البرنامج املفتاحية ) :(keywordكلمة محجوزة • الكلمة (ال يمكنك استخدام كلمات مفتاحية مثل ifو defو whileكأسماء متغيرات). ّ ً وغالبا نستخدم أسماء متغيرات سهلة • سهل التذكر ) :(mnemonicمساعدة الذاكرة، ُ التذكر لتساعدنا في تذكر ما خزن في املتغيرات. • عامل باقي القسمة ) :(modulus operatorعامل يشار إليه باإلشارة ،%يعمل مع األعداد الصحيحة ،وينتج الباقي عندما يكون الرقم مقسم على آخر. • املعامل ) :(operandأحد القيم التي يعمل عليها العامل. • العامل ) :(operatorرمز خاص ،ويمثل عملية حسابية بسيطة ،كالجمع والضرب أو تجميع سالسل نصية. ّ األولوية ) :(rules of precedenceمجموعة من القواعد التي تحكم ترتيب التعابير • قواعد التي تشمل العديد من العوامل واملعامالت. • التعليمة ) :(statementجزء من الشيفرة البرمجية التي تمثل ً أمرا أو إجر ًاء .التعليمات التي رأيناها حتى اآلن هي تعليمة اإلسناد وتعليمة طباعة. • السلسة ّ النص ّية ) :(stringنوع بيانات يمثل سلسلة من املحارف. • نوع البيانات ) :(typeتصنيف للقيم التي أيناها ً سابقا ،وهي intو floatو.string ر • القيمة ) :(valueإحدى الوحدات األساسية للبيانات ،مثل رقم أو سلسلة نصية ،التي تتغير في البرنامج. ّ املتغير) :(variableاسم يشير إلى قيمة. • الفصل الثاني :املتغيرات والتعابير والتعليمات 37 15.2تمارين ً ً برنامجا يستخدم دخال inputلتوجيه أمر للمستخدم لكتابة اسمه • التمرين األول :اكتب والترحيب به كما يلي: Enter your name: Chuck Hello Chuck ً برنامجا يسمح للمستخدم بإدخال ساعات ومعدل األجر لحساب • التمرين الثاني :اكتب الراتب اإلجمالي كما يلي: Enter Hours: 35 Enter Rate: 2.75 Pay: 96.25 ال داعي للقلق في حال تجاوزت قيمة الراتب payرقمين بعد الفاصلة العشرية. َّ املضمن في لغة بايثون لتقريب الراتب الناتج إلى منزلتين عشريتين. بإمكانك باستخدام تابع التقريب • التمرين الثالث :على فرض أننا ننفذ تعليمات اإلسناد التالية: width = 17 height = 12.0 اكتب قيمة التعبير ونوع بيانات والناتج لكل من التعابير التالية: o width//2 o width/2.0 o height/3 o 1+2*5 استخدم مفسر بايثون للتحقق من إجابتك. ً برنامجا يطلب من املستخدم إدخال قيمة درجة الحرارة لتحويلها من • التمرين الرابع :اكتب درجة مئوية (سيليسيوس) إلى فهرنهايت ،واطبع نتيجة التحويل. الفصل الثالث التنفيذ الشرطي الفصل الثالث :التنفيذ الشرطي 39 ّ ّ الش ّ رطي 3التنفيذ ّ ّ املنطقية 1.3التعابير ً ُيعرف التعبير املنطقي بأنه ٌ محققا ،Trueأو خاطئة .Falseيوضح قيمة واحدة فقط ،إما تعبير ذو ٍ َ املثال التالي وظيفة العامل == ،والذي ُيقارن بين معاملين ،ويقرر إذا ما كانت هذه العملية Trueأم .False >>> 5 == 5 True >>> 5 == 6 False تجدر اإلشارة إلى أن Trueو Falseقيمتان خاصتان تنتميان لصنف القيمة املنطقية ،class boolأي أنهما َ ليستا سلسلتين نصيتين ) ،)stringsويمكنك مالحظة ذلك من خالل املثال التالي: )>>>type (True >'<class 'bool )>>>type (False >'<class 'bool ُيعد العامل == أحد عوامل املقارنة التي يمكن تلخصيها كما يلي: xال يساوي y x!=y xأكبر ً تماما من y x>y xأصغر ً تماما من y x<y xأكبر أو يساوي y x >= y xأصغر أو يساوي y x<= y xمثل y x is y xليس مثل y x is not y الفصل الثالث :التنفيذ الشرطي 40 على الرغم من أن هذه العمليات قد تكون مألوفة لك ،إال أن الرموز املستخدمة في لغة بايثون تختلف ً عن الرموز الرياضية لنفس العمليات .على سبيل املثالُ ،يعتبر استخدام عالمة مساواة واحدة = بدال من عالمة مساواة مزدوجة == من األخطاء الشائعة التي قد يقع فيها املبرمج ،وذلك ألن عالمة املساواة ُ ُ الواحدة = تعتبر عامل إسناد ،بينما تعتبر عالمة املساواة املزدوجة == عامل مقارنة ،كما أنه ال وجود لرمز كهذا <= أو هذا <= في لغة بايثون. ّ املنطقية 2.3العوامل توجد ثالثة عوامل منطقية في لغة بايثون ،وهي and :و orو ،notوتشابه معاني هذه العوامل في لغة بايثون معانيها في اللغة اإلنجليزية ،فعلى سبيل املثالُ ،تعتبر هذه التعابير َّ محققة فقط إذا كانت قيمة تماما من 0وأصغر ً xأكبر ً تماما من .10 x > 0 and x < 10 أما التعبير: n%2 == 0 or n%3 == 0 َّ ً ُّ ُ أي من الشرطين ،سواء كان العدد يقبل القسمة على 2أو .3 فيعتبر محققا أي Trueفي حال تحقق ٍ ً فمثال ُيعتبر )َّ not (x > y ً محق ًقا Trueإذا أخيراُ ،يستخدم عامل النفي notلنفي التعابير املنطقية، كان x > yغير َّ محقق ،Falseأي إذا كان xأقل من أو يساوي .y باملعنى الدقيق للكلمة ،يجب أن تكون معامالت العوامل املنطقية عبارة عن تعبيرات منطقية ،لكن ُ لغة بايثون ليست صارمة للغاية؛ إذ تفسر أي رقم غير صفري على أنه .True >>> 17 and True True قد تكون هذه املرونة مفيدة ،إال أن بعض التفاصيل الدقيقة قد تكون مربكة ،ومن األفضل تجنبها حتى تتأكد من أنك تعرف ما تفعله. ّ 3.3التنفيذ املشروط حقق من الشروط وتغيير سلوك البرنامج ً دوما إلى الت ُّ من أجل كتابة برامج مفيدة ،نحتاج ً وفقا لذلك، ُ وتستخدم العبارات الشرطية لهذا الغرض. الفصل الثالث :التنفيذ الشرطي 41 يوضح املثال التالي أبسط صيغة لعبارة ifالشرطية: if x > 0 : )'print('x is positive ُ ُيسمى التعبير املنطقي بعد عبارة ifبالشرط .تنتهي تعليمة ifبرمز النقطتين ،:وتضاف مسافة بادئة قبل األسطر البرمجية التي ستنفذ في حال ُّ تحقق الشرط في تعليمة ( ifبمقدار 4فراغات أو باستخدام مفتاح tapفي لوحة املفاتيح) للداللة على أنها تنتمي إلى بنية ifالشرطية. الشكل :5آلية عمل ifالشرطية ُ إذا كان الشرط املنطقي َّ محق ًقا ،فست َّنفذ التعليمات ذات املسافة البادئة (،)indented statement أما إذا كان الشرط املنطقي غير َّ محقق ،فسيتم تجاهل تلك التعليمات. تملك عبارة ifالشرطية نفس البنية لتعاريف التوابع ( )functionsأو حلقات for؛ إذ تتكون عبارة if ً متبوعا بمجموعة تعليمات ذات مسافة بادئة. الشرطية من سطر أساس ي ينتهي برمز النقطتين : تسمى مثل هذه العبارات بالعبارات املركبة ألنها تتكون من أكثر من سطر. ٌ َ حد أعلى لعدد التعليمات .من يجب أن تلي ifتعليمة واحدة ذات مسافة بادئة على األقل ،وما من ٍ ً املفيد في بعض األحيان أال تضع تعليمات ذات مسافة بادئة بعد عبارة ( ifعادة ما تكون بمثابة بديل عن شيفرة برمجية لم تكتبها بعد) .في هذه الحالة ،يمكنك استخدام تعليمة passالتي ال تفعل ً شيئا، كما في املثال التالي: if x < 0 : !pass # need to handle negative values الفصل الثالث :التنفيذ الشرطي 42 إذا كتبت عبارة ifفي ُم َفسر لغة بايثون ،فسيتغير رمز بداية األسطر البرمجية من ثالث عالمات على شكل حرف vمقلوب >>> ،أو ما ُيعرف باسم شارة تلقين األوامر ،إلى ثالث نقاط … لإلشارة إلى أنك ضمن مجموعة التعليمات الخاصة بعبارة ،ifكما هو موضح أدناه: >>> x = 3 >>> if x < 10: ... )'print('Small ... Small >>> ُ ً ً سطرا فارغا في نهاية كتلة التعليمات ،وإال سترجع عند استخدام مفسر لغة بايثون ،يجب أن تترك ًّ ً قواعديا بدال من تنفيذ تلك األسطر البرمجية ،كما هو موضح في املثال التالي: لغة بايثون خطأ >>> x = 3 >>> if x < 10: )'print('Small )'print('Done ... ... File "<stdin>", line 3 )'print('Done ^ SyntaxError: invalid syntax ًّ ضروريا عند كتابة وتنفيذ نص تجدر اإلشارة إلى أن كتابة سطر فارغ في نهاية كتلة التعليمات ليس برمجي ( ،)scriptولكنه قد يحسن قابلية قراءة شيفرتك. ّ 4.3التنفيذ البديل ُ الشكل الثاني من تعليمة ifهو التنفيذ البديل ،حيث يوجد احتماالن ،ويحدد الشرط أيهما ُينفذ. تبدو بنية الجملة كما في املثال التالي: الفصل الثالث :التنفيذ الشرطي 43 if x%2 == 0 : )'print('x is even else : )'print('x is odd صفرا ،فإن ٌ x عدد ٌّ كما هو معلوم ،إذا كان باقي قسمة العدد xعلى 2يساوي ً زوجي ،ويعرض البرنامج ُ رسالة بهذا املعنى .أما إذا كان الشرط غير َّ محقق ،فست َّنفذ املجموعة الثانية من التعليمات ،وهي عرض رسالة تقول إن ٌ x عدد ٌّ فردي. الشكل : 6آلية عمل بنية if - else ُ ُ محق ًقا أو غير َّ نظرا ألن الشرط يجب أن يكون إما َّ ً محقق ،فست َنفذ إحدى البدائل فقط ،وتسمى البدائل بالفروع؛ ألنها فروع في املسار التنفيذي للبرنامج. ّ 5.3الشروط املتسلسلة قد يكون هناك أكثر من احتمالين في بعض األحيان ،وعندها سنحتاج إلى أكثر من فرعين .في هذه الحالة ،إحدى الطرق املستخدمة هي التعبير الشرطي املتسلسل ،كما في املثال التالي: if x < y: )'print ('x is less than y elif x > y: )'print ('x is greater than y else: )'print ('x and y are equal elifهو اختصار لعبارة " ."else ifمرة أخرىُ ، سي َّنفذ فرع واحد بالتحديد. الفصل الثالث :التنفيذ الشرطي 44 حد لعدد عبارات elifالشرطية ،وإذا كان هناك بند يحتوي على عبارة ،elseفيجب أن يكون ما من ٍ في النهاية ،ولكن ليس من الضروري أن يوجد. if choice == 'a': )'print ('Bad guess elif choice == 'b': )'print ('Good guess elif choice == 'c': )'print ('Close, but not correct الشكل :7بنية if – elif ُيوضح املثال أعاله أن كل شرط ُيفحص بالترتيب .إذا كان الشرط األول غير َّ عندئذ ُيفحص محقق، ٍ ٌ الشرط التالي ،وهكذا دواليك .إذا َّ شرط ماُ ، فسي َّنفذ الفرع املقابل له ،وتنتهي العبارة .حتى لو تحقق َّ َ َّ تحقق أكثر من شرط واحدُ ، تحقق شرطه فقط. سي َّنفذ أول فرع الفصل الثالث :التنفيذ الشرطي 45 ّ 6.3الشروط املتداخلة من املمكن ً أيضا أن يتداخل أحد الشرطين مع اآلخر .فعلى سبيل املثال ،كان بإمكاننا كتابة مثال الفروع الثالثة السابق بهذا الشكل: if x == y: )'print ('x and y are equal else: if x < y: )'print ('x is less than y else: )'print ('x is greater than y نالحظ من املثال أعاله أن الشرط الخارجي يحتوي على فرعين .يحتوي الفرع األول على تعليمة بسيطة ،بينما يحتوي الفرع الثاني على عبارة ifشرطية أخرى تملك فرعين خاصين بها .يحتوي هذان الفرعان على تعليمات بسيطة ً أيضا ،على الرغم من أنه كان من املمكن أن تكون عبارات شرطية مستقلة. ً واضحا ،إال أنه من الصعب قراءة على الرغم من أن إزاحة التعليمات تجعل هيكل الشروط املتداخلة عموما ،من الجيد ُّ ً تجنب استخدام الشروط املتداخلة قدر اإلمكان. الشروط املتداخلة بسهولة. توفر العوامل املنطقية طريقة لتبسيط العبارات الشرطية املتداخلة .فعلى سبيل املثال ،يمكننا إعادة كتابة الشيفرة البرمجية التالية باستخدام شرط واحد فقط. if 0 < x: if x < 10: )'print('x is a positive single-digit number. تنفذ فقط إذا َّ بما أن تعليمة َّ print تحقق الشرطان السابقان لها ،فيمكننا الحصول على نفس النتيجة باستخدام العامل املنطقي ،andكما في املثال التالي: الفصل الثالث :التنفيذ الشرطي 46 الشكل : 8البنية الشرطية املتداخلة if 0 < x and x < 10: )'print ('x is a positive single-digit number. ّ 7.3التعامل مع االستثناء باستخدام بنية tryوexcept ً مقطعا من شيفرة برمجية ،حيث استخدمنا تابعي inputو intلقراءة وتمرير رأينا في وقت سابق رقم صحيح أدخله املستخدم ،ورأينا ً ً خادعا ،كما في املثال أيضا كيف يمكن أن يكون القيام بذلك التالي: ">>> prompt = "What is the air velocity of an unladen swallow?\n )>>> speed = input(prompt ?What is the air velocity of an unladen swallow ?What do you mean, an African or a European swallow )>>> int(speed ValueError: invalid literal for int() with base 10: >>> ُ عندما ننفذ هذه التعليمات في ُمفسر لغة بايثون ،نحصل على موجه أوامر جديد من املفسر، ونصاب بالحيرة ،وننتقل إلى التعليمة التالية ،ولكن إذا قمت بوضع هذه الشيفرة في ُمحرر نصوص خاص ببايثون وحدث هذا الخطأ ،فإن النص البرمجي سيتوقف ً فورا ،وسيعرض رسالة تقرير الفصل الثالث :التنفيذ الشرطي 47 باألخطاء ،ولن ُينفذ التعليمات التالية .فيما يلي مثال لبرنامج ُيحول درجة حرارة من وحدة الفهرنهايت إلى درجة حرارة مئوية: )' inp = input ('Enter Fahrenheit Temperature: )fahr = float(inp cel = (fahr - 32.0) * 5.0 / 9.0 )print(cel # Code: http://www.py4e.com/code3/fahren.py ً إذا نفذنا هذا البرنامج ،وأدخلنا ُمدخال غير مسموح به ،فلن ُي َّنفذ ذلك البرنامج ببساطة ،وستظهر لنا رسالة الخطأ: python fahren.py Enter Fahrenheit Temperature:72 22.22222222222222 python fahren.py Enter Fahrenheit Temperature:fred Traceback (most recent call last): >File "fahren.py", line 2, in <module )fahr = float(inp 'ValueError: could not convert string to float: 'fred توجد بنية تنفيذ شرطية ُمضمنة في لغة بايثون ،تسمى بنية ،try/exceptومهمتها التعامل مع األخطاء املتوقعة وغير املتوقعة .تكمن فكرة try/exceptفي أنها تسمح للمبرمج بإضافة بعض التعليمات (ُ )except blockلت َّنفذ في حالة حدوث مشاكل في التنفيذ التسلسلي للبرنامج .وفي حالة عدم وجود ُ خطأ في تنفيذ البرنامج ،فإن تلك الكتلة من التعليمات ال ت َّنفذ ،أو بمعنى آخر يتم تجاهلها. يمكنك أن تشبه خاصية try/exceptفي بايثون بسياسة الضمان للتنفيذ التسلسلي للتعليمات. باالستفادة من هذه الخاصية ،يمكننا إعادة كتابة برنامج تحويل درجة الحرارة من الفهرنهايت إلى الفصل الثالث :التنفيذ الشرطي 48 الدرجة املئوية بالشكل التالي: )'inp = input ('Enter Fahrenheit Temperature: try: )fahr = float(inp cel = (fahr - 32.0) * 5.0 / 9.0 )print(cel except: )'print('Please enter a number # Code: http://www.py4e.com/code3/fahren2.py َّ يبدأ البايثون في تنفيذ التعليمات الخاصة بكتلة ،tryفإن سار كل ش يء كما هو مخطط له ،عندئذ ستتتجاهل بايثون مجموعة التعليمة املوجودة في كتلة .exceptأما لو حدث خطأ ما ،فسوف َّ تنفذ التعليمات املوجودة في كتلة ،exceptأي أن البايثون سيقفز من كتلة tryإلى كتلة .except موضح في املثال التالي :في الجزء األول ،يدخل املستخدم رقم ،72وهو رقم مقبول ،لذا َّ كما هو َّ ستنفذ التعليمة الخاصة بتحويل درجة الحرارة .أما في الجزء الثانيُ ،يدخل املستخدم سلسلة من الحروف ً بدال من إدخال عدد ،وهذا غير مقبول ،لذا َّ تنفذ التعليمة املوجودة في كتلة تعليمات ،except fred وهي )'.print ('please enter a number python fahren2.py Enter Fahrenheit Temperature:72 22.22222222222222 python fahren2.py Enter Fahrenheit Temperature:fred Please enter a number ُ تعرف عملية التعامل مع االستثناء ) (exceptionباستخدام تعليمة tryبالتقاط االستثناء ( catching .)an exceptionفي املثال السابق ،تظهر تعليمات كتلة exceptرسالة خطأ. بشكل عام ،تمنحك خاصية التقاط االستثناء فرصة إلصالح املشكلة ،أو املحاولة مرة أخرى ،أو على األقل إنهاء البرنامج بأمان. الفصل الثالث :التنفيذ الشرطي 49 ّ ّ ُّ ّ املنطقية 8.3تجاوزالتحقق من التعابير ًّ عندما ُيعالج ُمفسر لغة بايثون ً منطقيا ،مثل ،x >= 2 and (x/y) > 2فإنه يفحص التعبير تعبيرا املنطقي من اليسار إلى اليمين .وبما أن العامل املنطقي هو ،andفإذا كانت xأقل من ،2فإن التعبير ُ x >= 2يكون غير َّ محقق ،Falseوبالتالي فإن التعبير بأكمله يكون Falseبغض النظر عما إذا قي َمت (x / y)> 2كـ Trueأو .False عندما يكتشف ُمفسر لغة بايثون أنه ما من حاجة لتقييم بقية التعبير املنطقي ،فإنه يتوقف عن ُ تقييمه ،وال ُيجري الحسابات الخاصة ببقية التعبير املنطقي .تعرف العملية التي تجعل ُمفسر لغة بايثون يتوقف عن تقييم التعبير املنطقي ألن القيمة اإلجمالية معروفة بالفعل باسم تجاوز التحقق من التعابير املنطقية (.)short-circuiting the evaluation في حين أن هذه العملية قد تبدو وكأنها خاصية جيدة ،فإن سلوك تجاوز الت ُّ حقق من التعابير املنطقية يؤدي إلى أسلوب ذكي في البرمجة ،يسمى نمط الحماية من األخطاء (.)guardian pattern لتوضيح ذلك ،الحظ تسلسل الشيفرة التالية في ُمفسر لغة بايثون: >>> x = 6 >>> y = 2 >>> x >= 2 and (x/y) > 2 True >>> x = 1 >>> y = 0 >>> x >= 2 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and (x/y) > 2 Traceback (most recent call last): >File "<stdin>", line 1, in <module ZeroDivisionError: division by zero \>>> في املثال أعاله ،فشلت العملية الحسابية الثالثة ،والسبب أنه أثناء تقييم ُمفسر لغة بايثون للعملية الفصل الثالث :التنفيذ الشرطي 50 الحسابية ُ ،(x/y) > 2وجد أن ،y = 0مما َّ تسبب بحدوث خطأ أثناء التشغيل ( .)runtime errorلكن ُ ُ املثالين األول والثاني نفذا بنجاح ،فالجزء األول من هذه التعبيرات x> = 2قيم كـ Falseفي املثال الثاني ،لذا فإن ( )x/yلم ُي َّنفذ على اإلطالق بسبب قاعدة اختصار التقييم ولم يكن هناك خطأ. يمكننا بناء التعبير املنطقي لوضع نمط الحماية من األخطاء بشكل استراتيجي قبل التقييم مباشرة والذي قد يتسبب في حدوث خطأ بالشكل التالي: >>> x = 1 >>> y = 0 >>> x >= 2 and y != 0 and (x/y) > 2 False >>> x = 6 >>> y = 0 >>> x >= 2 and y != 0 and (x/y) > 2 False >>> x >= 2 and (x/y) > 2 and y != 0 Traceback (most recent call last): >File "<stdin>", line 1, in <module ZeroDivisionError: division by zero >>> في املثال أعاله ،نالحظ في التعبير املنطقي األول أن الشرط املنطقي ،x >= 2ولكن قيمة xتساوي ،1 لذا فعبارة الشرط املنطقي غير َّ محققة ،Falseفلن يقيم ُمفسر لغة بايثون الجزء الثاني من الشرط املنطقي )x/y(>2بسبب عدم تحقق الجزء األول من الشرط املنطقي ،x >= 2أي سيتوقف ُمفسر لغة بايثون عند عبارة .andأما في التعبير املنطقي الثاني ،فالجزء األول x >= 2محقق ،Trueولكن الجزء الثاني من الشرط املنطقي y != 0غير محقق ،Falseلذلك فلن يقيم ُمفسر لغة بايثون الجزء الثالث من الشرط املنطقي .)x/y(>2وفي التعبير املنطقي الثالث ،نالحظ أن الشرط y != 0أتى بعد حساب ( ،)x/yلذلك يفشل تنفيذ هذه التعليمات ،وتظهر لنا رسالة خطأ بسبب القسمة على الصفر. خالصة األمر ،في التعبير الثاني يمكننا أن نقول إن y != 0تعمل كتعليمة حماية للتأكد من أننا ننفذ ( )x/yفقط ،إذا كانت قيمة yغير صفرية. الفصل الثالث :التنفيذ الشرطي 51 ّ 9.3التنقيح ُي َ عرض تقرير بالخطأ عند حدوث خطأ ما .يحتوي هذا التقرير على الكثير من املعلومات ،ولكن هذه ً املعلومات قد تكون كثيرة لدرجة ال يقدر املبرمج على استيعابها .عادة ما تكون األجزاء األكثر فائدة في هذ املعلومات هي: • ماهية الخطأ الذي حدث. • في أي جزء من الشيفرة حدث ذلك الخطأ. عادة ما يكون من السهل العثور على األخطاء القواعدية ،إال أن بعض التفاصيل قد تكون مضللة؛ إذ يمكن أن تكون أخطاء املسافات الفارغة ) (Whitespaceخادعة ألن الفراغات واملسافة tapغير مرئية ونحن معتادون على تجاهلها ،كما في املثال التالي: >>> x = 5 >>> y = 6 File "<stdin>", line 1 y=6 ^ IndentationError: unexpected indent في هذا املثال ،تكمن املشكلة في أن السطر الثاني يحتوي على مسافة بادئة بمسافة واحدة .لكن رسالة الخطأ تشير إلى ،yوهذ أمر مضلل .بشكل عام ،تشير رسائل الخطأ إلى مكان اكتشاف املشكلة ،ولكن ً وأحيانا في السطر السابق للتعليمة التي الخطأ الفعلي قد يكون حدث في مكان سابق في التعليمة، يشير الخطأ إليها .بشكل عام ،تخبرك رسائل الخطأ حول مكان اكتشاف املشكلة ،ولكن ً غالبا ال يكون هذا هو املكان الذي حدثت فيه املشكلة بالضبط. 10.3فهرس املصطلحات ّ • جسم التعليمة ( :)bodyتسلسل التعليمات ضمن تعليمة مركبة. ّ ّ املنطقي ( :)Boolean expressionهو تعبير قيمته الصواب أو الخطأ ( True or • التعبير .)False الفصل الثالث :التنفيذ الشرطي 52 • الفرع ( :)branchهو إحدى التعليمات املتسلسلة البديلة في العبارات الشرطية. ّ الش ّ رطية املتسلسلة ( :)chained conditionalهي العبارات الشرطية التي • العبارات تحتوي على مجموعة من الفروع التسلسلية. • عامل املقارنة ( :)comparison operatorهو أحد العوامل املنطقية التي تقارن بين قيم معامالتها ،مثل == :أو > أو <. ّ الش ّ رطية ( :)conditional statementهي العبارة التي تتحكم في تسلسل تنفيذ • العبارة ً اعتمادا على شرط ما. التعليمات ّ • الشرط ( :)conditionهو التعبير املنطقي املوجود في العبارات الشرطية ،والذي يحدد أي من الفروع ُ سي َّنفذ. ّ • العبارات املركبة ( :)compound statementهي العبارات التي تتكون من جزأين :سطر أساس ي ،وكتلة تعليمات تابعة له .تكتب عالمة النقتطين :في نهاية السطر األساس ي ،بينما ُ تزاح تعليمات الكتلة بمسافة بادئة لتشير إلى ارتباطها بالسطر األساس ي. • نمط الحماية من األخطاء ( :)guardian patternهو النمط الذي ينتج عند كتابة تعبير منطقي يحتوي على مقارنات إضافية لالستفادة من خاصية تجاوز التحقق من التعابير املنطقية. ّ منطقي ( :)logical operatorأحد العوامل التي تجمع بين التعابير املنطقية ،مثل: • عامل ANDأو ORأو . NOT ّ الش ّ رطية املتداخلة ( :)nested conditionalعبارة شرطية تظهر في أحد فروع • العبارات جملة شرطية أخرى. ُ ُ • عرض تقريربالخطأ ) :(Tracebackقائمة بالتوابع التي ت َّنفذ وتطبع عند حدوث استثناء. ّ ّ ُّ ّ املنطقية ( :)short circuitيقصد بها العملية التي يتوقف فيها • تجاوز التحقق من التعابير مفسر لغة بايثون عن تقييم تعبير منطقي ما ألن القيمة النهائية للتعبير املنطقي معروفة ً سلفا دون الحاجة لتقييم بقية أجزاء التعبير املنطقي. الفصل الثالث :التنفيذ الشرطي 53 11.3تمارين • التمرين األول :اكتب برنامج لحساب الراتب ملنح املوظف 1.5ضعف سعر الساعة بالنسبة لساعات العمل التي تزيد عن 40ساعة. Enter Hours: 45 Enter Rate: 10 Pay: 475.0 • التمرين الثاني :أعد كتابة برنامج حساب الراتب باستخدام try /exceptبحيث يتعامل البرنامج مع املدخالت غير الرقمية بشكل آمن عن طريق طباعة رسالة خطأ والخروج من البرنامج .املثال التالي يوضح عمليتي تنفيذ للبرنامج: Enter Hours: 20 Enter Rate: nine Error, please enter numeric input Enter Hours: forty Error, please enter numeric input ً برنامجا اطلب فيه إدخال درجة تتراوح بين 0.0و .1.0في حال كانت • التمرين الثالث :اكتب ً تقديرا النتيجة خارج النطاق ،اطبع رسالة خطأ ،وإذا كانت الدرجة بين 0.0و ،1.0اطبع يقابل قيمة الدرجة باستخدام الجدول التالي: >= 0.9 A >= 0.8 B >= 0.7 C >= 0.6 D F < 0.6 Enter score: 0.95 A Enter score: perfect Bad score الفصل الثالث :التنفيذ الشرطي 54 Enter score: 10.0 Bad score Enter score: 0.75 C Enter score: 0.5 F نفذ البرنامج بشكل متكرر كما هو موضح أعاله الختبار القيم املختلفة لإلدخال. الفصل الرابع التوابع الفصل الرابع :التوابع 56 4التوابع 1.4استدعاء التوابع عرف التابع ( )functionعلى َّأنه سلسلة ُم َّ في السياق البرمجيُ ،ي َّ عرفة من التعليمات (العبارات َّ ُ البرمجية) التي تنفذ عملية حسابية .أي أن تعريف تابع ما يتطلب تحديد اسم التابع وتسلسل التعليمات ،بحيث تستطيع "استدعاء" التابع من خالل اسمه ً الحقا. ً لقد رأينا من قبل مثاال عن استدعاء تابع: )>>> type (32 >' <class ' int اسم التابع ُهنا هو ( typeبمعنى نوع) ،أما التعبير داخل األقواسُ ، ُ فيسمى وسيط التابع ً ُ ( ،(argumentوقد يكون الوسيط قيمة ثابتة ( )valueأو متغي ًرا ( )variableنمررها إلى التابع بصفتها ً دخال .نتيجة التابع typeهي تحديد نوع الوسيط. َ ُ ُ ُ من الشائع قول إن التابع "يأخذ" الوسيط َو ُ"يعيد" النتيجة ،وتدعى النتيجة ُهنا القيمة املعادة (.)return value 2.4التوابع الجاهزة ُ تقدم لغة بايثون العديد من التوابع الجاهزة التي يمكننا استخدامها دون الحاجة إلى تعريفها ،حيث وضع ُمبتكرو لغة بايثون مجموعة من التوابع لحل مسائل شائعةَّ ، وضمنوا هذه التوابع في لغة بايثون ليتيحوا لنا استخدامها. َ ضمن قائمة ).(list ُيقدم لنا التابعان َ maxو minالقيم األكبر واألصغر على الترتيب )'>>> max ('Hello world ''w )'>>> min ('Hello world ' ' >>> ُيخبرنا التابع maxباملحرف األكبر ضمن السلسلة النصية ،وهو الحرف .wويبين التابع minاملحرف الفصل الرابع :التوابع 57 األصغر ،وهو الفراغ (.)space ُي ُّ عد التابع lenمن التوابع الجاهزة شائعة االستخدام ،ويبين عدد العناصر املوجودة ضمن وسيطه، ً فإذا كان وسيط التابع lenسلسلة نصيةُ ،يعيد التابع عدد العناصر في السلسلة. )'>>> len ('Hello world 11 >>> ال تقتصر هذه التوابع على السالسل النصية ،بل يمكنها التعامل مع أية مجموعة من القيم ،وهذا ما سنراه في الفصول القادمة. يجب أن ُتعامل أسماء التوابع الجاهزة بصفتها كلمات محجوزة (أي َّأنه علينا ُّ تجنب استخدام كلمة ً ً ُ اسما ملتغير). maxمثال بصفتها 3.4توابع تحويل النوع ُتقدم بايثون ً أيضا َ توابع جاهزة تحول َ القيم من نوع آلخر .يأخذ التابع intأية قيمة ويحولها إلى عدد صحيح ( )integerإن أمكن ،أو يظهر رسالة خطأ إذا لم يكن التحويل ً ممكنا. ) '>>> int ( '32 32 ) '>>> int ( 'Hello 'ValueError: invalid literal for int() with base 10: 'Hello كما بإمكان التابع intتحويل األعداد ذات الفاصلة العشرية ) (floatإلى أعداد صحيحة ،لكنه ال ُيقربها ،بل يكتفي بإلغاء القسم العشري. )>>> int (3.99999 3 )>>> int (-2.3 -2 يحول التابع floatاألعداد الصحيحة والسالسل النصية (األرقام وليس األحرف) إلى أعداد ذات فواصل عشرية. )>>> float (32 الفصل الرابع :التوابع 58 32.0 ) ' >>> float ( ' 3.14159 3.14159 َ ً أخيرا ،يحول التابع strوسيطه إلى سلسلة نصية. )>>> str (32 ' ' 32 )>>> str (3.14159 ' ' 3.14159 ّ الرياضية 4.4التوابع تمتلك لغة بايثون وحدة رياضية تحوي معظم التوابع الرياضية املعروفة ،وعلينا استدعاء هذه الوحدة حتى نتمكن من استخدامها: >>> import math تنش ئ هذه التعليمة كائن وحدة ( (module objectيدعى .mathستحصل على بعض املعلومات عنه حين تضعه ضمن تعليمة الطباعة. )>>> print(math > )< module 'math' (built-in يحتوي كائن الوحدة على التوابع واملتغيرات َّ املعرفة في الوحدة .للوصول إلى أحد هذه التوابع ،عليك َ مفصولين بنقطة ( ،)dotوالتي ُتعرف ً أيضا باسم ( ،)periodوتدعى أن تحدد اسم الوحدة واسم التابع هذه الصيغة تأشيرة النقطة (.)dot notation >>> ratio = signal_power / noise_power )>>> decibels = 10 * math.log10(ratio >>> radians = 0.7 )>>> height = math.sin (radians يحسب املثال األول اللوغاريتم ذا األساس 10لنسبة اإلشارة إلى الضجيج (.)ratio-noise-to-signal الفصل الرابع :التوابع 59 كما تحوي الوحدة الرياضية ً تابعا ُيدعى ،logوالذي يحسب اللوغاريتم ذا األساس النيبري .e ً تلميحا إلى أن يوجد املثال الثاني الجيب ) )sinللعدد املسند في املتغير ُ .radiansيعطي اسم املتغير الجيب والدوال املثلثية األخرى ،مثل (… ،)cos, tan,تأخذ قيمها بالراديان .للتحويل من الدرجات إلى الراديان نقسم على ،360ثم نضرب بـ .2π >>> degrees = 45 >>> radians = degrees / 360.0 * 2 * math.pi )>>> math.sin(radians 0.7071067811865476 ُ تستخدم العبارة math.piللحصول على قيمة املتغير piمن الوحدة ،mathوالذي تمثل قيمته العدد πبدقة 15خانة. إن كنت ً خبيرا في علم املثلثات ،يمكنك التحقق من صحة النتيجة السابقة بقسمة الجذر التربيعي للرقم 2على 2كما يلي: >>> math.sqrt (2) / 2.0 0.7071067811865476 ّ العشوائية 5.4األعداد ُ تولد غالبية البرامج الحاسوبية نفس قيم الخرج في كل مرة تتلقى فيها قيم الدخل نفسها ،لذلك تدعى ُ ً وعادة ما تكون الحتمية ً أمرا جي ًدا ،حيث أننا نتوقع أن تثمر العملية حتمية (.)Deterministic َ الحسابية النتيجة ذاتها ،إال أننا قد نحتاج أن يكون الحاسوب غير قابل للتنبؤ في بعض التطبيقات. تعتبر األلعاب خير مثال ،ولكن ثمة تطبيقات أخرى سواها. حتمي باملطلق ،لكن َّثمة بعض األساليب التي تجعله يبدو برنامج غير في الواقع ،من غير السهل بناء ٍ ٍ ُ ً أعدادا كذلك على األقل .أحد هذه األساليب تكمن في استخدام الخوارزميات ) (algorithmsالتي تولد شبه عشوائية ) .)pseudorandomاألعداد شبه العشوائية ليست عشوائية باملطلق ،وذلك ألن عملية حاسوبية حتمية تولدها ،إنما يستحيل تمييز تلك األعداد عن األعداد العشوائية بمجرد النظر إليها. الفصل الرابع :التوابع 60 ُتقدم الوحدة العشوائية توابع تولد أعداد شبه عشوائية (والتي سندعوها "عشوائية" للسهولة ً بدءا من اآلن). ُيعيد التابع ً random ًّ ًّ عشوائيا بين َ 0.0و( 1.0متضم ًنا 0.0دون .)1.0 عشريا عددا ً في كل مرة تستدعي التابع randomستحصل على عدد من سلسلة طويلة من األعداد .لترى مثاال على ذلك ،شغل الحلقة التالية: import random for i in range (10) : )(x = random.random )print (x ُ ينتج عن البرنامج القائمة التالية املؤلفة من 10أعداد بين َ 0.0و 1.0وغير املتضمنة لـ :1.0 0.11132867921152356 0.5950949227890241 0.04820265884996877 0.841003109276478 0.997914947094958 0.04842330803368111 0.7416295948208405 0.510535245390327 0.27447040171978143 0.028511805472785867 التمرين األول :شغل البرنامج على حاسوبك وشاهد األرقام التي ستحصل عليها .شغل البرنامج أكثر من مرة لترى األعداد الناتجة. ُيعتبر التابع ً random واحدا من عدة َ توابع تتعامل مع األعداد العشوائية. يأخذ التابع randintمعاملين األول يمثل الحد األدنى ( )lowوالثاني الحد األعلى (ُ )highويعيد ً عددا ً صحيحا بينهما ُ(متضم ًنا القيمتين). الفصل الرابع :التوابع 61 )>>> random.randint (5 , 10 5 )>>> random.randint (5 , 10 9 الختيار عنصر من مجموعة عشوائية ،بإمكانك استخدام التعليمة :choice ]>>> t = [1 , 2 , 3 )>>> random.choice(t 2 )>>> random.choice(t 3 ُ باإلضافة إلى ذلك ،تؤمن الوحدة randomتوابع لتوليد قيم عشوائية من التوزيعات املستمرة ،ومن ضمنها التوزيعات الغوصية ( ،)Gaussiansواألسية (َ ،)Exponentialوغاما ) ،(gammaوغيرها. 6.4إضافة توابع جديدة ما زلنا نستخدم التوابع الجاهزة في بايثون حتى اآلن ،ولكن بإمكاننا ً أيضا إضافة توابع جديدة. ُ ُيحدد تعريف التابع ( (function definitionاسم التابع الجديد وسلسلة التعليمات التي ت َّنفذ عندما ُيستدعى التابع. حاملا نعرف ً تابعا ،يصبح باإلمكان إعادة استخدامه مر ًارا وتكر ًارا في البرنامج. إليك املثال التالي: def print_lyrics () : )" print (" I'm a lumberjack, and I'm okay. )' print (' I sleep all night and I work all day defهي الكلمة املفتاحية الدالة على تعريف التابع .اسم التابع هو .print_lyricsالقواعد التي تنطبق على أسماء املتغيرات تنطبق بدورها على أسماء التوابعُ ،ويسمح باستخدام األحرف واألرقام وبعض َ الشرطة السفلية _ ) ،ولكن ال يجوز أن يكون املحرف األول من اسم التابع ً رقما أو عالمات الترقيم (ك يحوي فراغات ،كما أنه ليس بإمكانك استخدام كلمة مفتاحية لتسمية التابع ،باإلضافة إلى ذلك، ينبغي ُّ تجنب أن يكون للتابع وللمتغير االسم ذاته. الفصل الرابع :التوابع 62 ُتشير األقواس الفارغة بعد اسم التابع ( ) إلى أنه ال يأخذ أي وسيط .سننش ئ ً الحقا توابع تقبل الوسائط بصفتها ُمدخالت. ُ ُيسمى السطر األول من تعريف التابع الترويسة ) ،)Headerوتسمى البقية جسم التابع (.)body يجب أن ينتهي العنوان بنقطتي القول ، :أما جسم التابع ،فيجب أن يكون ُمز ً احاُّ .اتف َق على أن تكون املسافة البادئة 4فراغات ً دوما ،ويمكن لجسم التابع أن يحتوي أي عدد من التعليمات. إذا َ كتبت تعريف التابع في الوضع التفاعلي ( ،(interactive modeفإن املفسر سيطبع ثالث نقاط ... َ إلعالمك بأن التعريف غير كامل. >>> def print_lyrics() : )" print (" I'm a lumberjack, and I'm okay. ... )' print (' I sleep all night and I work all day. ... ... ًّ ضروريا في حال كتابة النص البرمجي ضمن إلنهاء التابع ،سيتعين عليك إدخال سطر فارغ (وهذا ليس ملف). إن عملية تعريف تابع تعطي بدورها ُمتغي ًرا بنفس اسم التابع. )>>> print(print_lyrics ><function print_lyrics at 0xb7e99e9c ))>>> print(type(print_lyrics >'<class 'function قيمة التابع print_lyricsهي كائن لتابع ( (function objectمن النوع " ،"functionوطريقة استدعاء تابع جديد مشابهة الستدعاء التوابع الجاهزة: )(>>> print_lyrics I'm a lumberjack, and I'm okay I sleep all night and I work all day ً حاملا تعرف تابعُ ،يمكنك استخدامه ضمن تابع آخر .مثال ،لتكرار كلمات األغنية السابقة ،باإلمكان إضافة تابع ُيدعى .repeat_lyrics الفصل الرابع :التوابع 63 def repeat_lyrics() : )(print_lyrics )(print_lyrics ثم استدع التابع .repeat_lyrics )(>>> repeat_lyrics I'm a lumberjack, and I'm okay I sleep all night and I work all day. I'm a lumberjack, and I'm okay I sleep all night and I work all day. 7.4التعاريف واستخداماتها سيبدو البرنامج بأكمله على الشكل التالي بعد تجميع أجزاء النص البرمجي من القسم السابق: def print_lyrics(): )"print("I'm a lumberjack, and I'm okay. )'print('I sleep all night and I work all day. def repeat_lyrics(): )(print_lyrics )(print_lyrics )(repeat_lyrics # Code: http://www.py4e.com/code3/lyrics.py ُ يحتوي هذا البرنامج على تعاريف لتابعينَ print_lyrics :و .repeat_lyricsت َن َّفذ تعريفات التابع مثل ُ غيرها من التعليمات ،وهي تنش ئ كائنات التابع .ال ت َّنفذ العبارات داخل التابع حتى ُيستدعى التابع، كما أن تعريف التابع ال ُيولد ً خرجا. بالطبع عليك أن تنش ئ ً تابعا قبل أن تنفذ محتواه .بمعنى آخر ،يجب كتابة تعريف التابع قبل استدعائه ألول مرة. التمرين الثاني :انقل السطر األخير من البرنامج السابق إلى األعلى بحيث تصبح تعليمة استدعاء التابع موجودة قبل التعريفات .شغل البرنامج والحظ رسالة الخطأ الناتجة. الفصل الرابع :التوابع 64 ً التمرين الثالث :انقل تعليمة استدعاء التابع إلى األسفل ثانية ،وانقل تعريف print_lyricsليصبح بعد تعريف .repeat_lyricsما الذي يحدث عند تشغيل البرنامج؟ 8.4تسلسل التنفيذ ُ من أجل ضمان أن التابع ُعر َف َ قبل استخدامه ألول مرة ،عليك أن تعرف الترتيب الذي ت َنفذ وفقه التعليمات ،والذي ُيعرف بـتسلسل التنفيذ ).(Flow of execution ُ يبدأ التنفيذ ً دوما من التعليمة األولى في البرنامج ،حيث تنفذ التعليمات واحدة تلو األخرى بالترتيب ُ من األعلى لألسفل .ال تغير تعريفات التوابع من تسلسل التنفيذ في البرنامج ،لكن تذكر أن التعليمات ُ ال تنفذ حتى ُيستدعى التابع. ً ُ تعتبر عملية استدعاء التابع بمثابة انعطاف في تسلسل التنفيذ ،فبدال من الذهاب إلى الجملة ً التالية ،يقفز التسلسل إلى جسم التابع ُمنفذا جميع التعليمات هناك ،ثم يعود بعد ذلك ليستأنف من حيث توقف. ً يبدو هذا سهال إلى أن تتذكر أن بإمكان التابع نفسه استدعاء تابع آخر ،حيث قد يضطر البرنامج - أثناء وصوله ملنتصف أحد التوابع -إلى تنفيذ تعليمات في تابع آخر ،ولكن خالل تنفيذ التابع الجديد قد ُينفذ البرنامج ً تابعا آخر. لحسن الحظ ،فإن لغة بايثون جيدة في حفظ مسارها ،إذ في كل مرة يكتمل تنفيذ أحد التوابع، يستأنف البرنامج من حيث توقف في التابع الذي استدعاه ،وعندما يصل إلى نهاية البرنامج تنتهي العملية. ً ً برنامجا ،قد ال تكون القراءة من األعلى لألسفل فعالة ما املغزى من هذه القصة الشيقة؟ عندما تقرأ ً ًّ فأحيانا يكون ُّ ً منطقيا أكثر. تتب ُع تسلسل التنفيذ دائما، ُ 9.4املعامالت والوسائط ً تتطلب بعض التوابع الجاهزة التي صادفناها وسائط ،فمثال عندما تستدعي التابع ،math.sinفإنك ً تمرر له رقم باعتباره وسيطا .تأخذ بعض التوابع أكثر من وسيط :التابع math.powيأخذ وسيطين، هما "األساس واألس". ُ ُ ُ تسند هذه الوسائط ملتغيرات داخل التابع تدعى ُمعامالت (.)Parameters الفصل الرابع :التوابع 65 ً ً إليك مثاال عن التوابع املعرفة من قبل املستخدم ( ،(User defined functionsوالتي تأخذ وسيطا: >>> def print_twice(bruce): )print(bruce )print(bruce يسند هذا التابع الوسيط إلى ُمعامل اسمه .bruceعندما ُيستدعى التابع ،فإنه يطبع قيمة املعامل (مهما كانت) مرتين. يعمل هذا التابع مع أية قيمة ُيمكن كتابتها. )'>>> print_twice('Spam Spam Spam )>>> print_twice(17 17 17 >>> import math )>>> print_twice(math.pi 3.141592653589793 3.141592653589793 ُ قواعد إنشاء التوابع (ذاتها التي تنطبق على التوابع تنطبق على التوابع املعرفة من قبل املستخدم الجاهزة ،لذا بإمكاننا استخدام أي تعبير كوسيط للتابع .print_twice )>>> print_twice('Spam '*4 Spam Spam Spam Spam Spam Spam Spam Spam ))>>> print_twice(math.cos(math.pi -1.0 -1.0 ُ ُي َ حسب الوسيط قبل استدعاء التابع ،لذلك فإن التعابير َ 'spam' *4و) math.cos(math.piتحسب مرة واحدة فقط. بإمكانك ً أيضا استخدام ُمتغير َ كوسيط: ٍ '>>> michael = 'Eric, the half a bee. الفصل الرابع :التوابع 66 )>>> print_twice(michael Eric, the half a bee. Eric, the half a bee. ُ ال عالقة السم املتغير الذي مررناه كوسيط Michaelباسم املعامل ،bruceفبغض النظر عن االسم ُ الذي أطل َق على القيمة في عملية االستدعاءُ ،هنا في التابع print_twiceندعوها .bruce ُ 10.4التوابع املنتجة والتوابع الخالية ُ بعض التوابع التي نستخدمها (كالتوابع الرياضية) ُتعطي ً ابتكرت نتائجا .ولعدم وجود اسم أفضل، ُ لها اسم التوابع املنتجة ).(fruitful functions ُ ُ ُ التوابع األخرى ،مثل ،print_twiceتنجز مهمة ،لكنها ال ترجع قيمة .نطلق على هذه التوابع اسم التوابع الخالية ).)Void functions تابعا ُم ً عندما تستدعي ً نتجا ،فهدفك في أغلب األحيان هو االستفادة من النتيجة. ً ُ مثال ،قد تسند النتيجة إلى ُمتغير أو تستخدمها كجزء من التعبير: )X = math.cos(radians golden = (math.sqrt(5) + 1) / 2 عندما تستدعي ً تابعا في الوضع التفاعلي ،فإن لغة بايثون تعرض النتيجة. )>>> math.sqrt(5 2.23606797749979 ُ تابعا ُم ً لكن في وضع كتابة النص البرمجي ضمن ملف ،إذا استدعيت ً نتجا ولم تخزن النتيجة في ُمتغير، ُ فإن القيمة املرجعة ستختفي. )math.sqrt(5 َيحسب هذا النص البرمجي الجذر التربيعي للعدد ،5ولكن بما أنه لم ُيخزن النتيجة في متغير أو يعرضها ،فهو غير مفيد. ُ قد تعرض التوابع الخالية ً شيئا ما على الشاشة ،أو قد تملك ً تأثيرا آخر ،لكنها ال تملك قيمة ُمرجعة. إذا حاولت أن تسند النتيجة إلى ُمتغير ،ستحصل على قيمة مميزة تدعى .None )'>>> result = print_twice('Bing الفصل الرابع :التوابع 67 Bing Bing )>>> print(result None ُ ُّ نوع خاص. القيمة Noneليست ذاتها السلسلة النصية " ،"Noneبل تعد قيمة مميزة ذات ٍ ))>>> print (type (None >'<class 'NoneType ً نستخدم التعليمة returnفي التابع الخاص بنا إلرجاع نتيجة التابع .مثال ،بإمكاننا إنشاء تابع بسيط للغاية اسمه ،addtwoوالذي يجمع رقمين ُويرجع نتيجة الجمع. def addtwo (a, b): added = a + b return added )x = addtwo(3, 5 )print(x # Code: http://www.py4e.com/code3/addtwo.py عندما ُينفذ هذا النص البرمجي ،تطبع تعليمة printالعدد 8بسبب التابع addtwoالذي ُ استدعي ُومرر الوسيطان 3و 5له. داخل التابع ،املعامالت َ aو bهما َ 3و 5على الترتيب. َيحسب التابع ناتج جمع العددين ،ويضعه في متغير محلي للتابع اسمه ،addedثم يستخدم تعليمة ُ returnإلرسال النتيجة املحسوبة إلى التابع املستدعى كنتيجة للتابع ،والتي تكون ُمسندة بدورها إلى ُ املتغير ،xوتكتب على الشاشة. 11.4ملاذا نستخدم التوابع ً ُّ ً واضحاَ . قد ال يكون تستحق العناء. لم ُي َعد تقسيم البرنامج إلى توابع عملية إليك عدة أسباب: َ • تمنحك عملية إنشاء تابع جديد الفرصة لتسمية مجموعة من التعليمات ،مما يجعل برنامجك أسهل للقراءة والفهم والتصحيح. الفصل الرابع :التوابع 68 • يمكن للتوابع أن تجعل برنامجك أصغر من خالل التخلص من التعليمات َّ املكررة، بحيث إن َ أردت ً الحقا إجراء تغيير ،فسينحصر ذلك في مكان واحد فقط. َ تنقيح أجزاء البرنامج ٌّ كل على حدة ،ومن ثم • تتيح لك عملية تجزئة البرنامج الطويل تجميعها ً معا في برنامج واحد. ً َّ املصممة بشكل جيد مفيدة في العديد من البرامج .حاملا تكتب غالبا ما تكون التوابع • وتنقح أحدها ،بإمكانك إعادة استخدامه. في بقية الكتاب ،سنستخدم ً غالبا تعريف التابع لشرح مفهوم ما. أساسيات مهارة إنشاء التوابع واستخدامها أن تملك ً َّ تابعا ُيجسد فكرة ،مثل "أوجد القيمة تتضمن الصغرى في مجموعة من َ القيم". سنعرض عليك ً الحقا مجموعة تعليمات توجد أصغر قيمة ضمن مجموعة قيم ،وسنقدمها لك كتابع يدعى " ،"minوالذي يأخذ سلسلة القيم كوسائط له ُويعيد القيمة األصغر بينها. ّ 12.4التنقيح إذا كنت تستخدم محرر نصوص لكتابة نصوصك البرمجية ،فستواجه ً غالبا مشاكل متعلقة بالفراغات ) (spacesواإلزاحات ).(tabs ُ ً حصرا (دون اإلزاحات) .تقوم غالبية الطريقة املثلى لتجنب هذه املشاكل هي استخدام فراغات محررات النصوص التي تتعامل مع لغة بايثون بهذا األمر بشكل افتراض ي ،لكن البعض ال يفعل. ً عادة ما تكون اإلزاحات والفراغات غير مرئية ،مما يجعل تنقيحها أصعب ،لذا حاول إيجاد محرر نصوص ُينظم لك املسافات البادئة. إضافة إلى ذلك ،ال َ تنس حفظ برنامجك قبل تشغيله .تقوم بعض بيئات التطوير بذلك بشكل ً مختلفا تلقائي ،ولكن بعضها اآلخر ال يفعل ،لذا قد يكون البرنامج الذي تشاهده في محرر النصوص عن البرنامج الذي تشغله. ً ستأخذ عملية التنقيح ً وقتا طويال إذا استمريت بتشغيل نفس البرنامج الخاطئ مر ًارا وتكر ًارا .احرص على أن يكون النص البرمجي التي تنظر إليه هو ذات النص الذي تشغله .وفي حال لم تكن ُمتأك ًدا، اكتب ً شيئا ما مثل )" print("helloفي بداية البرنامج وشغله من جديد. الفصل الرابع :التوابع 69 إذا لم تظهر لك الكلمة ،helloفإنك ال تشغل البرنامج الصحيح. 13.4فهرس املصطلحات ّ الخوارزمية ( :)Algorithmالخطوات العامة لحل أنواع من املشكالت. • ُ ُ • الوسيط ( :)Argumentقيمة تقدم للتابع عند استدعائه ،تسند هذه القيمة إلى املعامل املناسب في التابع. • جسم التابع ( :)bodyسلسلة من التعليمات داخل تعريف التابع. • التركيب ( :)compositionاستخدام تعبير كجزء من تعبير أوسع ،أو تعليمة كجزء من تعليمة أوسع. • الحتمية (ُ :)deterministicيشير إلى البرنامج الذي ينفذ الش يء ذاته عند إعطائه نفس ُ املدخالت في كل مرة يجري تشغيله. • تأشيرة النقطة ( :)dot notationصياغة تستخدم عند استدعاء تابع في وحدة عبر كتابة ً متبوعا ُبنقطة واسم التابع. اسم الوحدة • تسلسل التنفيذ ( :)flow of executionالترتيب الذي َّ تنفذ وفقه التعليمات خالل تشغيل البرنامج. ُ • التابع املنتج ( :)fruitful functionالتابع الذي ُيرجع قيمة. • التابع ( :)functionسلسلة ُمعرفة من التعليمات التي تنجز عملية مفيدة .قد تأخذ التوابع وسائط وقد ال تأخذ ،كما قد تقدم نتيجة وقد ال تفعل. • استدعاء التابع ( :)function callتعليمة تؤدي إلى بدء تنفيذ التابع ،وتتألف من اسم التابع ً متبوعا بسلسلة وسائط. ً • تعريف التابع ( :)function definitionتعليمة تنش ئ ً جديدا عبر تخصيص اسم له، تابعا ُومعامالت وتعليمات تؤدي إلى تنفيذه. • كائن التابع ( :)function objectقيمة تنشأ بعد تعريف التابع .إن اسم التابع هو متغير يدل على كائن التابع. الفصل الرابع :التوابع 70 • الترويسة ( :)headerالسطر األول من تعريف التابع. • تعليمة :)Import statement( importتعليمة تقرأ ملف الوحدة ،وتنش ئ كائن منه. • كائن النموذج ( :)module objectالقيمة التي ُتنشئها تعليمة ،importوالتي تتيح الوصول إلى البيانات والشيفرات املعرفة في الوحدة. ً ُ عامل ( :)parameterاسم ُيستخدم داخل التابع للداللة على قيمة ُممررة بصفتها وسيطا. • امل ِّ ُ ّ العشوائي ( :)pseudorandomتشير إلى سلسلة من األعداد التي تبدو وكأنها • شبه َّ عشوائية ،ولكنها تولد من قبل برنامج حتمي. • القيمة املُرجعة ( :)return valueنتيجة التابع .إذا ُ استخدم استدعاء التابع كتعبير ،فإن القيمة املرجعة هي قيمة هذا التعبير. • التابع الخالي ( :)void functionهو التابع الذي ال ُيرجع أية قيمة. 14.4تمارين • التمرين الرابع :ما هو الهدف من الكلمة املفتاحية " "defفي لغة بايثون؟ .aهي كلمة عامية تعني "الشيفرة التالية رائعة". ُ .bتشير إلى بداية التابع. خزنة لالستخدام ً ُ .cتشير إلى أن املسافة البادئة التالية من الشيفرة ُم َّ الحقا. .dكل من bو cصحيح. .eال ش يء مما سبق. • التمرين الخامس :ماذا سيعرض برنامج بايثون التالي على الخرج؟ def fred(): )"print("Zap def jane(): )"print("ABC )(jane الفصل الرابع :التوابع 71 )(fred )(jane Zap ABC jane fred jane .a Zap ABC Zap .b ABC Zap jane .c ABC Zap ABC .d Zap Zap Zap .e • التمرين السادس :أعد كتابة برنامج حساب الراتب الذي يعطي قيمة 1.5ضعف األجر للوقت اإلضافي ،وأنش ئ ً تابعا يسمى computepayبحيث يأخذ ُمعاملين ( hoursو.)rate Enter Hours: 45 Enter Rate: 10 Pay: 475. مستخدما ً ً تابعا يدعى • التمرين السابع :أعد كتابة برنامج الدرجات من الفصل السابق ،computegradeوالذي يأخذ النتيجة كمعامل له ويعيد الدرجة كسلسلة نصية. Score Grade A >= 0.9 B >= 0.8 >= 0.7 C >= 0.6 D F < 0.6 Enter score: 0.95 A Enter score: perfect Bad score الفصل الرابع :التوابع 72 Enter score: 10.0 Bad score Enter score: 0.75 C Enter score: 0.5 F كرر تشغيل البرنامج واختبره مع القيم املختلفة للدخل. الفصل الخامس التكرار الفصل الخامس :التكرار 74 5التكرار 1.5تحديث قيم املتغيرات ً اعتمادا على قيمته القديمة: تستخدم تعليمة اإلسناد لتحديث قيمة متغير x=x+1 ً ً واحدا ثم اجعل الناتج قيمة ويعني هذا السطر :قم بإحضار قيمة املتغير xالحالية وأضف إليها ً جديدة للمتغير .x سنحصل على رسالة خطأ في حال حاولنا أن نحدث قيمة متغير غير موجود ً سابقا ألن لغة بايثون تنفذ الطرف األيمن قبل أن تحدث قيمة املتغير :x >>> x = x + 1 NameError: name 'x' is not defined ً لذا عليك تعريف املتغير أوال قبل أن تحدث قيمته: >>> x = 0 >>> x = x + 1 تسمى عملية تحديث قيمة متغير ما بإضافة 1إلى قيمته القديمة بالزيادة ( )incrementأما في حال ً إنقاصا (.)decrement طرح 1من القيمة القديمة فتسمى 2.5حلقة while ُ ً تستخدم الحواسيب عادة ألتمتة املهام املتكررة ،ففي حين تبرع الحواسيب في تكرار املهام املتطابقة أو املتشابهة ،يعجز البشر عن ذلك دون ارتكاب العديد من األخطاء ،لذا فإن لغة بايثون تزودنا بالعديد من املميزات التي تسهل تنفيذ مثل هذه العمليات. ً ٌ برنامج بسيط يقوم بالعد التنازلي تعد حلقة whileشكال من أشكال التكرار في لغة بايثون ،وفيما يلي ً ابتداء بالرقم 5ثم ينتهي بعبارة."Blastoff!" : n=5 while n > 0: )print(n الفصل الخامس :التكرار 75 n=n–1 )'!print('Blastoff يمكن فهم هذه التعليمات بسهولة فهي تعني" :اطبع قيمة nثم اطرح منها ً واحدا إذا كانت قيمة nأكبر من الصفر ،وعندما تصبح قيمة ً n صفرا اخرج من تعليمة whileواطبع كلمة " ،"!Blastoffحيث تنفذ تعليمة whileكاآلتي: .1قيم فيما إذا كان الشرط قد حقق أم ال. .2إذا لم ُيحقق الشرط ،اخرج من الحلقة ثم نفذ التعليمة التالية. .3إذا ُحقق نفذ محتوى (جسم) الحلقة ثم عد إلى الخطوة األولى. لعلك عرفت اآلن سبب تسميتها بالحلقة ( )Loopوذلك ألن الخطوة الثالثة تعود إلى الخطوة األولى مرة أخرى. نطلق على كل مرة يتم فيها تنفيذ جسم الحلقة بالتكرار ( ،)iterationفالحلقة املذكورة في املثال السابق لها خمس تكرارات أي أن جسم الحلقة َّ ينفذ خمس مرات متتالية. يجب أن تغير التعليمات الواردة في جسم الحلقة قيمة متغير معين نسميه متغير التكرار ( iteration )variableحتى نصل إلى مرحلة ال يتحقق فيها شرط الحلقة ومن ثم يتوقف تنفيذها .وفي حال غياب متغير التكرار ،سيتكرر تنفيذ الحلقة باستمرار وينتج عن ذلك ما يسمى بالحلقة الالنهائية ( infinite .)loop 3.5الحلقات الالنهائية يجد املبرمجون التعليمات املكتوبة على عبوات الشامبو مضحكة ،حيث أن خطوات االستخدام هي ً (ضع قليال من املستحضر ،اغسل باملاء ،وكرر ذلك) لكنها تمثل حلقة النهائية لغياب متغير التكرار الذي يحدد عدد مرات تنفيذ هذه الحلقة. نعلم في مثال العد التنازلي السابق أن الحلقة منتهية حيث أعطينا nقيمة محددة ،ونالحظ انخفاض قيمة nعند كل مرة َّ ينفذ فيها جسم الحلقة حتى تصل ً أخيرا إلى الصفر. ً قد يغيب متغير التكرار في بعض الحاالت األخرى لتصبح الحلقة النهائية ،فقد ال نعلم مثال متى ينتهي تنفيذ الحلقة إال في منتصفها ،وعندها نتعمد كتابة حلقة النهائية ثم نستخدم تعليمة اإليقاف break الفصل الخامس :التكرار 76 للخروج من الحلقة عند تحقق شرط معين. الحلقة التالية النهائية وذلك ألن الشرط املستخدم فيها هو الثابت املنطقي ( Trueوهو محقق ً دائما). n = 10 while True: )' '=print (n, end n=n–1 )'!print('Done إذا نفذت هذا البرنامج فإما أن تتعلم كيف تنهي مهمة بايثون الخارجة عن السيطرة أو ستضطر إلى استخدام زر الطاقة إليقاف تشغيل الحاسوب ،فالبرنامج سيستمر في العمل بشكل النهائي أو حتى تنفذ بطارية جهازك .تعني' '= endأن القيم ستظهر على سطر واحد. قد تبدو هذه الحلقة الالنهائية بال فائدة ،لكن نستطيع توظيف هذا النمط من الحلقات إن أضفنا ً أمرا إلى جسم الحلقة للخروج منها باستخدام تعليمة اإليقاف breakعند تحقق شرط معين ،فعلى ً فرض أننا نريد كتابة برنامج يأخذ من املستخدم دخال حتى يدخل كلمة ،doneيمكننا كتابة الحلقة التالية: while True: )' >'( line = input if line == 'done': break )print(line )'!print('Done # Code: http://www.py4e.com/code3/copytildone1.py الحظ أن الشرط املستخدم في هذه الحلقة هو الثابت Trueوهو محقق ً دائما ،وعليه فإن الحلقة ستتكرر حتى تنفذ تعليمة اإليقاف َّ .breakكلما نفذت الحلقة سيظهر للمستخدم إشارة < ً طالبا منه إدخال ما يريد ،وعند إدخال كلمة doneتقوم تعليمة اإليقاف breakبالخروج من الحلقة ،وإال فإن البرنامج سيطبع ما يدخله املستخدم ثم يعود إلى بداية الحلقة. الفصل الخامس :التكرار 77 ً ًّ تجريبيا للبرنامج السابق: إليك تشغيال > hello there hello there > finished finished > done !Done من الشائع استخدام هذه الطريقة في كتابة حلقة ،whileحيث أنه من املمكن التحقق من شرط الحلقة في جسمها وليس فقط في ترويستها ،كما يمكن أن نعبر عن شرط اإليقاف بالشكل (توقف ً عند تحقق ذلك الشرط) بدال من التعبير (تابع التنفيذ حتى يحدث ذلك الشرط). 4.5إنهاء التكرار باستخدام تعليمة Continue أثناء تنفيذ أحد تكرارات الحلقة ،قد نحتاج إلى إيقاف تنفيذ التكرار الحالي والعودة لبدء تكرار جديد ،نستخدم تعليمة املتابعة continueالتي توقف تنفيذ التكرار الحالي دون الخروج من الحلقة. فيما يلي مثال عن حلقة تقوم بطباعة النص املدخل إلى أن يدخل املستخدم كلمة ،doneولكنها تتجاهل السطور املدخلة التي تبدأ برمز #وال تقوم بطباعتها (ما يشبه التعليقات املستخدمة في لغة بايثون): while True: )' >'( line = input if line [0] == '#': continue if line == 'done': break )print(line )'!print ('Done # Code: http://www.py4e.com/code3/copytildone2.py الفصل الخامس :التكرار 78 يظهر عند تشغيل البرنامج مع إضافة تعليمة املتابعة :continue > hello there hello there > # don't print this !> print this !print this > done !Done نالحظ طباعة كل السطور التي تم إدخالها ما عدا السطر الذي ابتدأ بالرمز ،#ألن تنفيذ تعليمة املتابعة continueيوقف تنفيذ التكرار الحالي ويعود لتنفيذ حلقة whileللبدء بتكرار جديد وبالتالي تجاهل تعليمة الطباعة. 5.5الحلقات املحددة باستخدام For ً أحيانا أن نتعامل مع مجموعة من األشياء كقائمة من الكلمات أو األرقام أو حتى مع أسطر نحتاج ملف نص ي ،حينئذ يستحسن استخدام الحلقة املحددة .forتعد حلقة whileحلقة غير محددة ً ألنها ببساطة تتكرر حتى يصبح شرطها غير صحيح ،في حين تعد حلقة forحلقة محددة ألنها تتكرر بعدد األشياء املوجودة في املجموعة. إن قواعد كتابة حلقة forمماثلة لكتابة حلقة whileحيث يوجد ترويسة لحلقة forويتلوها جسم الحلقة .مثال: ]'friends = ['Joseph', 'Glenn', 'Sally for friend in friends: )print('Happy New Year:', friend )'!print('Done قد ال يتضح معنى هذه الحلقة للقارئ مباشرة كما هو الحال في حلقة ،whileولكن إذا اعتبرنا املتغير friendsقائمة تتكون من ثالث عناصر من النوع سلسلة نصية فيمكن أن نصيغ معنى الحلقة كما الفصل الخامس :التكرار 79 يلي :نفذ التعليمات الواردة في جسم الحلقة مرة لكل عنصر friendموجود في القائمة املسماة .friends ً نرى أن كال من forو inكلمات محجوزة للغة بايثون ،وكل من friendو friendsمتغيرات. for friend in friends: )print ('Happy New Year:', friend ً نسمي املتغير friendمتغير التكرار في الحلقة ،حيث أنه يتغير لكل تكرار ويعد مسؤوال عن اكتمال تنفيذ الحلقة ،كما يتعاقب على العناصر النصية الثالثة املوجودة في القائمة ،friendsوفيما يلي الخرج الناتج عن تنفيذ هذه الحلقة: Happy New Year: Joseph Happy New Year: Glenn Happy New Year: Sally !Done 6.5أنماط كتابة الحلقات نستخدم عادة كل من حلقتي forو whileلتنفيذ عملية ما على مجموعة عناصر لقائمة ( )listأو محتويات ملف ،قد تكون هذه العملية البحث عن ش يء ما كأكبر أو أصغر قيمة بين البيانات التي نتعامل معها. تتم عادة بناء الحلقات كما يلي: -1إعطاء قيمة ابتدائية ملتغير أو عدة متغيرات قبل بداية الحلقة. -2تنفيذ عملية حسابية على كل عنصر في جسم الحلقة ،وقد يترافق ذلك مع تغيير في قيم املتغيرات. -3إظهار القيم الناتجة للمتغيرات بعد إتمام تنفيذ الحلقة. ً ً مثاال نستخدم فيه قائمة من األرقام لنوضح املفاهيم الواردة ً سابقا وطريقة بناء عدة سنورد تاليا أنماط للحلقات. الفصل الخامس :التكرار 80 1.6.5حلقات العد والجمع إذا أردنا ان نحص ي عدد األرقام املوجودة في قائمة ما ،فيمكن أن نكتب الحلقة التالية: count = 0 for itervar in [3, 41, 12, 9, 74, 15]: count = count + 1 )print ('Count: ', count ً بداية أعطينا املتغير countالقيمة االبتدائية صفر ،ثم كتبنا حلقة forلتنفيذها على قائمة األرقام. إن متغير التكرار في هذا املثال هو املتغير ،itervarونالحظ أننا ال نستخدم هذا املتغير مباشرة في جسم الحلقة ،إال أنه يتحكم في تنفيذ الحلقة ويتسبب بتنفيذ جسمها مرة لكل عنصر في القائمة. أضفنا واحد إلى قيمة املتغير countفي جسم الحلقة لكل عنصر من عناصر القائمة ،وأثناء تنفيذ الحلقة فإن قيمة املتغير countتساوي عدد القيم التي مررنا بها حتى اآلن. عند اكتمال تنفيذ الحلقة تساوي قيمة املتغير countالعدد اإلجمالي للعناصر ،الذي يظهر عند اكتمال التنفيذ. ً ً لنرى اآلن حلقة مشابهة للحلقة السابقة ولكنها تقوم بحساب مجموع قائمة من األرقام: total = 0 for itervar in [3, 41, 12, 9, 74, 15]: total = total + itervar )print ('Total: ', total ً استخدمنا في هذه الحلقة ًّ فعليا متغير التكرار ،itervarفبدال عن إضافة واحد إلى املتغير كما في الحلقة السابقة ،فقد أضفنا القيمة الفعلية للعنصر ( 3و 41و ........12إلخ) إلى املجموع الحالي عند كل تكرار للحلقة ،وبالنظر إلى املتغير totalفإنه يمثل قيمة املجموع الجاري للقيم التي مررنا بها حتى اآلن ،ولذلك فإننا نعطي هذا املتغير القيمة صفر قبل بداية الحلقة .يمثل ذلك املتغير عند اكتمال الحلقة مجموع القيم في القائمة .أثناء تنفيذ الحلقة فإن املتغير totalيجمع أو يراكم قيم العناصر، لذا فهو يسمى املراكم (.)accumulator الفصل الخامس :التكرار 81 حلقات مفيدة ًّ عمليا لوجود توابع جاهزة لهذا الغرض (التابع ال تعتبر أي من الحلقتين السابقتين ٍ )( lenلحساب عدد العناصر في قائمة والتابع )( sumلحساب مجموع العناصر في قائمة). 2.6.5حلقات إيجاد القيم الكبرى والصغرى للحصول على القيمة الكبرى في قائمة أو سلسلة يمكن أن نكتب الحلقة التالية: largest = None )print ('Before:', largest for itervar in [3, 41, 12, 9, 74, 15]: if largest is None or itervar > largest : largest = itervar )print ('Loop:', itervar, largest )print ('Largest:', largest وعند تنفيذ هذا البرنامج ينتج لدينا الخرج التالي: Before: None Loop: 3 3 Loop: 41 41 Loop: 12 41 Loop: 9 41 Loop: 74 74 Loop: 15 74 Largest: 74 يمثل املتغير largestأكبر قيمة مررنا بها حتى اآلن حيث قبل بداية الحلقة يحمل هذا املتغير القيمة ،Noneيعتبر الثابت Noneقيمة مميزة يمكن أن نعطيها ملتغير ما لنقول عنه إنه فارغ (أي ال يحتوي أي قيمة). قبل بداية تنفيذ الحلقة تكون القيمة Noneهي أكبر قيمة ألننا لم نمر بأي قيمة بعد ،وفي أثناء التنفيذ إذا كانت القيمة املخزنة في املتغير largestهي Noneنعتبر قيمة أول عنصر هي القيمة األكبر، الفصل الخامس :التكرار 82 حيث نالحظ عند تنفيذ البرنامج السابق أننا في أول تكرار للحلقة وعندما كان املتغير itervarيحمل القيمة Noneأصبحت قيمة largestتساوي .3 بعد ذلك لم يعد املتغير largestيحمل القيمة ،Noneولذلك فإن القسم الثاني من التعبير املنطقي املركب يتحقق فقط إذا مررنا بقيمة أكبر من القيمة الحالية للمتغير .largestوعندئذ فإنها تصبح هي القيمة األكبر والتي تخزن فيه ،ويمكن أن نراقب تزايد القيمة الكبرى من 3إلى 41ثم إلى 74في خرج املثال املوضح أعاله. عند انتهاء الحلقة نكون قد أجرينا ً مسحا على كافة القيمة املوجودة في القائمة وعندها يحمل املتغير largestأكبر قيمة موجودة في القائمة. الستخراج القيمة الصغرى في قائمة ما نكتب حلقة مشابهة للحلقة السابقة مع تغيير بسيط: smallest = None )print('Before:', smallest for itervar in [3, 41, 12, 9, 74, 15]: if smallest is None or itervar < smallest: smallest = itervar )print('Loop:', itervar, smallest )print('Smallest:', smallest نقول إن املتغير smallestيحمل القيمة الصغرى الحالية قبل وأثناء وبعد تنفيذ الحلقة ،وعند انتهاء الحلقة يحمل هذا املتغير أصغر قيمة موجودة في القائمة .وكما هو الحال مع حلقات الجمع والعد فإن وجود التوابع الجاهزة ( )( minو)( ) maxيغني عن كتابة حلقات كهذه. إليك نسخة مبسطة عن التابع الجاهز )( minفي لغة بايثون: def min(values): smallest = None for value in values: if smallest is None or value < smallest: الفصل الخامس :التكرار 83 smallest = value return smallest الحظ أننا قمنا بحذف أوامر الطباعة حتى نحصل على تابع مشابه للتابع الجاهز في لغة بايثون. 7.5التنقيح ً ستجد عندما تبدأ بكتابة برامج أعقد أنك تمض ي ً وقتا طويال في التنقيح ،حيث أن كتابة املزيد من الشيفرات يزيد من احتمالية ارتكاب األخطاء واألماكن التي يمكن أن تختبئ فيها. لذا تعتبر عملية التنقيح بالتجزئة إحدى طرق تقليل الوقت املستهلك في التنقيح .فعلى سبيل املثال، سطرا ً إذا احتوى البرنامج على مئة سطر واختبرتها ً سطرا فستحتاج إلى مئة خطوة .لذا قسم املشكلة إلى نصفين ً عوضا عن ذلك ،وابحث في منتصف البرنامج -أو قرب املنتصف -عن قيمة وسطية يمكن ً التأكد منها ،ثم أضف تعليمة الطباعة (أو إضافة أي تغيير يعطي ً واضحا) وقم بتشغيل البرنامج. أثرا إذا فشلت عملية التحقق التي أضفناها تكون املشكلة في النصف األول للبرنامج ،وفي حال كانت نتيجة هذه العملية واضحة فاملشكلة إذا في النصف الثاني .في كل مرة نقوم بتكرار هذه الطريقة فإننا نختصر عدد السطور التي نحتاج إلى التحقق منها إلى النصف ،وبعد ست خطوات (وهو عدد اقل ًّ (نظريا على األقل). بكثير من مئة خطوة) فإننا سنحصر املشكلة في سطر أو سطرين فقط عند التطبيق العملي لهذه الطريقة ،قد ال يكون من الواضح ً دائما املكان الذي يعتبر نصف البرنامج ً وقد ال يكون هذا املوضع قابال للتعيين ،كما أنه من غير املعقول أن نعد األسطر ونجد نقطة املنتصف ً ً عوضا عن ذلك بالبحث عن األماكن التي يمكن أن تحتوي على أخطاء أو التي يسهل تماما ،فنقوم التحقق من نتيجتها ثم نختار نقطة تمثل املنتصف بالنسبة لهذه األماكن. 8.5فهرس املصطلحات • املراكم ( :)accumulatorمتغير يستخدم في الحلقة ليجمع النتائج مع بعضها. • العداد ( :)counterمتغير يستخدم في حلقة ليقوم بعد املرات التي يحدث فيها ش يء ما. يعطى هذا املتغير قيمة ابتدائية تساوي الصفر ونزيد قيمته بمقدار 1كل مرة نعد ً شيئا ما. • التنقيص ( :)decrementإنقاص قيمة املتغير. • إعطاء قيمة ابتدائية ( :)initializeإسناد قيمة ابتدائية ملتغير ما سيتم تحديثه ً الحقا. الفصل الخامس :التكرار 84 • الزيادة ( :)incrementتحديث لقيمة متغير ما يسبب زيادتها (عادة بمقدار .)1 • حلقة ال نهائية ( :)infinite loopوهي حلقة ال يتحقق فيها شرط اإلنهاء ً بتاتا أو هي الحلقة التي يغيب عنها هذا الشرط ً أساسا. 9.5تمارين ً برنامجا يقرأ األرقام املدخلة بشكل متكرر حتى يدخل املستخدم كلمة • التمرين األول :اكتب ،doneوعندها يطبع البرنامج كل من املجموع واملتوسط والعدد الكلي لهذه األرقام .إذا أدخل املستخدم أي محارف عدا األرقام اكتشف هذا الخطأ باستخدام تعليمتي tryوexpect وأظهر رسالة خطأ ثم انتقل إلى اإلدخال التالي. Enter a number: 4 Enter a number: 5 Enter a number: bad data Invalid input Enter a number: 7 Enter a number: done 16 3 5.333333333333333 ً برنامجا يطلب قائمة من األرقام كما في املثال السابق وعند النهاية • التمرين الثاني :اكتب ً يظهر القيمة الكبرى والصغرى لألرقام بدال عن املتوسط. الفصل السادس السالسل النصية الفصل السادس :السالسل النصية 86 6السالسل النصية 1.6السلسلة النصية هي سلسلة من املحارف ً ً ً ُّ كل منها وصوال منفصال باستخدام تعد السلسة النصية سلسلة من املحارف التي يمكن الوصول إلى ٍ عامل القوس ] [. '>>> fruit = 'banana ]>>> letter = fruit[1 ٌ تعيد التعلمية الثانية املحرف املوجود في املوقع ذي الفهرس 1من املتغير ُ fruitليسند إلى املتغير .letter ُيدعى التعبير ما بين األقواس [ ] بالفهرس الذي يشير إلى املحرف املرغوب َو ً فقا لتسلسله (من هنا جاءت التسمية "السلسلة النصية") ،لكنك قد ال تحصل على ما تتوقعه ً دائما: )>>> print (letter a َ املحرف َّ األول من كلمة bananaهو bوليس ،aلكن قيمة الفهرس في لغة قد يكون من البديهي أن بدءا من َّأول السلسلة ،وترتيب املحرف َّ بايثون ُتعبر عن الترتيب ً األول فيها هو الصفر. ]>>> letter = fruit [0 )>>> print(letter b مما سبق أن الحرف bهو الحرف َّ نجد َّ األول (ذو الفهرس )0من كلمة bananaوالحرف aهو الحرف الثاني (ذو الفهرس )1و nهو الحرف الثالث (ذو الفهرس .)2 باإلمكان استخدام أي تعبير بما في ذلك من املتغيرات واملعامالت على أنها فهرس ،لكن قيمها يجب أن تكون ً ً صحيحا وإال فإنك ستحصل على خطأ“ :خطأ في نوع البيانات :فهارس السالسل النصية عددا يجب أن تكون أعداد صحيحة” ]>>> letter = fruit [1.5 TypeError: string indices must be integers الفصل السادس :السالسل النصية 87 الشكل : 9فهارس السلسلة النصية 2.6الحصول على طول السلسلة النصية باستخدام التابع len التابع َ len ُيعيد ُ عدد املحارف في السلسة النصية. '>>> fruit = 'banana )>>> len (fruit 6 قد تظن أنه يمكن كتابة التعليمات التالية للحصول على آخر محرف في السلسلة النصية: )>>> length = len (fruit ]>>> last = fruit [length IndexError: string index out of range لكن سيعترضك خطأ "خطأ فهرسةَّ : إن فهرس السلسلة النصية خارج املجال". يعود السبب في ظهور خطأ الفهرسة إلى عدم وجود محرف في كلمة bananaله الفهرس ،6وما دام ُ أن العد يبدأ من الصفر؛ فاألحرف الستة ُمفهرسة من 0حتى ،5أي يجب طرح 1من طول السلسلة النصية للحصول على املحرف األخير: ]>>> last = fruit[length-1 )>>> print(last a وبطريقة أخرى ،يمكنك استخدام الفهارس العكسية التي ُت ُّ ًّ عكسيا من نهاية السلسلة النصية؛ عد إذ َّ التعبير [ُ fruit]-1يعيد الحرف األخير و[ fruit]-2يعيد الحرف ما َ َ قبل األخير وهكذا دواليك. إن الفصل السادس :السالسل النصية 88 3.6التعامل مع محارف السلسة النصية باستخدام الحلقات َ تتطلب ُ لجة محارف السلسلة النصية كل منها على حدى ً بدءا من َّأول محرف ،حيث بعض البرامج معا ُ ُ ُ عمليات ما عليه واملتابعة بهذا النحو حتى املحرف األخير. ُيحدد املحرف ثم ت َّنفذ ُيدعى هذا َّ الن َمط من عمليات املعالجة باملرور على عناصر السلسلة )ُّ (traversal وتعد حلقة while إحدى طرق تنفيذه: index = 0 while index < len(fruit): ]letter = fruit[index )print(letter index = index + 1 ً ً عناصر السلسلة النصية ُوتظهر َّ َ ظهورا مستقال .وألن كل محرف على سطر تمر هذه الحلقة على شرط هذه الحلقة هو ) ،index < len(fruitلذا سيختل الشرط عندما يتساوى طو ُل السلسلة النصية والفهرس ،فال تنفذ التعليمات في جسم الحلقة. آخر محرف ُوصل إليه هو الذي يملك الفهرس len(fruit)-1الذي يدل على آخر محرف في السلسلة النصية. َ التمرين األول :استخدم حلقة whileبحيث تبدأ من نهاية السلسلة النصية لتنتهي عند املحرف َّ سطر مستقل. األول لها واطبع كل حرف على ٍ حلقة forهي طريقة أخرى للمرور على عناصر السلسلة for char in fruit: )print(char ُ ُي َ سند املحرف املوجود في السلسلة النصية إلى املتحول charفي كل دور من أدوار الحلقة التي تستمر حتى آخر محرف في السلسلة. الفصل السادس :السالسل النصية 89 4.6تجزئة السالسل النصية ُ َ َ ُ اختيار محرف في اختيار شريحة الجزء من السلسلة النصية بالشريحة ( ،)sliceيشابه نسمي السلسلة النصية '>>> s = 'Monty Python )]>>> print(s[0:5 Monty )]>>> print(s[6:12 Python يعيد العامل [ً ]n,m جزءا من السلسلة النصية ،من املحرف ذي الفهرس nإلى املحرف الذي يسبق َ املحرف ذا الفهرس ،mأي يتضمن املحرف ذو الفهرس َّ األول nوال يتضمن ذو الفهرس األخير .m َ ُ الفهرس ( nقبل عامل النقطتين) فإن التجزئة ستبدأ من بداية السلسلة النصية ،وفي في حال ُحذف ُ ُّ تستمر حتى نهاية السلسلة النصية. الفهرس الثاني ( mبعد عامل النقطتين) فإن التجزئة حال ُحذف '>>> fruit = 'banana ]>>> fruit[:3 ''ban ]>>> fruit[3: ''ana ُ َّ إذا كان الفهرس َّ األول َ أكبر أو يساوي الثاني؛ فإن النتيجة هي سلسلة نصية فارغة تمثل بعالمة اقتباس. '>>> fruit = 'banana ]>>> fruit[3:3 ' ' ٌ ال تحوي السلسلة النصية الفارغة َّ أي محارف وطولها صفر ،وعلى الرغم من هذا ،فهي سلسلة نصية. التمرين الثاني :بالعودة إلى السلسلة النصية fruitاملُعطاة ً سابقا ،ما نتيجة التعليمة التالية [fruit]:؟ الفصل السادس :السالسل النصية 90 5.6السالسل النصية غير قابلة للتعديل ُ محرف في السلسلة النصية كما يلي: استخدام عامل اإلسناد لتغيير قد يبدو من املناسب ٍ '!>>> greeting = 'Hello, world '>>> greeting [0] = 'J TypeError: 'str' object does not support item assignment فتظهر لك رسالة خطأ "خطأ تصنيف :الكائن strال يدعم إسناد العنصر". ُ السلسلة النصية و"العنصر" هو املحرف الذي حاولت أن َ تسنده ،يمكنك "الكائن" في هذه الحالة هو َ ً ُّ ً مشابها ً ً َّ تعرفا أفضل)، (ستتعرف هذا املفهوم الحقا تماما ملفهوم القيمة األن اعتبار مفهوم الكائن َّأما العنصر فهو أحد القيم في سلسلة. يظهر خطأ النوع ألن السالسل النصية ُ غير قابلة للتعديل مما يعني أنك ال تستطيع تغيير سلسلة إنشاء سلسلة نصية جديدة تمثل ُّ ُ التغير على السلسلة األصلية. نصية ،ما يمكنك القيام به هو '!>>> greeting = 'Hello, world ]>>> new_greeting = 'J' + greeting[1: )>>> print(new_greeting !Jello, world ُ َ ٌ أضيف في هذا املثال حرف جديد إلى جزء من السلسلة النصية greetingمن َدون التعديل على السلسلة األصلية. ّ والعد 6.6استخدام الحلقات يحسب البرنامج التالي َ عدد مرات ظهور املحرف " "aفي السلسلة النصية 'word = 'banana count = 0 for letter in word: if letter == 'a': count = count + 1 الفصل السادس :السالسل النصية 91 )print(count ً نموذجا لبرامج تقوم بعمليات حسابية كالعد ،فاملتغير countيبدأ من القيمة 0ثم ُيمثل هذا البرنامج َ َ (العدد َّ الكلي يزداد في كل مرة يظهر فيها املحرف aوعند انتهاء الحلقة يتضمن املتغير countالنتيجة ملرات ظهور املحرف .)a َ البرنامج السابق في تابع سمه countبحيث يقبل السلسلة النصية التمرين الثالث :أعد كتابة َ ُ َ والحرف املراد معرفة مرات تكراره باعتبارهم وسائط. 7.6العامل in ً ً ُّ ًّ منطقيا يأخذ سلسلتين نصيتين ويعيد الثابت املنطقي Trueإذا كانت األولى سلسلة يعد inعامال فرعية م َن الثانية. '>>> 'a' in 'banana True '>>> 'seed' in 'banana False 8.6مقارنة السالسل النصية ُّ ُ للتحقق من تساوي سلسلتين. عوامل املقارنة على السالسل النصية تعمل if word == 'banana' : )'print ('All right, bananas. ُ عوامل مقارنة أخرى لترتيب مجموعة سالسل نصية َو َ ُ فق الترتيب األبجدي. تستخدم if word < 'banana': )'print('Your word,' + word + ', comes before banana. elif word > 'banana': )'print('Your word,' + word + ', comes after banana. else: )'print('All right, bananas. الفصل السادس :السالسل النصية 92 ُ َ َ ال تتعامل لغة بايثون واألحرف الكبيرة والصغيرة كما يتعامل الناس معها ،ففي لغة البايثون تأتي ُ قبل األحرف الصغيرة ً كلمة َ Pinapple األحرف الكبيرة َ قبل .banana دوما ،لذلك تأتي ُ َ توحيد ن َمط السالسل النصية (حروف صغيرة فقط إحدى الطرائق الشائعة لتفادي هذه املشكلة هي ً مثال) َ قبل القيام بعملية املقارنة ،أبق هذه املالحظة في بالك عند املقارنة بين كلمات ذات حروف صغيرة وكبيرة. 9.6توابع السالسل النصية ُّ تعد السالسل النصية إحدى أمثلة الكائنات في لغة بايثون ،يتضمن الكائن البيانات (السلسلة بحد َ ضمن الكائن ومتاحة ألي نسخة من هذا الكائن. ذاتها) وتوابع الصنف ) (methodsوهي توابع مبنية التابع َ type َ التوابع املتاحة لكائن ما ،في حين ُيظهر ُ ُيظهر التابع dirفي لغة بايثون نوع الكائن. '>>> stuff = 'Hello world )>>> type (stuff >'<class 'str )>>> dir (stuff ['capitalize', 'casefold', 'center', 'count', 'encode', 'endswith' , 'expandtabs', 'find', 'format', 'format_map', 'index' , 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier' , 'islower', 'isnumeric', 'isprintable', 'isspace' , 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip' , 'maketrans', 'partition', 'replace', 'rfind', 'rindex' , 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split' , 'splitlines', 'startswith', 'strip', 'swapcase', ]''title' , 'translate', 'upper', 'zfill )>>> help (str.capitalize Help on method_descriptor: )capitalize(... الفصل السادس :السالسل النصية 93 S.capitalize() -> str Return a capitalized version of S, i.e. make the first character have upper case and the rest lower case. >>> باإلمكان استعر ُ اض التوابع باستخدام التابع ،dirكما يمكن استخدام helpللحصول على شرح مختصر عن تابع ماَّ ،أما للحصو ُل على ملفات تفصيلية خاصة بتوابع السالسل النصية ،فمن األفضل زيارة الرابطhttps://docs.python.org/library/stdtypes.html#string-methods. : َ استدعاء التابع العادي ( )functionحيث كالهما يأخذان يشابه استدعاء تابع الصنف ((method َ وسائط ويعيدان قيمة لكن قواعد الكتابة ُمختلفة .نستدعي َ توابع الصنف عن طريق إلحاق اسمها باسم املتغير باستخدام عامل النقطة. ً ً ً ً يأخذ التابع -،upperمثال -سلسلة نصية ليعيد نسخة منها مكتوبة بأحرف كبيرة؛ فبدال من كتابة التابع بالشكل ( upper(wordنكتب ().word.upper '>>> word = 'banana )( >>> new_word = word.upper )>>> print(new_word BANANA َ عامل النقطة َ يحدد ُ واسم السلسلة النصية التي سيتعامل معها التابع .word اسم التابع upper َ ُ يشير وجود أقواس فارغة إلى َّ أن التابع ال يأخذ وسائط. َ ُ التابع upperعلى استخدام التابع باالستدعاء وفي هذه الحالة يمكن القول :إننا نستخدم ُيدعى السلسلة النصية .word ً فمثال ،لدينا تابع لسلسلة نصية يدعى findيبحث عن موقع سلسلة نصية َّ محدد في سلسلة نصية أخرى. '>>> word = 'banana )'>>> index = word.find('a )>>> print(index الفصل السادس :السالسل النصية 94 1 َ َ التابع findعلى السلسلة النصية wordوأدخلنا املحرف الذي نبحث استخدمنا-في املثال السابق- َ محرف ما. سالسل فرعية أو عنه على َّأنه وسيط .يمكن لهذا التابع العثور على ٍ )'>>> word.find('na 2 ً قد يأخذ وسيطا آخر يعبر عن الفهرس الذي يجب أن يبدأ عنده البحث. )>>> word.find('na', 3 4 َ التابع stripللتخلص من املسافات البيضاء (مسافات فارغة ،إزاحة باستخدام املفتاح نستخدم ،tapمحارف السطور الجديدة) من بداية السلسلة النصية أو نهايتها. ' Here we go ' = >>> line )(>>> line.strip ''Here we go مثل ً startswith تعيد بعض التوابعُ ، قيما منطقية. '>>> line = 'Have a nice day )'>>> line.startswith('Have True )'>>> line.startswith('h False ُ ُ تحويل سلسة نصية إلى ستلحظ أن التابع startswithيحتاج إلى معامل ملطابقته ،لذا من األحسن أحرف صغيرة باستخدام التابع َ lower قبل القيام بأي عمليات مطابقة. '>>> line = 'Have a nice day )'>>> line.startswith('h False )(>>> line.lower الفصل السادس :السالسل النصية 95 ''have a nice day )'>>> line.lower().startswith('h True ُ التابع ،lowerفنستخدم startswithللتحقق من أن السلسة النصية في املثال األخير ُيستدعى برمجي واحد مع تعبير الناتجة تبدأ بمحرف" ،"hوباإلمكان القيام ٍ بعدد من االستدعاءات للتوابع في ٍ ٍ أخذ الترتيب باالعتبار. َّ ٌ مشابه ً تماما ملا قمنا به في التمارين السابقة ،وتتوفر التمرين الرابع :يوجد تابع صنف ُيدعى count معلومات عن هذا التابع في الرابط التالي: https://docs.python.org/library/stdtypes.html#string-methods اكتب شيفرة برمجية لعد َّ مرات ظهور الحرف " "aفي كلمة " "bananaباستدعاء هذا التابع. 10.6تحليل السالسل النصية ً َ ضمن السلسلة النصية ،على سبيل املثال :في حال أحيانا إلى البحث عن سلسلة فرعية قد نحتاج لدينا مجموعة من األسطر كالتالية: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 ونريد استخر َ اج النصف الثاني من عنوان البريد االلكتروني املعطى ،أي ( )uct.ac.zaمن كل سطر: يمكننا القيام بذلك من خالل استخدام التابع findوتجزئة السلسلة النصية. ً بداية عن موقع عالمة @ في السلسلة النصية ُثم نحدد موقع َّأول مسافة فارغة َ بعد عالمة @ نبحث َ ومن ثم نجزئ السلسلة النصية القتطاع الجزء املطلوب من السلسلة. '>>> data = 'From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 )'@'(>>> atpos = data.find )>>> print(atpos 21 )>>> sppos = data.find(' ',atpos )>>> print(sppos 31 الفصل السادس :السالسل النصية 96 ]>>> host = data[atpos+1:sppos )>>> print(host uct.ac.za >>> اإلصدار من التابع findبتحديد املوقع في السلسلة النصية الذي نريد منه َ ُ بدء البحث. يسمح هذا َ املحارف ً بدءا من املحرف الذي يلي إشارة @ حتى املحرف الذي اقتطعنا بعملية التجزئة السابقة يسبق املسافة الفارغة. ملزيد من املعلومات عن التابع ،findباإلمكان زيارة الرابط التالي: https://docs.python.org/library/stdtypes.html#string-methods 11.6عامل التنسيق عامل التنسيق َ % َ ُ سالسل نصية واستبدال أجزاء منها ،ببيانات مخزنة في املتغيراتُ .يمثل بناء يتيح ُ عامل باقي القسمة لكن عندما يكون املعامل َّ َ األول الرمز %عند استعماله مع األعداد الصحيحة ً سلسلة نصية يكون عامل تنسيق. ُ حيث َّ األول -وهو سلسلة نصيةً - يضم املعامل َّ إن رموزا محددة لتحدد كيفية تنسيق املعامل الثاني ً ٌ نتيجة هذه العملية هي سلسلة نصية؛ فمثال يشير رمز التنسيق %dإلى أن املعامل الثاني يجب أن ُي َن َّسق باعتباره ً ً ً اختصارا لـ .)decimal صحيحا (d عددا >>> camels = 42 >>> '%d' % camels ''42 َّ َ ينتج َّ مما سبق السلسلة النصية ' '42ويجب أال ُيخلط بينها وبين العدد الصحيح .42 ُ يمكن أن تظهر رموز التنسيق في أي مكان من السلسلة حيث يمكنك ذلك من إضافة جملة معينة. >>> camels = 42 >>> 'I have spotted %d camels.' % camels ''I have spotted 42 camels. الفصل السادس :السالسل النصية 97 ُ في حال وجود َ أكثر من رمز تنسيق في السلسلة النصية؛ فالوسيط الثاني يجب أن يكون من نوع ٌ البيانات صف (ُّ .)Tuple كل رمز تنسيق مرتبط بعنصر من الصف َح َس َب الطلب. ُ املثال التالي %dلتنسيق عدد صحيح g%لتنسيق رقم ذي فاصلة عشرية و %sلتنسيق يستخدم سلسلة نصية. )'>>> 'In %d years I have spotted %g %s.' % (3, 0.1, 'camels ''In 3 years I have spotted 0.1 camels. عدد العناصر في الصف َ يجب أن يساوي ُ عدد رموز التنسيق في السلسلة النصية ،كما يجب أن َ يرتبط نوع العناصر بتسلسل التنسيق. )>>> '%d %d %d' % (1, 2 TypeError: not enough arguments for format string ُ ٌ ال توجد وسائط كافية لتنسيق السلسلة. '>>> '%d' % 'dollars TypeError: %d format: a number is required, not str رمز التنسيق %dيتطلب رق ًما وليس سلسلة نصية. ٌ ُ ال يوجد في املثال َّ كاف ونوع العنصر في الثاني خطأ. األول عدد عناصر ٍ عامل التنسيق قو ٌّي ومفيد لكنة صعب االستخدام ،باإلمكان قراءة املزيد عنه من خالل الرابط التالي: https://docs.python.org/library/stdtypes.html#printf-style-string-formatting 12.6التنقيح ُ حيث َ إنك ُمبرمج -هي أن تسأل نفسك ً دوما" :ما الخطأ الذي يمكن املهارة التي ينبغي لك تطويرها -من ُ فعلها لتفشل بر ُ امجنا التي تبدو أن يحصل هنا أو باألحرى ما هي األشياء التي يمكن للمستخدم مثالية؟". البرنامج الذي استخدمناه لشرح حلقة whileفي فصل َّ َ التكرار: على سبيل املثال ،لنعد إلى while True: )' >'(line = input الفصل السادس :السالسل النصية 98 if line[0] == '#': continue if line == 'done': break )print(line )'!print('Done # Code: http://www.py4e.com/code3/copytildone2.py ً انتبه ما الذي يحصل عندما ُيدخل املستخدم ً سطرا فارغا. > hello there hello there > # don't print this !> print this !print this > Traceback (most recent call last): >File "copytildone.py", line 3, in <module if line[0] == '#': IndexError: string index out of range تظهر رسالة خطأ "خطأ في الفهرسة :فهرس السلسلة النصية خارج املجال" ً عمال ً ٌ سطر فارغ ،في هذه الحالة ال يوجد محرف في املوقع []0 سليما حتى ُيدخل سيعمل البرنامج لذلك نحصل على تقرير بالخطأ ،ثمة حالن لهذه املشكلة. ُ استخدام التابع startswithالذي يعيد الثابت املنطقي Falseفي حال أحد هذه الحلول هي بسهولة كانت السلسلة النصية فارغة. if line.startswith('#'): أكثر ً الطريقة األخرى ُ أمانا وهي باستخدام عبارة ifالشرطية مع استخدام تعليمات تفادي األخطاء الفصل السادس :السالسل النصية 99 ُ تحقق من الشرط الثاني إال في حال َّ بحيث ال ُي َّ ُ تحقق َّ وجود محرف واحد األول وهو باستخدام شرطين على األقل. if len(line) > 0 and line[0] == '#': 13.6فهرس املصطلحات ً ● العداد ( :)counterهو متغير لعد ش يء ما ،عادة ما يبدأ من الصفر وتزداد قيمته. ُ َّ ● سلسلة نصية فارغة ( :)empty stringهي سلسلة نصية دون أي محارف وطولها ،0تمثل باستخدام عالمتي االقتباس. ُ َ ● عامل التنسيق ( :)format operatorهو العامل %يطلب رموز التنسيق َوصف لتوليد سلسلة نصية تتضمن عناصر الصف ُمنسقة على َوفق رموز التنسيق. َُ ● رموز التنسيق ) :)format sequenceسلسلة من املحارفَ ، مثل %d :تحدد كيف تن َّسق ٌ قيمة معينة. ُ ُ ● سلسلة التنسيق ) :)format stringسلسلة نصية تستخدم مع عامل التنسيق بحيث َ تتضمن رموز تنسيق. َ محقق أو غير َّ منطقي يشير فيما إذا كان الشرط َّ ٌّ محقق. ● العلم ) :(flagمتغير ● استدعاء ( :(invocationعبارة نستدعي من خاللها تابع الصنف. ٌ ُ تعديل عناصرها. ● غيرقابل للتعديل ) :)Immutableميزة للسالسل بحيث ال يمكن ● الفهرس (ٌ :)index عدد صحيح ُيستخدم لتحديد عنصر في سلسلة مثل محرف ضمن سلسلة نصية. ● عنصر (ُ :)item أحد القيم في سلسلة ما. ٌ ● تابع الصنف ( :)methodتابع مرتبط بكائن ُويستدعى باستخدام عامل النقطة. ● الكائن ( :)objectش ٌيء يمكن للمتحول أن يشير إليه ،حتى اآلن يمكنك ُّ عد "الكائن" و"القيمة" الش َيء َ نفسه. ● البحث )ٌ :)search شكل من أشكال املرور على عناصر سلسلة بحيث يتوقف عندما يجد ما الفصل السادس :السالسل النصية 100 ُ يبحث عنه. ٌ ٌ مرتبة من القيم بحيث ُّ كل قيمة معرفة باستخدام فهرس. ● سلسلة ( :)sequenceمجموعة جزء من السلسلة النصية َّ ● شريحة (ٌ :)slice املحدد بعدد من الفهارس. ● املرور على عناصر السلسة ) :)traverseاملرور على عناصر سلسلة وإجراء عمليات مماثلة في كل مرة. 14.6تمارين • التمرين الخامس :الشيفرة البرمجية التالية مكتوبة بلغة بايثون تخزن سلسلة نصية: 'str = 'X-DSPAM-Confidence:0.8475 استخدم تعليمة findوتجزئة السالسل النصية القتطاع الجزء من السلسلة الواقع َ بعد النقطتين ُ ُ عدد ذي فاصلة عشرية. ثم استخدم التابع floatلتحويل السلسلة املقتطعة إلى ٍ • التمرين السادس :اقرأ توصيف توابع السلسلة النصية عبر زيارة الرابط: https://docs.python.org/library/stdtypes.html#string-methods من املفيد التعامل مع أحدها للتأكد من فهمها وفهم كيف عملها .مثل stripو replaceفهما مفيدان ًّ جدا. ً ً قد يعترضك أثناء قراءة التوصيف جمال قد تكون غير مفهومة ،مثال: )]]in find (sub[, start[, end َ ٌ مطلوب لكن startاختيارية ،وفي تشير األقواس إلى وسائط اختيارية ،أي أن الوسيط sub حال ُ ضمنت startتكون endاختيارية. الفصل السابع امللفات الفصل السابع :امللفات 102 7ا ِّمللفات 1.7اإلصرارعلى التعلم تعلمنا حتى اآلن كيفية كتابة البرامج وتنفيذ ما نريده عبر وحدة املعالجة املركزية باستخدام التنفيذ املشروط والتوابع َّ والتكرار .كما تعلمنا كيفية إنشاء بنى البيانات ( )data structuresواستخدامها في الذاكرة الرئيسة .حيث ُيخزن ال َ برنامج ُوينفذ في وحدة املعالجة املركزية والذاكرة ُويعتبران املكان الذي يحدث فيه "التفكير" .ولكن إذا َ كنت تتذكر نقاشنا عن بنية الحاسب ،فبمجرد فصل التغذية الكهربائية عن الحاسوبُ ،يحذف أي ش يء مخزن في وحدة املعالجة املركزية أو في الذاكرة الرئيسية. ما األمر التالي؟ الشبكة الذاكرة الثانوية البرمجيات وحدة املعالجة املركزية أجهزة الدخل والخرج الذاكرةالرئيسية الشكل : 10الذاكرة الثانوية َّ سنتعرف في هذا الفصل إلى وسيط تخزين جديد ُيسمى الذاكرة الثانوية (أو امللفات) .تمتاز الذاكرة الثانوية بعدم فقدانها محتوياتها عند فقدان الطاقة .أو في حالة وحدة تخزين متنقلة (،)USB Flash يمكن إزالة البيانات-التي نكتبها من برامجنا -من النظام ونقلها إلى نظام َ آخر. سنركز ً أساسيا على قراءة امللفات النصية وكتابتهاَ ، ًّ مثل تلك التي ننشئها في محرر النصوص. تركيزا سنرى ً ً الحقا كيفية العمل مع ملفات قواعد البيانات وهي ملفات ثنائية (َّ ،)Binary خصيصا مصممة للقراءة والكتابة من خالل برمجيات َمعنية بقواعد البيانات. الفصل السابع :امللفات 103 2.7فتح ا ِّمللفات عندما نريد قراءة ملف أو الكتابة عليه -على سبيل املثال :ملف محفوظ على محرك األقراص ً الصلبة ،-يجب َّأوال فتح امللف .يؤدي فتح امللف إلى االتصال بنظام تشغيلك ،الذي يعرف مكان تخزين البيانات الخاصة بكل ملف .عندما تفتح م ًلفا ،فإنك تطلب من نظام التشغيل العثور على امللف باالسم والتأكد من وجوده .يوضح املثال أدناه طريقة فتح امللف النص ي ،mbox.txtالذي يجب تخزينه في املجلد نفسه الذي استخدمته عند بدء تشغيل بايثون .يمكنك تنزيل هذا امللف من خالل الضغط على الرابط التالي: www.py4e.com/code3/mbox.txt )'>>> fhand = open('mbox.txt )>>> print(fhand >'<_io.TextIOWrapper name='mbox.txt' mode='r' encoding='cp1252 ُ ً بنجاح ،فسيعيد لنا نظام التشغيل معرفا للملف ( .)file handleال يمثل املعرف لف امل تح ف إذا ٍ ً ً البيانات الفعلية املوجودة في امللف ،ولكنه بدال من ذلك يكون واجهة يمكننا استخدامها لقراءة ً البياناتُ .ت َ ً موجودا ولديك األذونات املطلوبة لقراءة امللف. منح معرفا للملف إذا كان امللف املطلوب الشكل :11معرف امللف الفصل السابع :امللفات 104 ً موجودا ،فستفشل عملية الفتح ُ وسيعرض في الشاشة تقرير بالخطأ ولن تحصل إذا لم يكن امللف على معرف للوصول إلى محتويات امللف كما يوضح املثال التالي: )'>>> fhand = open('stuff.txt Traceback (most recent call last): >File "<stdin>", line 1, in <module 'FileNotFoundError: [Errno 2] No such file or directory: 'stuff.txt سوف نستخدم ً الحقا خاصية التعامل مع االستثناءات try/exceptللتعامل بأمان َ أكثر مع الحاالت التي نحاول فيه فتح ملف غير موجود. 3.7 ِّملفات النصوص واألسطر يمكن عد امللف النص ي على أنه سلسلة من األسطرُ ، مثل السلسلة النصية في لغة بايثون التي يمكن ً اعتبارها سلسلة من املحارف .مثال ،هذه عينة من ملف نص ي يسجل نشاط البريد من أفراد مختلفين مشروع مفتوح املصدر. في فريق تطوير ٍ From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 >Return-Path: <postmaster@collab.sakaiproject.org Date: Sat, 5 Jan 2008 09:12:18 -0500 To: source@collab.sakaiproject.org From: stephen.marquard@uct.ac.za Subject: [sakai] svn commit: r39772 - content/branches/ Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772 ً يمكنك الحصول على ملف نشاطات البريد اإللكتروني كامال من خالل الضغط على الرابط التالي: www.py4e.com/code3/mbox.txt كما يمكنك الحصو ُل على النسخة املختصرة من هذا امللف من خالل الضغط على الرابط التالي: www.py4e.com/code3/mbox-short.txt هذه امللفات ذات صيغة قياسية؛ إذ يحتوي امللف على عدد من رسائل بريدية .واألسطر التي تبدأ بكلمة " "Fromتفصل بين الرسائل املختلفة .األسطر التي تبدأ بكلمة "ُ "Fromتعد ً جزءا من الرسائل. ملعرفة املزيد من املعلومات عن صيغة رسائل البريد ،باإلمكان زيارة الرابط التالي: الفصل السابع :امللفات 105 https://en.wikipedia.org/wiki/Mbox ٌ لتقسيم امللف إلى عدد من األسطرُ ،يستخدم محرف خاص ُيمثل "نهاية السطر" ويطلق عليه اسم محرف السطر الجديد (.)newline ٌ تستخدم في لغة باثيون شرطة مائلة عكسية ( )backslashمع حرف nفي السالسل النصية إلنشاء ٌ سطر جديد . \nعلى الرغم من أن محرف إنشاء سطر جديد يبدو محرفين ،فهو في الواقع محرف واحد .عندما نكتب املتغير stuffفي مفسر لغة بايثون ،فإنه يظهر \nفي السلسلة النصية الناتجة، ولكن عندما نستخدم printإلظهار السلسلة ،نرى السلسلة َّ مقسمة إلى سطرين بواسطة محرف السطر الجديد .املثال التالي يوضح كيفية إنشاء سطر جديد في لغة بايثون: '!>>> stuff = 'Hello\nWorld >>> stuff '!'Hello\nWorld )>>> print(stuff Hello !World '>>> stuff = 'X\nY )>>> print(stuff X Y )>>> len(stuff 3 ُ ً مالحظة أن طول السلسلة X \nYهو ثالثة؛ َّ يجدر بك ً ألن حرف السطر الجديد ُ \nيعتبر محرفا أيضا ً واحدا. ً محرفا ًّ خاصا َ غير مرئي ُيسمى لذلك عندما ننظر إلى السطور في ملف ما ،علينا أن نتخيل أن ثمة محرف السطر الجديد في نهاية كل سطر ُيمثل نهاية السطر .أي أن محرف السطر الجديد يفصل املحارف في امللف إلى سطور. 4.7قراءة ا ِّمللفات على الرغم من أن معرف امللف ال يحتوي على بيانات امللفَّ ، فإن من السهل ًّ َ إنشاء حلقة for جدا الفصل السابع :امللفات 106 لقراءة كل سطر وعده ،من سطور امللف: )'fhand = open('mbox-short.txt count = 0 for line in fhand: count = count + 1 )print('Line Count:', count # Code: http://www.py4e.com/code3/open.py ً سلسلة َّ للتكرار في حلقة forحيث تحسب حلقة forبسهولة َ عدد يمكننا استخدام معرف امللف األسطر في امللف وتطبعها .بمعنى آخر ،يمكن تلخيص عمل حلقة forكالتالي :لكل سطر في امللف املمثل بمعرف امللف ،أضف ً واحدا إلى املتغير .count كبيرا ًّ يعود السبب في أن تابع فتح امللفات openال يقرأ امللف بالكامل إلى أن امللف قد يكون ً جدا وقد يصل ُ حجمه إلى أكثر من واحد غيغابايت .تستغرق تعليمة َ open نفس القدر من الوقت بغض النظر عن حجم امللف وتعمل حلقة forعلى قراءة البيانات من امللف. ُ َ ُ حين ُيقرأ امللف باستخدام حلقة forبهذه الطريقة؛ تقسم لغة بايثون البيانات املوجودة في امللف إلى أسطر منفصلة باستخدام محرف إنشاء السطر الجديد .\nتقرأ لغة بايثون كل سطر عن طريق َ ٌ َ محرف إنشاء السطر الجديد وتضيف هذا املحرف على أنه محرف أخير في املتغير lineلكل تكرار للحلقة .for َ سطرا ً ُ ً ً وحسابها واحدا في كل مرة ،فمن ثم يمكنها قراءة األسطر نظرا إلى أن حلقة forتقرأ البيانات بكفاءة في امللفات الكبيرة ًّ َ للبرنامج أعاله جدا دون نفاد الذاكرة الرئيسة لتخزين البيانات .يمكن حساب األسطر في أي ملف بأي حجم باستخدام ذاكرة ذات حجم صغير ًّ ُ جدا؛ إذ ُيقرأ كل سطر ويعد ثم نتخلص منه. إذا كنت تعلم أن امللف صغير ًّ نسبيا موازنة بحجم ذاكرتك الرئيسة ،فيمكنك قراءة امللف بأكمله في سلسلة واحدة باستخدام تابع القراءة .read )'>>> fhand = open('mbox-short.txt )(>>> inp = fhand.read ))>>> print(len(inp الفصل السابع :امللفات 107 94626 )]>>> print(inp[:20 From stephen.marquar ُ ً ً في املثال أعاله ،قرئت محتويات امللف mbox-short.txtبالكامل 94626-محرفا -مباشرة في املتغير ً .inpكما يوضح املثال استخدام تعليمة تجزئة السالسل النصية لطباعة َّأول 20حرفا من بيانات السلسلة املخزنة في املتغير .inp عند قراءة امللف بهذه الطريقة ،فإن جميع املحارف ،بما في ذلك جميع األسطر ومحارف إنشاء ُ السطر الجديد ،تعتبر سلسلة واحدة كبيرة ضمن املتغير .inpتجدر اإلشارة إلى أنه من الجيد تخزين ناتج القراءة ضمن متغير وذلك ألن كل استدعاء للقراءة يستنفد املورد وهذا ما يوضحه املثال التالي: )'>>> fhand = open('mbox-short.txt )))(>>> print(len(fhand.read 94626 )))(>>> print(len(fhand.read 0 كما عليك أن تضع في الحسبان أنه يجب استخدام هذه الصيغة لتابع فتح امللفات openفقط إذا كبيرا ًّ كانت بيانات امللف مناسبة بشكل مريح للذاكرة الرئيسة لحاسوبكَّ .أما إذا كان امللف ً جدا َ البرنامج لقراءة محتويات امللف في أجزاء بحيث ال يتسع للذاكرة الرئيسة ،فيجب عليك كتابة باستخدام حلقة forأو .while 5.7البحث خالل ِّملف عندما تبحث عن بيانات في ملف ،من الشائع ًّ جدا تجاهل معظم السطور والتركيز في معالجة األسطر َ التي تفي بشرط ُمعين فقط .يمكننا دمج نمط قراءة ملف مع التوابع املستخدمة مع السالسل النصية إلنشاء آليات بحث سهلة. على سبيل املثال ،إذا أردنا قراءة ملف وطباعة األسطر التي بدأت بالبادئة " ":Fromفقط ،فيمكننا استخدام التابع startswithلتحديد تلك األسطر التي تحتوي على البادئة املطلوبة فقط كما في املثال التالي: )'fhand = open('mbox-short.txt count = 0 الفصل السابع :امللفات 108 for line in fhand: if line.startswith('From: '): )print(line # Code: http://www.py4e.com/code3/search1.py َ البرنامج ،نحصل على املخرجات التالية: عندما ُينفذ هذا From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu ... تبدو هذه املخرجات رائعة ألن األسطر الوحيدة التي نراها هي تلك التي تبدأ بـ ،from:ولكن ملاذا نرى األسطر الفارغة اإلضافية؟ ُيعزى ذلك إلى استخدام محرف إنشاء السطر الجديد الذي ال ُي َ طبع بل يظهر تأثيره َ فحسب .ينتهي كل سطر بمحرف إنشاء السطر الجديد ،لذا فإن تعليمة الطباعة التي ً سطرا تطبع السلسلة في املتغير lineالذي يتضمن محرف سطر جديد ثم تضيف تعليمة الطباعة ً جديدا آخر ،مما يؤدي إلى وجود تباعد أو مسافة مزدوجة بين األسطر. َ يمكننا استخدام طريقة تجزئة األسطر لطباعة كل املحارف ما عدا املحرف األخير ،ولكن الطريقة األنسب هي استخدام التابع rstripالذي يحذف املسافات البيضاء ( )white spacesالواقعة بين األسطر كما في املثال التالي: )'fhand = open('mbox-short.txt for line in fhand: )(line = line.rstrip if line.startswith('From: '): )print(line # Code: http://www.py4e.com/code3/search2.py َ البرنامج ،نحصل على املخرجات التالية: وعند تنفيذ هذا From: stephen.marquard@uct.ac.za الفصل السابع :امللفات 109 From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: zqian@umich.edu From: rjlowe@iupui.edu From: cwen@iupui.edu … ً ً تعقيدا ،فقد ترغب في تنظيم حلقات البحث نظرا إلى أن برامج معالجة ملفاتك ،تصبح أكثر باستخدام التعليمة .continueالفكرة األساسية لحلقة البحث هي أنك تبحث عن األسطر “املهمة" مثيرا لالهتمام؛ نفعل ً سطرا ً ً شيئا ما به .يمكننا هيكلة وتتخطى األسطر "غير املهمة" .ثم عندما نجد الحلقة لتتبع َنمط تخطي السطور غير املهمة على النحو التالي: )'fhand = open('mbox-short.txt for line in fhand: )(line = line.rstrip '# Skip 'uninteresting lines if not line.startswith('From:'): continue # Process our 'interesting' line )print(line # Code: http://www.py4e.com/code3/search3.py َ البرنامج؛ ستحصل على نفس املخرجات السابقة .بمعنى آخر ،األسطر ُ غير املهمة هي عند تنفيذ هذا تلك األسطر التي ال تبدأ بـ ، :Fromوهي التي نتخطاها باستخدام التعليمة . continueفيما يعالج ُ السطور "املهمة" (أي تلك التي تبدأ بـ .):Fromيمكننا استخدام التابع findملحاكاة أداة البحث في محرر نصوص التي تعثر على السطور حيث تكون سلسلة البحث في أي جزأ من السطرً . نظرا إلى أن تعليمة findتبحث عن تواجد سلسلة داخل سلسلة أخرى وتقوم َّإما بإرجاع موضع السلسلة َّ وإما ُ طباعة .1-إذا لم تعثر على السلسلة ،فيمكننا كتابة الحلقة التالية إلظهار األسطر التي تحتوي على السلسلة "( "@uct.ac.zaأي أنهم ينتمون إلى جامعة كيب تاون في جنوب إفريقيا) كما في املثال التالي: )'fhand = open('mbox-short.txt for line in fhand: )(line = line.rstrip الفصل السابع :امللفات 110 if line.find ('@uct.ac.za') == -1: continue )print(line # Code: http://www.py4e.com/code3/search4.py ُ َ البرنامج ،نحصل على املخرجات التالية وهي عناوين البريد اإللكتروني ملنتمين إلى عند تنفيذ هذا جامعة كيب تاون في جنوب أفريقيا: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 X-Authentication-Warning: set sender to stephen.marquard@uct.ac.za using -f From: stephen.marquard@uct.ac.za Author: stephen.marquard@uct.ac.za From david.horwitz@uct.ac.za Fri Jan 4 07:02:32 2008 X-Authentication-Warning: set sender to david.horwitz@uct.ac.za using -f From: david.horwitz@uct.ac.za Author: david.horwitz@uct.ac.za … نستخدم هنا ً َ الشكل املختصر لجملة ifالشرطية ،إذ نضع تعليمة continueعلى نفس السطر أيضا ُّبرفقة تعليمة ifالشرطية .يعمل هذا الشكل من جملة ifالشرطية كما لو كانت تعليمة continue في السطر التالي ومسبوقة بمسافة بادئة. 6.7السماح للمستخدم باختيارا ِّمللف ال نريد ً أبدا أن ُن َّ ضطر إلى تعديل شيفرة لغة بايثون في كل مرة نريد فيها معالجة ملف مختلف .سيكون َ َ البرنامج حتى يتمكن إدخال اسم امللف في كل مرة يتم فيها تشغيل من األفضل أن تطلب من املستخدم من استخدام َ برنامجنا على ملفات مختلفة دون تغيير الشيفرة .يمكن تنفيذ هذا األمر بسهولة من خالل قراءة اسم امللف من املستخدم باستخدام التابع inputعلى النحو التالي: )' fname = input('Enter the file name: )fhand = open(fname count = 0 for line in fhand: if line.startswith('Subject:'): count = count + 1 )print('There were', count, 'subject lines in', fname الفصل السابع :امللفات 111 # Code: http://www.py4e.com/code3/search6.py ُ َ البرنامج األعلى أن اسم امللف يدخله املستخدم .ونضعه في متغير ُيسمى fnameونفتح هذا نلحظ من ً َ ً متكررا على ملفات مختلفة كما هو موضح أدناه: البرنامج تشغيال امللف .اآلن يمكننا تشغيل python search6.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search6.py Enter the file name: mbox-short.txt There were 27 subject lines in mbox-short.txt َ البرنامج األعلى واسأل نفسك«،ما الخطأ قبل إلقاء نظرة خاطفة إلى القسم التالي ،ألق نظرة إلى املحتمل هنا؟» أو «ما الذي يمكن أن يفعله مستخدمنا الودود ليجعل َ ُ برنامجنا الصغير اللطيف ال ً ُينفذ بل تظهر رسالة خطأ بدال من ذلك ،مما يجعلنا نبدو مبرمجين غير محترفين في أعين مستخدمينا؟». 7.7استخدام tryو exceptوopen أخبرتك للتو بأال تختلس النظر إلى هذا القسم قبل اإلجابة على االسئلة السابقة ،هذه هي فرصتك األخيرة. ماذا لو كتب مستخدمنا ً شيئا ما غير اسم امللف؟ تمعن في حاالت التنفيذ التالية ،ما الذي تلحظه؟ python search6.py Enter the file name: missing.txt Traceback (most recent call last): >File "search6.py", line 2, in <module )fhand = open(fname 'FileNotFoundError: [Errno 2] No such file or directory: 'missing.txt python search6.py Enter the file name: na na boo boo الفصل السابع :امللفات 112 Traceback (most recent call last): >File "search6.py", line 2, in <module )fhand = open(fname 'FileNotFoundError: [Errno 2] No such file or directory: 'na na boo boo ً حسنا ،ال تضحك .سيفعل املستخدمون في النهاية كل ما يمكنهم فعله لتفشيل َ برنامجكَّ ،إما عن شخصا أو ً وإما بنية سيئة .في واقع األمرَّ ، ً قصد َّ فريقا إن أي فريق تطوير برمجيات يجب أن يتضمن ً مسؤوال عما ُيسمى بضمان الجودة ،وتتمثل مهمة هذا الفريق في القيام بأكثر األشياء ً جنونا في محاولة ً ُ َ البرنامج الذي أنشأه املبرمج أو فريق البرمجة .يعتبر فريق ضمان الجودة مسؤوال عن اكتشاف لكسر ُّ َ َ البرنامج أو يدفعون رواتب البرنامج للمستخدمين الذين قد يشترون العيوب في البرامج قبل تسلم ُ أفضل صديق للمبرمج. املبرمجين .لذا ،فريق ضمان الجودة هو َ البرنامج ،يمكننا إصالحه بأناقة باستخدام بنية .try / exceptنحتاج إلى واآلن بعد أن رأينا الخلل في ُ افتراض أن عملية استدعاء التابع openقد تخفق ،لذا سنقوم بإضافة شيفرة استعادة (recovery )codeعند فشل عملية استدعاء التابع openعلى النحو التالي: )' fname = input('Enter the file name: try: )fhand = open(fname except: )print('File cannot be opened:', fname )(exit count = 0 for line in fhand: if line.startswith('Subject:'): count = count + 1 )print('There were', count, 'subject lines in', fname # Code: http://www.py4e.com/code3/search7.py َ َ التابع وال يعود بأي قيمة .اآلن عندما يكتب البرنامج؛ إذ نستدعي هذا يعمل التابع exitعلى إنهاء الفصل السابع :امللفات 113 املستخدم (أو فريق ضمان الجودة) أسماء للملفات غير أسمائها الحقيقية ،فإننا "نستدرك الوضع" بأمان كما هو موضح أدناه: python search7.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python search7.py Enter the file name: na na boo boo File cannot be opened: na na boo boo ً تعد حماية استدعاء التابع openمثاال جي ًدا على االستخدام الصحيح لبنية tryو exceptفي البرامج املكتوبة بلغة بايثون .نستخدم مصطلح "بايثوني" " "Pythonicعندما نفعل ً شيئا بأسلوب محترف في لغة بايثون .يمكننا القول :إن املثال السابق هو "طريقة بايثونية" لفتح ملف. بمجرد أن تصبح أكثر مهار ًة في لغة بايثون ،يمكنك املشاركة في اقتراح حل بديل مع مبرمجي بايثون اآلخرين لتحديد أي من الحلين املتكافئين ملشكلة ما هو "أكثر بايثونية" .الهدف من أن تكون "أكثر جزء من الهندسة وجزء من الفن .لسنا مهتمين ً بايثونية" يجسد فكرة أن البرمجة ٌ دائما فقط بإنجاح أيضا أن يكون حلنا ً ش يء ما ،بل نريد ً أنيقا وأن يحظى بتقدير الجميع. 8.7كتابة ا ِّمللفات ثان للتابع openكما في املثال التالي: لكتابة ملف ،عليك فتحه باستخدام الوضع " "wكمعامل ٍ )'>>> fout = open ('output.txt', 'w )>>> print(fout >'<_io.TextIOWrapper name='output.txt' mode='w' encoding='cp1252 ً موجودا بالفعل ،فإن فتحه في وضع الكتابة يؤدي إلى مسح البيانات القديمة ويبدأ من إذا كان امللف ُ َ ٌ جديد ،لذا كن ً فسينشأ ملف جديد. حذرا! أما إذا كان امللف غير موجود، يعمل تابع الكتابة writeالخاص بكائن معرف امللف على وضع البيانات في امللف وإرجاع عدد األحرف ُ ُ القيمة 24التي تمثل َ عدد الحروف املوجودة في املكتوبة كما نلحظ في املثال األدنى؛ إذ أرجعت السلسلة النصية املجودة بين عالمتي التنصيص " " .إن الوضع االفتراض ي هو ملف نص ي في حالتي الفصل السابع :امللفات 114 كتابة السالسل النصية وقراءتها. ">>> line1 = "This here's the wattle,\n )>>> fout.write(line1 24 مرة أخرى ،يحفظ كائن امللف مكانه ،لذلك إذا استدعيت تابع الكتابة writeمرة أخرى ،فإن البيانات الجديدة ُ ستضاف إلى النهاية. يجب أن نتأكد من إدارة نهايات األسطر في أثناء الكتابة على امللف عن طريق إدراج حرف إنشاء ُ ً السطر الجديد \nإدر ً صريحا عندما نريد إنهاء السطر .من هنا ينبغي أن نعرف أن تعليمة print اجا ُ ً ًّ ًّ تلقائيا ً تلقائيا. جديدا ،لكن استعمال التابع writeال يضيف السطر الجديد سطرا تضيف '>>> line2 = 'the emblem of our land.\n )>>> fout.write(line2 24 عند االنتهاء من عملية الكتابة ،يجب عليك إغالق امللف كما في الشيفرة أدناه للتأكد من كتابة آخر جزء من البيانات ً فعليا على القرص حتى ال يضيع هذا الجزء إذا انقطع التيار الكهربائي. )(>>> fout.close يمكننا إغالق امللفات التي نفتحها للقراءة ً أيضا ،ولكن يمكن أن نكون مهملين بعض الش يء إذا كنا َ البرنامج .أما نفتح بعض امللفات فقط ألن ُمفسر بايثون يغلق جميع امللفات املفتوحة عند انتهاء ً ً ً تفاديا من أي ش يء قد قاطعا وذلك عندما نكتب على امللفات ،فيجب علينا إغالق امللفات إغالقا يحدث. 9.7التنقيح عند قراءة امللفات أو الكتابة عليها ،قد تواجه مشكالت في الفراغات أو ما يسمى املسافات البيضاء. قد يكون من الصعب تصحيح هذه األخطاء ألن املسافات واإلزاحات واألسطر الجديدة عادة ما تكون َ غير مرئية كما في املثال التالي: '>>> s = '1 2\t 3\n 4 )>>> print(s 3 12 4 الفصل السابع :امللفات 115 يمكن أن يساعد التابع الجاهز reprفي حل هذه املشكالت؛ إذ يأخذ أي كائن كوسيط ويعيد سلسلة نصية تمثل الكائن .فيما يخص السالسل النصية ،إن ذلك التابع ُيمثل رموز املسافات البيضاء بسلسلة من الشرطات العكسية: ))>>> print(repr(s ''1 2\t 3\n 4 ً مفيدا ،ولكن ثمة مشكلة أخرى قد تواجهها ،وهي أن األنظمة املختلفة يمكن أن يكون التنقيح ً تستخدم محارفا مختلفة لإلشارة إلى نهاية السطر؛ إذ تستخدم بعض األنظمة الرمز \nإلنشاء سطر جديد ،في حين تستخدم أنظمة أخرى الرمز ،\rوتستخدم بعض األنظمة كال الرمزين .عند نقل امللفات بين أنظمة مختلفة ،فقد تتسبب هذه التناقضات في حدوث مشكالت. ُّ يخص معظم األنظمة ،ثمة تطبيقات للتحويل من تنسيق إلى آخر .يمكنك العثور عليها (وقراءة فيما املزيد عن هذه املشكلة) على الرابطhttps://www.wikipedia.org/wiki/Newline. : أو ،بالطبع ،يمكنك إنشاء تطبيق بنفسك. 10.7فهرس املصطلحات ُ َ البرنامج باستخدام • التقاط االستثناء ( :)catchطريقة تستخدم ملنع استثناء من إنهاء عبارات tryو.except ُ محرف إنشاء السطر الجديد ( :)newlineمحرف َم ٌّ عني يستخدم في امللفات والسالسل • النصية لإلشارة إلى نهاية السطر. • البايثونية ( :)Pythonicهي إسلوب برمجي خاص بلغة بايثون ،على سبيل املثال "استخدام tryو exceptهي طريقة بايثونية في حالة كانت امللفات التي ُ َ البرنامج مفقودة". استدعيت في ٌ شخص أو فريق يتركز عمله على ضمان الجودة • ضمان الجودة ( :)Quality Assuranceهو َ ً وغالبا ما يشارك فريق ضمان الجودة في اختبار املنتج وتحديد البرنامج الشاملة ملنتج َ البرنامج قبل طرحه للبيع. املشكالت في • ملف نص ي ( :)Text Fileعبارة عن سلسلة من األحرف املخزنة بوحدة تخزين دائم َ مثل ِّ القرص الصلب. الفصل السابع :امللفات 116 11.7تمارين • التمرين األول :اكتب َ ً (سطرا بسطر) كلها بأحرف برنام ًجا لقراءة ملف وطباعة محتوياته َ البرنامج على النحو التالي: كبيرة بحيث يبدو تنفيذ python shout.py Enter a file name: mbox-short.txt FROM STEPHEN.MARQUARD@UCT.AC.ZA SAT JAN 5 09:14:16 2008 >RETURN-PATH: <POSTMASTER@COLLAB.SAKAIPROJECT.ORG )]RECEIVED: FROM MURDER (MAIL.UMICH.EDU [141.211.14.90 ;BY FRANKENSTEIN.MAIL.UMICH.EDU (CYRUS V2.3.8) WITH LMTPA SAT, 05 JAN 2008 09:14:16 -0500 بإمكانك تنزيل امللف من خالل الرابط التالي: www.py4e.com/code3/mbox-short.txt • التمرين الثاني :اكتب َ برنام ًجا ملطالبة املستخدم باسم امللف ،ثم اقرأ محتويات امللف وابحث عن السطور التي تحتوي على الصيغة التاليةX-DSPAM-Confidence: 0.8475 : ً سطرا يبدأ بـ " ،":X-DSPAM-Confidenceافصل السطر الستخراج الرقم وحينما تصادف ذي الفاصلة العشرية من السطر. واحسب عدد هذه السطور ثم احسب إجمالي القيم ذات الفواصل العشرية في هذه السطور َ ( )Average spam confidenceوعندما تصل إلى نهاية امللف ،اطبع متوسطهم . َ البرنامج سيبدو على الشكل التالي: الحظ أن تنفيذ Enter the file name: mbox.txt Average spam confidence: 0.894128046745 Enter the file name: mbox-short.txt Average spam confidence: 0.750718518519 اختبر َ برنامجك على ملف mbox.txtوملف .mbox-short.txt الفصل السابع :امللفات 117 • التمرين الثالث :عندما يشعر املبرمجون ً أحيانا بامللل أو يرغبون في الحصول على القليل من َ املرح ،فإنهم يضيفون بعض املفاجئات إلى َ البرنامج الذي يطالب برنامجهم .قم بتعديل املستخدم باسم امللف بحيث يطبع رسالة مضحكة عندما يكتب املستخدم اسم امللف ً َ ًّ طبيعيا مع جميع امللفات البرنامج عمال بالشكل التالي" ."na na boo booيجب أن يعمل َ البرنامج: األخرى املوجودة وغير املوجودة .فيما يلي نموذج لتنفيذ python egg.py Enter the file name: mbox.txt There were 1797 subject lines in mbox.txt python egg.py Enter the file name: missing.tyxt File cannot be opened: missing.tyxt python egg.py Enter the file name: na na boo boo !NA NA BOO BOO TO YOU - You have been punk'd ُ مجرد تمرين ،فنحن ال نشجعك على ترك مفاجآت في برامجك! تذكر بأن هذا الفصل الثامن القوائم الفصل الثامن :القوائم 119 8القوائم 1.8القائمة هي سلسلة إن القائمة ) (Listهي سلسلة من القيم ،كما هي السالسل النصية ) ،(stringحيث تكون القيم في السلسلة النصية عبارة عن محارف ،بينما يمكن أن تكون القيم في القائمة أي نوع بيانات. ُ تسمى القيم في القائمة بـالعناصر ( elementsأو .)items يوجد العديد من الطرق إلنشاء قائمة جديدة .الطريقة األسهل هي حصر العناصر ضمن قوسين ُمربعين ("]" و"["): ][10, 20, 30, 40 ]'['crunchy frog', 'ram bladder', 'lark vomit يبين املثال األول قائمة مؤلفة من 4أعداد صحيحة .بينما الثاني عبارة عن قائمة مؤلفة من ثالث سالسل نصية. ليس بالضرورة أن تكون عناصر القائمة من النوع ذاته ،حيث تحتوي القائمة التالية على سلسلة نصية وعدد ذي فاصلة عشرية وعدد صحيح .كما أن بإمكانها احتواء قائمة أخرى. ]]['spam', 2.0, 5, [10, 20 إن وجود قائمة ضمن قائمة أخرى يعني أنها ُمتداخلة ( (nestedأما القائمة التي ال تحتوي عناصر فتسمى بالقائمة الفارغة ).(empty list بإمكانك إسناد قيم القائمة إلى ُمتغيرات: ]'>>> cheeses = ['Cheddar', 'Edam', 'Gouda ]>>> numbers = [17, 123 ][ = >>> empty )>>> print(cheeses, numbers, empty ][ ]['Cheddar', 'Edam', 'Gouda'] [17, 123 2.8القوائم قابلة للتعديل ُ إن القاعدة أو الطريقة املتبعة في الوصول إلى عناصر قائمة هي ذاتها املستخدمة في الوصول إلى الفصل الثامن :القوائم 120 املحارف في السلسلة النصية ،أي عامل القوس ( .(bracket operatorحيث يحدد التعبير داخل األقواس الفهرس املطلوب .تذكر أن الفهارس تبدأ من الـصفر. )]>>> print(cheese[0 cheddar ً خالفا للسالسل النصية ،فإن القوائم قابلة للتعديل ،حيث بإمكانك تغيير ترتيب عناصر قائمة ما، أو إعادة تعيين عنصر فيها. عندما يظهر عامل القوس في الجانب األيسر من عملية اإلسناد ،فهو يحدد ُع ً نصرا في القائمة ُ ست َ سند قيمة إليه. ]>>> numbers = [17, 123 >>> numbers[1] = 5 )>>> print(numbers ][17, 5 في املثال السابقُ ، العنصر األول من القائمة املتضمنة األعداد ،والذي كان ذا قيمة ،123أصبح اآلن .5 َ بإمكانك أن تعد القائمة عبارة عن عالقة بين الفهارس والعناصر ،وتسمى هذه العالقة بالربط ( ،)mappingحيث إن كل فهرس ُمرتبط بأحد العناصر. تعمل فهارس القوائم بنفس طريقة عمل فهارس السالسل النصية: • أي تعبير يمثل عدد صحيح ُيمكن أن ُيستخدم كفهرس. • إذا حاولت أن تقرأ أو تكتب ُع ً نصرا غير موجود ،ستحصل على خطأ فهرسة (.(IndexError ً ابتداء من نهاية القائمة. • إذا كان لفهرس ما قيمة سالبة ،فإنه يبدأ العد بشكل عكس ي ُيمكن للعامل inالتعامل مع القوائم ً أيضا. ]'>>> cheeses = ['Cheddar', 'Edam', 'Gouda >>> 'Edam' in cheeses True >>> 'Brie' in cheeses الفصل الثامن :القوائم 121 False 3.8املرورعلى عناصرقائمة ُيعد استخدام حلقة forالطريقة األكثر ُش ً يوعا للمرور على عناصر قائمة ،وبشكل مماثل للتعامل مع السالسل النصية: for cheese in cheeses: )print(cheese هذا ُمفيد إذا َ أردت فقط قراءة عناصر من القائمة ،لكن إن أردت كتابة أو تحديث العناصر ،فإن َك بحاجة إلى الفهارس .من الشائع استخدام كال التابعين َ rangeو lenلهذا الغرض: for i in range(len(numbers)): numbers[i] = numbers[i] * 2 ُتحدث هذه الحلقة قيمة كل عنصر في القائمة لدى ُمرورها على العناصر ً تباعا. ُيعيد التابع lenعدد العناصر في القائمة .بينما ُيعيد التابع rangeقائمة من الفهارس من 0حتى ،n-1حيث nهي عدد العناصر في القائمة. ُ ُ َ ستخدم قيمة iمن قبل تعليمة اإلسناد في جسم الحلقة ،حيث في كل مرة ندخل في الحلقة ،ت تستخد َم ُه لقراءة القيمة القديمة للعنصر ،وإسناد القيمة الجديدة إليه ،ويأخذ iقيمة فهرس العنصر التالي. ُ ال تنفذ حلقة forالتعليمات في جسم الحلقة في حالة القائمة الفارغة: for x in empty: )'print ('This never happens. أن تلك القائمة تعد كعنصر ُمنفرد .لذاَّ ، بالرغم من أن بإمكان القائمة احتواء قائمة أخرى ،إال َّ فإن طول القائمة التالية هو .4 ]]['spam', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3 الفصل الثامن :القوائم 122 ّ العمليات على القوائم 4.8 َ يجمع عامل الجمع +القوائم (يضعها جنبا إلى جنب بشكل متسلسل). ]>>> a = [1, 2, 3 ]>>> b = [4, 5, 6 >>> c = a + b )>>> print(c ][1, 2, 3, 4, 5, 6 بشكل ُمشابهُ ،يكرر عامل النجمة -الضرب * -القائمة بمقدار عدد معلوم من املرات. >>> [0] * 4 ][0, 0, 0, 0 >>> [1, 2, 3] * 3 ][1, 2, 3, 1, 2, 3, 1, 2, 3 ُيكرر املثال األول السلسلة 4مرات .بينما في املثال الثاني ،تتكرر السلسلة 3مرات. 5.8تجزئة القوائم يعمل عامل التجزئة ً أيضا مع القوائم: ]'>>> t = ['a', 'b', 'c', 'd', 'e', 'f ]>>> t[1:3 ]'['b', 'c ]>>> t[:4 ]'['a', 'b', 'c', 'd ]>>> t[3: ]'['d', 'e', 'f إذا تجاهلت الفهرس األول ،فإن التجزئة تبدأ من بداية القائمة .أما إذا تجاهلت الفهرس الثاني، الفصل الثامن :القوائم 123 تستمر التجزئة حتى النهاية .بينما إذا تجاهلت االثنين ً معا ] ،[ :فإن التجزئة هي عبارة عن نسخة ُمطابقة للقائمة بأكملها. ]>>> t[: ]'['a', 'b', 'c', 'd', 'e', 'f نظرا إلى أن القوائم قابلة للتعديل ،فمن املفيد ً ً غالبا نسخ القائمة قبل إجراء عمليات عليها. ُيمكن لعامل التجزئة على يسار عملية اإلسناد أن ُيحدث قيم عدة عناصر في نفس الوقت: ]'>>> t = ['a', 'b', 'c', 'd', 'e', 'f ]'>>> t[1:3] = ['x', 'y )>>> print(t ]'['a', 'x', 'y', 'd', 'e', 'f 6.8توابع ّ خاصة بالقوائم ً ً مثال ،يضيف التابع ُ appendع ً جديدا إلى نصرا تتضمن لغة بايثون عدة توابع للعمل على القوائم. نهاية قائمة. ]'>>> t = ['a', 'b', 'c )'>>> t.append('d )>>> print(t ]'['a', 'b', 'c', 'd في املثال التالي ،يأخذ التابع extendقائمة كوسيط ،ثم يضيف جميع عناصرها لقائمة أخرى دفعة واحدة: ]'>>> t1 = ['a', 'b', 'c ]'>>> t2 = ['d', 'e )>>> t1.extend(t2 )>>> print(t1 ]'['a', 'b', 'c', 'd', 'e لم يطرأ على t2في هذا املثال أي تعديل. الفصل الثامن :القوائم 124 ًّ تصاعديا: يرتب التابع sortعناصر القائمة ]'>>> t = ['d', 'c', 'e', 'b', 'a )(>>> t.sort )>>> print(t ]'['a', 'b', 'c', 'd', 'e َّ إن ُمعظم توابع القوائم من النوع ،voidحيث إنها تعدل على القائمة ،وتعيد ،Noneلذا إذا حدث َ وكتبت )( ،t = t.sortستحصل على نتيجة مخيبة لآلمال. 7.8حذف العناصر ُ ُ ُ هناك عدة طرق لحذف العناصر من القائمة .إذا كنت تعلم فهرس العنصر املراد حذفه ،بإمكانك عندئذ استعمال التابع .pop ٍ ]'>>> t = ['a', 'b', 'c )>>> x = t.pop(1 )>>> print(t ]'['a', 'c )>>> print(x b ُ ً ُ ُ تجري التعليمة popتعديال على القائمة ،وتعيد العنصر الذي أزيل. في حال لم ُتحدد ً فهرسا معي ًنا ،عندها تحذف popالعنصر األخير في القائمة ،وتخزنه كقيمة ُمرجعة. بإمكانك استخدام العامل delإذا لم تكن بحاجة لالحتفاظ بالقيمة املحذوفة: ]'>>> t = ['a', 'b', 'c ]>>> del t[1 )>>> print(t ]'['a', 'c إذا كنت على علم بالعنصر الذي ترغب بإزالته ،لكنك ال تعلم الفهرس الخاص به ،عندها بإمكانك استعمال .remove الفصل الثامن :القوائم 125 ]'>>> t = ['a', 'b', 'c )'>>> t.remove('b )>>> print(t ]'['a', 'c القيمة التي تعيدها removeهي .None إلزالة أكثر من عنصر ،بإمكانك استخدام delمع فهرس التجزئة: ]'>>> t = ['a', 'b', 'c', 'd', 'e', 'f ]>>> del t[1:5 )>>> print(t ]'['a', 'f كالعادة ،التجزئة تشمل كل العناصر املحددة من الفهرس األول حتى الفهرس الذي يسبق الفهرس الثاني ،أي ال تتضمن العنصر ذا الفهرس الثاني. 8.8القوائم والتوابع يوجد عدد من التوابع الجاهزة التي باإلمكان استخدامها على القوائم ،والتي تمنحك سالسة البحث في القائمة دون الحاجة إلى استخدام الحلقات: ]>>> nums = [3, 41, 12, 9, 74, 15 ))>>> print(len(nums 6 ))>>> print(max(nums 74 ))>>> print(min(nums 3 ))>>> print(sum(nums 154 ))>>> print(sum(nums)/len(nums الفصل الثامن :القوائم 126 25 ً أعدادا .أما التوابع األخرى ،مثل )(max يعمل تابع الجمع )( sumفقط عندما تكون عناصر القائمة َو)( lenوغيرها ،تعمل مع قوائم ذات عناصر من نوع سالسل نصية وأنواع البيانات األخرى القابلة للمقارنة. بإمكاننا إعادة كتابة البرنامج السابق الذي يـحسب املتوسط الحسابي لألعداد عبر استخدام القوائم. في البداية ،تمعن في البرنامج الذي يحسب املتوسط دون استخدام القوائم: total = 0 count = 0 while (True): )' inp = input('Enter a number: if inp == 'done': break )value = float(inp total = total + value count = count + 1 average = total / count )print('Average:', average # Code: http://www.py4e.com/code3/avenum.py في هذا البرنامج ،لدينا ٌّ كل من املتغيرين َ countو ،totalحيث ُيخزن املتغير countتعداد األعداد ،بينما َ يحفظ totalالقيمة التراكمية لألعداد التي يدخلها املستخدم. بإمكاننا ببساطة تخزين كل عدد عند إدخاله من قبل املستخدم ،واستخدام توابع جاهزة لحساب تعداد األعداد واملجموع في النهاية. )(numlist = list while (True): )' inp = input('Enter a number: if inp == 'done': break الفصل الثامن :القوائم 127 )value = float(inp )numlist.append(value )average = sum(numlist) / len(numlist )print('Average:', average # Code: http://www.py4e.com/code3/avelist.py أنشأنا قائمة فارغة قبل أن تبدأ الحلقة ،وبعد ذلك في كل مرة يكون لدينا عدد جديد نضيفه إلى القائمة .في نهاية البرنامج ،نحسب مجموع األعداد في القائمة ببساطة ،ثم نقسمه على عدد األعداد لنحصل على املتوسط الحسابي (املعدل). ّ النص ّية 9.8القوائم والسالسل إن السلسلة النصية هي سلسلة من املحارف ،بينما القائمة هي سلسلة من القيم ،ولكن القائمة ُ املؤلفة من مجموعة محارف ال تعتبر سلسلة نصية. للتحويل من سلسلة نصية إلى قائمة من املحارف ،بإمكانك استخدام التابع :list '>>> s = 'spam )>>> t = list(s )>>> print(t ]'['s', 'p', 'a', 'm وألن listهو اسم لتابع جاهز ،عليك ُّ تجنب استخدامه كاسم ملُتغير .وقد تجنبت ً أيضا استخدام الحرف ( Iالحرف األول من كلمة )listوذلك لشبهه بالعدد ،1لذلك استخدمت الحرف . t يقسم التابع listالسلسلة النصية إلى أحرف منفصلة .أما إذا َ أردت تقسيم السلسلة النصية إلى كلمات ،بإمكانك استخدام التابع .split '>>> s = 'pining for the fjords )(>>> t = s.split )>>> print(t ]'['pining', 'for', 'the', 'fjords الفصل الثامن :القوائم 128 )]>>> print(t[2 the بمجرد أن تستعمل splitلتقسيم السلسلة النصية إلى كلمات ،يكون بإمكانك استعمال عامل الفهرس (القوس القائم الزاوية) الختيار كلمة محددة من القائمة. يمكنك استدعاء splitمع وسيط اختياري ُيسمى ُمحدد ( ،(delimiterوالذي ُيحدد املحرف الذي َ ُ ست َّ الشرطة )ُ (hyphen كمحدد: قسم السلسلة وفقه .املثال التالي يستخدم '>>> s = 'spam-spam-spam '>>> delimiter = '- )>>> s.split(delimiter ]'['spam', 'spam', 'spam يعمل joinعكس عمل ،splitفهو يأخذ قائمة من السالسل النصية ،ويجمع العناصر. إن joinتابع خاص بالسلسلة النصية .لذلك ،الستخدامه ،عليك استدعاءه باستخدام محدد، ُ وتمرر القائمة كمعامل. ]'>>> t = ['pining', 'for', 'the', 'fjords ' ' = >>> delimiter )>>> delimiter.join(t ''pining for the fjords ُ ً وفي هذه الحالة يكون املحدد هو محرف املسافة الفارغة ’ ‘ ،وبالتالي فإن تعليمة joinتضع فراغا بين الكلمات .لكي ترتب السالسل النصية دون فراغات ،يمكنك استخدام السلسلة الخالية "" ُ كمحدد. 10.8التعامل مع األسطرفي امللفات َ عادة ،عند قراءتنا مللف ،فنحن نرغب بالتعديل على األسطر أكثر ما نرغب بمجرد عرض السطر بأكمله. في أكثر األحيان ،نرغب بإيجاد "األسطر املهمة" ،ومن َّ ثم تحليل السطر نفسه إليجاد أجزاء مهمة منه. على سبيل املثال ،ماذا لو أردنا طباعة اختصار اسم يوم من أيام األسبوع الواردة في هذه األسطر التي تبدأ بكلمة ""From؟ الفصل الثامن :القوائم 129 From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 يعد تابع splitفع ًاال ًّ جدا عندما نواجه هذا النوع من املسائل. بإمكاننا كتابة برنامج صغير يبحث عن األسطر التي تبدأ بـ ،Fromويفصل هذه األسطر ،ومن ثم طباعة الكلمة الثالثة في السطر. )'fhand = open('mbox-short.txt for line in fhand: )(line = line.rstrip if not line.startswith('From '): continue )(words = line.split )]print(words[2 # Code: http://www.py4e.com/code3/search5.py ُينتج البرنامج الخرج التالي: Sat Fri Fri Fri ... ً ات ُمتقدمة النتقاء األسطر التي ُنريد العمل عليها ،وكيف نفرق الحقا ،سنتعلم بشكل مفصل تقني ٍ هذه األسطر إليجاد املعلومة التي نبحث عنها بدقة. َ والقيم 11.8الكائنات إذا َّنفذنا تعليمات اإلسناد التالية: 'a = 'banana 'b = 'banana نعلم أن كل من َ aوُ bيشيران إلى سلسلة نصية ،لكننا ال نعلم ما إذا كانا ُيشيران إلى نفس السلسة الفصل الثامن :القوائم 130 النصية .هناك حالتان ممكنتان: الشكل :12القيم والكائنات في الحالة األولى a :وُ bيشيران إلى كائنين ُمختلفين لهما نفس القيمة. في الحالة الثانية a :وُ bيشيران إلى الكائن نفسه. لنختبر ما إذا كان ُهناك ُمتغيران ُيشيران إلى نفس الكائن .باإلمكان استخدام املعامل .is '>>> a = 'banana '>>> b = 'banana >>> a is b True ُ في هذا املثال ،تنش ئ بايثون كائن واحد لسلسلة نصية ،حيث ُيشير إليه كل من aو .b ُ لكن عندما تنش ئ قائمتين فإنك تحصل على كائنين. ]>>> a = [1, 2, 3 ]>>> b = [1, 2, 3 >>> a is b False في هذه الحالة ،نقول إن القائمتين متكافئتان ) ،(equivalentألن لديهما نفس العناصر ،لكنهما غير متطابقتين ) ،(identicalألنهما ليسا الكائن ذاته. إذا كان لدينا كائنان متطابقان ،فهذا يعني أنهما متكافئان (متساويان) ،ولكن كونهما متكافئين ال يعني بالضرورة أنهما متطابقان. إلى حد اآلن ،نحن نستخدم "الكائن" ( )objectو"القيمة" ( )valueبالتبادل ،ولكن لتوخي الدقة نقول إن للكائن قيمة خاصة به. إذا نفذت ]ُ ،a = [1,2,3تشير aإلى كائن لقائمة ،والتي َ قيمها هي سلسلة محددة من العناصر. الفصل الثامن :القوائم 131 إذا امتلكت قائمة أخرى نفس العناصر ،نقول إن لها نفس القيمة. 12.8التسمية البديلة إذا كان ُ aيشير إلى كائن ،وأجريت عملية إسناد ،b = aعندها كال املُتغيرين ُ سيشيران إلى نفس الكائن: ]>>> a = [1, 2, 3 >>> b = a >>> b is a True ُ ُيسمى ارتباط املتغير بالكائن بـ املرجع ( ،(referenceفي هذا املثال ،يوجد مرجعين لنفس الكائن. يكون للكائن الذي لديه أكثر من مرجع واحد أكثر من اسم واحد ،لذلك نقول يملك هذا الكائن ً اسما ً ً بديال ( .)aliasedإذا كان الكائن ذو االسم البديل قابال للتعديل ،فإن التغيرات التي تحدث مع البديل تؤثر على اآلخر: >>> b[0] = 17 )>>> print(a ][17, 2, 3 على الرغم من أن هذا السلوك ُيمكن أن يكون ُم ً فيدا ،إال أنه مسبب للخطأ. تجنب التسمية البديلة ُي َع ُّد أكثر ً بشكل عام ،إن ُّ أمانا عند عملنا مع كائنات قابلة للتعديل. ُ من أجل الكائنات غير القابلة للتعديل ،مثل السالسل النصية ،ال تعد التسمية البديلة مشكلة. كما في املثال: 'a = 'banana 'b = 'banana ُ ً تقريبا ال يوجد فرق فيما إذا كانت aأو bتشير إلى نفس السلسلة النصية ،أم ال. 13.8وسائط القائمة ُ عندما تمرر قائمة إلى تابع ،يحصل التابع على مرجع للقائمة .إذا عدل التابع على ُمعامل القائمة، ُ تالحظ التغيير عند االستدعاء .على سبيل املثال ،يحذف التابع delete_headالعنصر األول من القائمة: الفصل الثامن :القوائم 132 def delete_head(t): ]del t[0 إليك كيفية استخدامه: ]'>>> letters = ['a', 'b', 'c )>>> delete_head(letters )>>> print(letters ]'['b', 'c ُ املعامل َ tواملتغير lettersهما أسماء بديلة لنفس الكائن. ً ُ ُ ُ من املهم أن نميز بين العمليات التي تعدل القوائم ،والعمليات التي تنش ئ قوائم جديدة .مثال ،تعدل appendعلى القائمة ،بينما ينشأ عامل الجمع +قائمة جديدة. ]>>> t1 = [1, 2 )>>> t2 = t1.append(3 )>>> print(t1 ][1, 2, 3 )>>> print(t2 None ]>>> t3 = t1 + [3 )>>> print(t3 ][1, 2, 3 >>> t2 is t3 False ُ ُ يكون هذا االختالف ًّ مهما عندما تكتب توابع من املفترض بها أن تعدل القوائم. ً مثال ،هذا التابع ال يحذف أول عنصر في القائمة: def bad_delete_head(t): !# WRONG ]t = t[1: الفصل الثامن :القوائم 133 ُ ُ ألي من هذا تأثير على القائمة ينش ئ عامل التجزئة قائمة جديدة ،بحيث تشير tإلى القائمة .ولكن ليس ٍ التي ُمر َرت كوسيط. البديل هو إنشاء تابع ينش ئ قيمة جديدة ُويعيدها .على سبيل املثالُ :يعيد التابع tailجميع العناصر عدا العنصر األول من القائمة: def tail(t): ]return t[1: يترك هذا التابع القائمة األصلية بال أي تعديل .إليك كيفية استخدامه: ]'>>> letters = ['a', 'b', 'c )>>> rest = tail(letters )>>> print(rest ]'['b', 'c التمرين األول :أنش ئ ً تابعا باسم ،chopبحيث يأخذ قائمة ُويعدل عليها عن طريق إزالة العنصرين ثم أنش ئ ً األول واألخيرُ ،ويعيد َّ ،none تابعا باسم middleيأخذ قائمة ُويعيد قائمة جديدة تحوي جميع العناصر عدا األول واألخير. 14.8التنقيح إن سوء استخدام القوائم (والكائنات األخرى القابلة للتعديل) قد يقود إلى ساعات طويلة من عملية التنقيح .إليك بعض َ الحيل واألساليب لتجنب ذلك: ُ ُ َ 1ال َ عكس عمل تنس أن ُمعظم توابع القوائم تعدل الوسيط وتعيد ( Noneال ش يء)ُ .يعد هذا ُ توابع السالسل النصية التي تعيد سلسلة نصية جديدة ،وتتغاض ى عن السلسلة األصلية. إذا َ كنت ُم ً عتادا على كتابة شيفرة السلسلة النصية على الشكل التالي: (word = word.strip قد تكتب شيفرة القائمة على الشكل التالي: !# WRONG )(t = t.sort ُ وألن التابع ُ sortيعيد ،Noneفإن العملية التالية التي تجريها مع tمصيرها الفشل. الفصل الثامن :القوائم 134 قبل استخدام توابع وعوامل القوائم ،عليك قراءة ملفات التوثيق بعناية ،واختبارها في الوضع التفاعلي. ُ تصفح ملفات توثيق التوابع والعوامل التي تشاركها القوائم مع سالسل أخرى (كالسالسل النصية) في: docs.python.org/library/stdtypes.html#common-sequence-operations ُ والتوابع والقوائم التي تطبق فقط على السالسل القابلة للتغيير هنا: docs.python.org/library/stdtypes.html#mutable-sequence-types َ ً صطلحا ،والتزم به: 2اختر ُم ً إن جزء من املشكلة مع القوائم ُ يكمن في تعدد األساليب للقيام باألشياء .مثال ،إلزالة عنصر من ُ القائمةُ ،يمكنك استخدام كل من َ ،popوَ ،removeو ،delوحتى التجزئة. إلضافة ُعنصر ،يمكنك استخدام طريقة ،appendأو عامل الجمع .+لكن ،ال َ تنس أن ما يلي ً صحيحا: ُيعد )t.append(x ]t = t + [x أما ما يلي ،فهو خاطئ: !# WRONG !# WRONG !# WRONG !# WRONG )]t.append([x )t = t.append(x ]t + [x t=t+x نفذ هذه األمثلة في الوضع التفاعلي لتضمن أنك تفهم آلية عملهم. انتبه إلى أن السطر األخير فقط ُيسبب خطأ تشغيل ( ،(runtime errorبينما الثالث أسطر الباقية مسموحة ،لكنها تنفذ ً أمورا خاطئة. 3انسخ لتجنب التسمية البديلة: ُ ُ إذا كنت تريد استخدام تابع كـ sortالذي ُيعدل على الوسيط ،ولكنك تريد االحتفاظ الفصل الثامن :القوائم 135 بالقائمة األصلية على أية حال ،يمكنك عمل نسخة. ]orig = t[: )(t.sort ُيمكنك في هذا املثال ً أيضا استخدام التابع الجاهز ،sortedوالذي ُيعيد قائمة جديدة ُمرتبة ،ويترك القائمة األصلية على حالها .لكن ،في تلك الحالة ،احرص على ُّ تجنب استخدام ُ sortedكاسم ملتغير. 4استخدام القوائم والتابع splitمع امللفات: عندما نقرأ ونحلل امللفات ،هناك احتمالية أن إحدى املدخالت قد توقف برنامجنا .لذا، ً ً فإن إعادة النظر في نمط الحماية ُيعد فكرة جيدة عند كتابة البرامج التي تبحث في امللف َ "كالبحث عن إبرة في كومة قش". ُ دعونا نعد النظر في برنامجنا الذي يبحث عن يوم من أيام األسبوع من السطور املوجودة في ملف. From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 ُبمجرد تقسيمنا السطر إلى كلمات ،بإمكاننا االستغناء عن استخدام تعليمة ،startswith ُ والنظر ببساطة إلى الكلمة األولى من السطر لتحديد ما إذا كنا ُمهتمين في السطر ككل .كما بإمكاننا استخدام continueلتخطي السطور التي ال تحتوي الكلمة Fromككلمة أولى على النحو التالي: )'fhand = open('mbox-short.txt for line in fhand: )(words = line.split if words[0] != 'From' : continue )]print(words[2 يبدو هذا أكثر سهولة .باإلضافة إلى أننا ال نحتاج حتى إلى تنفيذ التابع rstripإلزالة محرف السطر الجديد في نهاية امللف .لكن هل هذا أفضل؟ الفصل الثامن :القوائم 136 python search8.py Sat Traceback (most recent call last): >File "search8.py", line 5, in <module if words[0] != 'From' : continue IndexError: list index out of range ً ً صحيحا ،بحيث أننا نحصل على اليوم من السطر األول (السبت .)satلكن ،بعد قد يبدو هذا عمال ذلك يفشل البرنامج مع وجود خطأ .ما الخطأ الذي حصل؟ ما هي البيانات التالفة التي تسببت بفشل برنامج بايثون األنيق والذكي الخاص بنا؟ ً ُ قد تفكر مطوال في البرنامج ،وتتملك َك الحيرة ،أو يمكن أن تسأل شخص ما ملساعدتك. َّ ولكن النهج األذكى واألسرع هو إضافة تعليمة .printإن املكان األفضل إلضافة تعليمة printهو بالتحديد قبل السطر الذي أخفق به البرنامج ،ثم طباعة البيانات التي تبدو ُمسببة للفشل. قد يؤدي هذا النهج إلى عرض الكثير من األسطر في الخرج ،لكن على األقل ستكون قد كشفت ً فورا ُ على طرف الخيط لحل املشكلة ،لذلك أضفنا تعليمة طباعة املتغير wordsقبل السطر الخامس ُ ً ُمباشرة .حتى أننا أضفنا البادئة " "Debug:إلى السطر البرمجي ،بحيث نتمكن من املحافظة على خرج ً البرنامج ُمنفصال عن خرج عملية التنقيح. for line in fhand: )(words = line.split )print('Debug:', words if words[0] != 'From' : continue )]print(words[2 ُ عندما نشغل البرنامج ،تعرض الكثير من السطور على الشاشة .لكن ،في النهاية ،نرى خرج التنقيح الخاص بنا ،وخطأ التتبع ،لذا ُندرك ما حدث بالضبط قبل خطأ ُّ التتبع. ]'Debug: ['X-DSPAM-Confidence:', '0.8475 ]'Debug: ['X-DSPAM-Probability:', '0.0000 ][ Debug: الفصل الثامن :القوائم 137 Traceback (most recent call last): >File "search9.py", line 6, in <module if words[0] != 'From' : continue IndexError: list index out of range كل سطر من عملية التنقيح يطبع قائمة من الكلمات ،والتي نحصل عليها عند تفرقة السطر إلى كلمات. عندما يفشل البرنامج ،تكون قائمة الكلمات فارغة ][ .إذا فتحنا امللف في ُمحرر النصوص وتفحصناه ،سيظهر على الشكل التالي: X-DSPAM-Result: Innocent X-DSPAM-Processed: Sat Jan 5 09:14:16 2008 X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772 يظهر الخطأ عندما يصطدم برنامجنا بسطر فارغ. ُ بالطبع ،ال يحتوي السطر الفارغ على كلمات .ملاذا لم نفكر بذلك عند كتابة البرنامج؟ ُ عندما تبحث الشيفرة عن الكلمة األولى ] word[0للتحقق منها ملعرفة ما إذا كانت تطابق ،From نحصل على خطأ فهرس خارج النطاق ). (index out of range error بالطبع ،هذا هو املكان املثالي إلضافة البعض من شيفرات الحماية – guardian code ُّ لتجنب عملية التحقق من الكلمة األولى في حال لم تكن الكلمة األولى موجودة. يوجد العديد من األساليب لحماية هذه الشيفرة .سنلجأ إلى التحقق من عدد الكلمات التي لدينا قبل البحث عن الكلمة األولى: )'fhand = open('mbox-short.txt count = 0 for line in fhand: الفصل الثامن :القوائم 138 )(words = line.split )# print('Debug:', words if len(words) == 0 : continue if words[0] != 'From' : continue )]print(words[2 ً في البداية ،تجاهلنا تعليمة التنقيح بدال من إزالتها ،والسبب أنه في حال فشل التعديل الذي قمنا به، فنحن بحاجة إلى التنقيح ُمجد ًدا. ثم أضفنا تعليمة حماية تتحقق من حالة عدم وجود كلمات .وفي هذه الحالة ،نستعمل التعليمة continueلتخطي السطر التالي في امللف. ُ ُ ُيمكننا اعتبار أن تعليمتي continueتساعداننا في تنقيح بعض األسطر البرمجية "املهمة" بالنسبة ُ ُ لنا ،والتي نريد أن نخضعها ملزيد من املعالجة. إن السطر الذي ال يحوي كلمات ُيعد "غير مهم" ،لذلك نتخطاه إلى السطر الذي يليهً . أيضا السطر الذي ال يحوي كلمة Fromككلمة أولى غير مهم ،ويمكن تخطيه. إن البرنامج -كما ُعد َل -يعمل بنجاح ،لذا من املمكن أن يكون صحيح. ً كاف ،ألننا عندما إن تعليمة الحماية تحرص على أن ] words[0لن تفشل أبدا .لكن ،ربما هذا غير ٍ ُنبرمج نتساءل ً دوما" ،ما الخطأ الذي قد يحدث"؟ محمي بشكل كامل. التمرين الثاني :اكتشف أي سطر من البرنامج أعاله ال يزال غير ٍ تحقق من إمكانية إنشاء ملف نص ي يؤدي إلى فشل البرنامجًّ ، ثم عدل البرنامج بحيث تؤمن حماية ُ اختبره للتأكد من تعامله السليم مع ملفك النص ي الجديد. للسطر البرمجي .بعد ذلك، ً التمرين الثالث :أعد كتابة شيفرة الحماية في املثال أعاله دون استعمال تعليمتي ifفبدال من ذلك، ُ استخدم التعبير املنطقي املركب باستخدام العامل املنطقي orمع عبارة ifواحدة. 15.8فهرس املصطلحات • التسمية البديلة ( :)Aliasingالحالة التي يكون فيها ُمتغيران أو أكثر ُيشيران إلى نفس الكائن. الفصل الثامن :القوائم 139 ُ ُ امل ّ حد ْد ( :)Delimiterمحرف أو سلسلة نصية ،تستعمل لإلشارة إلى املكان الذي يجب أن • ِّ ُ تفصل به السلسلة النصية. العنصر( :)Elementواحد من القيم في القائمة (أو سلسلة أخرى) ،يمكن أن نسميه أي ً • ُ ضا .item ُ كافئ (ُ :)Equivalentله القيمة ذاتها. • م ِّ ُ • الفهرس ( :)indexقيمة صحيحة تشير إلى عنصر في القائمة. ُ التطابق (ُ :)Identicalمطابق لنفس الكائن (بما يعني التكافؤ). • • القائمة ( :)Listسلسلة من القيم. • املرورعلى عناصرقائمة ( :)List traversalالوصول التسلسلي إلى كل عنصر في القائمة. ُ • القائمة املتداخلة ( :)Nested listالقائمة التي تكون ُع ً نصرا ضمن قائمة أخرى. • الكائن ( :)Objectش يء أو ُمتغير ُيمكن اإلشارة إليه ،بحيث يكون للكائن نوع وقيمة. ُ • املرجع ( :)Referenceيمثل االرتباط بين املتغير وقيمته. 16.8تمارين • التمرين الرابع :حمل نسخة من امللف من الرابط التالي: www.py4e.com/code3/romeo.txt ً برنامجا لفتح امللف romeo.txtوقراءته ً سطرا بسطر. اكتب ً َ ُ ُ من أجل كل سطر ،فرق السطر إلى كلمات ُمستعمال التابع .splitومن أجل كل كلمة ،تحقق ما إذا كانت موجودة ُم ً سبقا في القائمة .في حال لم تكن موجودة ،أضفها إلى القائمة. ً عند اكتمال البرنامج ،رتب واطبع الكلمات الناتجة ً أبجديا. ترتيبا Enter file: romeo.txt ['Arise', 'But', 'It', 'Juliet', 'Who', 'already', 'and', 'breaks', 'east', 'envious', 'fair', 'grief', 'is', 'kill', 'light', 'moon', 'pale', 'sick', 'soft', 'sun', 'the', 'through', 'what', 'window', الفصل الثامن :القوائم 140 ]''with', 'yonder ً برنامجا لقراءة بيانات امللف . mail boxعندما تجد ً سطرا يبدأ • التمرين الخامس :اكتب مستخدما التابع ُ .split ً نحن ُّ نهتم ُبمرسل الرسالة، بـ ،Fromقسم السطر إلى كلمات والتي هي الكلمة الثانية من السطر. From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 ُ ستحلل السطر الذي يبدأ بـ ،Fromثم تطبع الكلمة الثانية من كل سطر يبدأ بـ .From باإلضافة إلى ذلك ،ستحص ي عدد السطور التي تبدأ بـ ،Fromوتطبع العدد في النهاية. فيما يلي خرج لعينة محذوف منها بضعة أسطر: python fromcount.py Enter a file name: mbox-short.txt stephen.marquard@uct.ac.za louis@media.berkeley.edu zqian@umich.edu ][...some output removed... ray@media.berkeley.edu cwen@iupui.edu cwen@iupui.edu cwen@iupui.edu There were 27 lines in the file with From as the first word • التمرين السادس :أعد كتابة البرنامج الذي يطلب من املستخدم قائمة مكونة من ُ أعداد ،ث َّم يطبع العدد األعظمي واألصغري من األعداد عندما ُيدخل املستخدم ""done في نهاية البرنامج. اكتب البرنامج لتخزين األعداد التي أدخلها املستخدم إلى القائمة .واستخدم التابعين القوائم:الفصل الثامن 141 . لحساب القيمة األعظمية واألصغرية لألعداد بعد اكتمال الحلقةmin() َوmax() Enter a number: 6 Enter a number: 2 Enter a number: 9 Enter a number: 3 Enter a number: 5 Enter a number: done Maximum: 9.0 Minimum: 2.0 الفصل التاسع القواميس الفصل التاسع :القواميس 143 9القواميس يشابه القاموس ( )dictionaryالقوائم ( )listإال أنه أكثر شمولية ،ففي القوائم تكون فهارس املواقع أعداد صحيحة intعلى عكس القواميس حيث قد تكون من أي نوع ،حيث يمكنك تخيل القاموس وكأنه يربط بين مجموعة فهارس والتي تدعى باملفاتيح ) )keysومجموعة من القيم ) ،(valuesحيث يدعى ارتباط املفتاح مع القيمة بزوج مفتاح-قيمة ( (key-value pairأو ً أحيانا يدعى بالعنصر ).(item لتوضيح ما سبق ،سننش ئ قاموس يربط كلمات باإلنكليزية مع ترجماتها في اللغة اإلسبانية بالتالي هنا كال املفاتيح والقيم هما من نوع البيانات سالسل نصية. ً ً قاموسا فارغا بدون أي عناصر .لذا ،يجب عليك تجنب تسمية متغيراتك بهذا ينش ئ التابع dict االسم ،ألنه اسم تابع في لغة بايثون: )(>>> eng2sp = dict )>>> print(eng2sp }{ ً تمثل أقواس املجموعة {} قامو ًسا فارغا وإلضافة عناصر لهذا القاموس يجب استخدام األقواس القائمة []: '>>> eng2sp['one'] = 'uno حيث يضيف هذا السطر البرمجي عنصر يرتبط فيه املفتاح ' 'oneبالقيمة " "unoفإذا أظهرنا محتوى القاموس ينتج لدينا زوج مفتاح-قيمة يفصل بينهما عالمة النقطتين: )>>> print(eng2sp }'{'one' : 'uno تماثل صيغة الدخل صيغة الخرج في املثال السابق ،لكن في حال إنشاء قاموس بثالثة عناصر قد تتفاجأ عند طباعة eng2spحيث يظهر ما يلي: }'>>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres )>>> print(eng2sp }'{'one': 'uno', 'three': 'tres', 'two': 'dos الفصل التاسع :القواميس 144 حيث ترتيب العناصر ال يكون نفسه في كل مرة وال يمكن التنبؤ به في القواميس ،حتى إن جربت كتابة نفس املثال على حاسوبك فقد تحصل على نتيجة مختلفة ،إال أن هذا ال يشكل مشكلة ألن فهارس ُ العناصر في القواميس ليست عبارة عن أرقام صحيحة بل تستخدم املفاتيح إلظهار القيمة املوافقة لها: )]'>>> print(eng2sp['two ''dos فاملفتاح ' 'twoمرتبط بالقيمة 'ً 'dos دائما .فيكون ترتيب العناصر غير مهم ،وستحصل على رسالة خطأ إن كان القاموس ال يحوي املفتاح املطلوب: )]'>>> print(eng2sp['four 'KeyError: 'four ويمكن استخدام التابع lenمع القواميس ليظهر عدد العناصر في القاموس: )>>> len(eng2sp 3 كما يمكن استخدام العامل inمعها حيث يؤكد وجود مفتاح معين في القاموس من عدمه (ال يتعامل مع القيم): >>> 'one' in eng2sp True >>> 'uno' in eng2sp False أما للبحث عن قيمة ما ضمن القاموس ،يمكن استخدام تابع يدعى valuesيعيد القيم كقائمة ثم نستخدم العامل :in ))(>>> vals = list(eng2sp.values >>> 'uno' in vals True لكل من القوائم والقواميس ،ففي مع األخذ بعين االعتبار أن العامل inيستخدم خوارزميات مختلفة ٍ الفصل التاسع :القواميس 145 القوائم ،يعتمد على خوارزمية بحث خطية ،مما يزيد الوقت الالزم للبحث في قيم القائمة كلما زاد طولها .بينما تستخدم بايثون للقواميس خوارزمية تدعى " "hash tableوالتي تتميز بأن العامل in قاموس ما بغض النظر عن عدد عناصره .وال يمكننا سيستغرق نفس الوقت في البحث ضمن ٍ الحديث هنا عن ميزات هذه الخوارزمية الرائعة ولكن بإمكانك أن تقرأ القليل عنها من هنا: www.wikipedia.org/wiki/Hash_table التمرين األول :حمل نسخة من امللف املوجود على الرابط اآلتي: www.py4e.com/code3/words.txt ً قاموس ما بغض النظر عما برنامجا يقرأ الكلمات املوجود في هذا امللف ثم يخزنها كمفاتيح في اكتب ٍ ستكون عليه القيم ،ثم استخدم العامل inللتحقق من وجود كلمة معينة. 1.9استخدام القواميس في العد ُ نص أمامك تريد أن تستخرج منه عدد مرات تكرار كل حرف ،توجد عدة طرق لحل افترض وجود ٍ هذا: .1بإمكانك إنشاء 26متغير حيث يقابل كل متغير أحد األحرف األبجدية اإلنكليزية ،ثم تمر على ً مستخدما سلسلة من العبارات كل محرف على حدى لتزيد قيمة العداد املوافقة لكل متغير الشرطية. .2تستطيع إنشاء قائمة ذات 26عنصر ثم تحويل كل محرف إلى رقم بواسطة التابع ord الستخدامه كفهرس في القائمة وزيادة العداد املوافق له. .3يمكن إنشاء قاموس حيث تشكل األحرف املفاتيح فيه ،وتشكل عددها القيم املوافقة للمفاتيح. ُ فعند اكتشاف املحرف ألول مرةُ ، سيدخل عنصر جديد للقاموس بينما في املرات التالية ستزاد قيمة هذا العنصر فقط. تحل كل طريقة من هذه الطرق املشكلة بأسلوب مختلف ،ونجد هنا مفهوم التنفيذ ويعني أسلوب حل مسألة ما ،وتكون بعض هذه االساليب أفضل من غيرها ،فعلى سبيل املثال تكمن فائدة تطبيق مسبقا بل نخصص لها ً ً مكانا ً معينا استخدام القاموس في عدم حاجتنا ملعرفة األحرف التي ستظهر بعد ظهورها ،وسيبدو البرنامج كما يأتي: الفصل التاسع :القواميس 146 'word = 'brontosaurus )(d = dict for c in word: if c not in d: d[c] = 1 else: d[c] = d[c] + 1 )print(d أي أننا ً علميا حسبنا الهيستوغرام ) )histogramوهو مصطلح إحصائي يدل على مجموعة من العدادات (أو التكرارات) للعناصر .وكما نرى فإن الحلقة forتمر على محارف النص ،وفي كل مرة ال نجد املحرف ضمن القاموس ننش ئ عنصر جديد فيه مفتاحه cوقيمته االبتدائية ( 1بما أن املحرف ً ً مسبقا فنكتفي بزيادة قيمة ] d[cليكون خرج موجودا ضمنه ظهر ملرة واحدة) ،لكن إن كان املفتاح c البرنامج كاآلتي: }{'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1 أي ،يبين الهيستوغرام أن األحرف aو bقد ظهرت مرة واحدة في حين تكرر oمرتين وهكذا دواليك، كما تملك القواميس تابع يدعى getيتطلب هذا التابع معاملين هما املفتاح وقيمة معينة يعيدها في حال عدم وجود املفتاح ضمن القاموس وإال يعيد القيمة املوافقة للمفتاح واملوجودة ضمن القاموس ،وتمثل هذه التعليمة كما يأتي: }counts = { 'chuck': 1 , 'annie': 42, 'jan': 100 ))>>> print ( counts.get ( ‘jan’, 0 100 ))>>> print ( counts.get (‘tim’, 0 0 وهذا يمكننا من كتابة برنامجنا بأسلوب مختصر أكثر فالتابع getيحل مسألة عدم وجود املفتاح ً تلقائيا مما يؤدي إلى اختصار أربعة أسطر برمجية إلى واحد واالستعاضة عن تعليمة ضمن القاموس :if الفصل التاسع :القواميس 147 'word = 'brontosaurus )(d = dict for c in word: d[c] = d.get(c,0) + 1 )print(d إن اتباع هذا األسلوب شائع في بايثون وسنستعمله عدة مرات في بقية الكتاب ،لذلك قد تحتاج بعض الوقت لتقارن بين األسلوبين حيث استخدمنا getلالستعاضة عن تعليمة ifوالعامل inفي الحلقة ً اختصارا. فكالهما يؤديان نفس الوظيفة إال أن أحدهما أكثر 2.9القواميس وامللفات ً ً شائعا، استخداما إن استخدام القواميس لعد عدد مرات تكرار الكلمات في امللفات النصية يعد لذلك سنبدأ بتوضيح هذا بمثال صغير مأخوذ من امللف النص ي " "Romeo and Julietحيث في األمثلة األولى سنستخدم نسخة مبسطة ومختصرة من النص بدون عالمات ترقيم كما يأتي: But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief سنكتب اآلن برنامج بلغة بايثون يقرأ أسطر النص ويجزئها إلى قائمة من الكلمات ثم يمر على كل منها ً باستخدام حلقة ليعد مرات تكرارها حافظا النتيجة في قاموس .كما ستالحظ أننا استخدمنا حلقتي forحيث تقرأ األولى أسطر النص ،بينما تمر الثانية على كلمات كل سطر .ويدعى هذا النمط بالحلقات املتداخلة ( (nested loopsوسبب التسمية يرجع لوجود حلقة خارجية وأخرى داخلية ضمنها .وتنفذ الحلقة الداخلية جميع تكراراتها من أجل كل تكرار للحلقة الخارجية ،فيبدو وكأن الحلقة الداخلية تعمل بشكل سريع بينما تكون الخارجية أبطأ منها ،و ً أيضا يضمن لنا هذا النمط املرور على كل كلمة في كل سطر من النص املدخل: ) ‘ fname = input(‘Enter the file name: try: )fhand = open(fname القواميس:الفصل التاسع 148 except: print(‘File cannot be opened: ‘, fname) exit() counts = dict() for line in fhand: words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 print(counts) # Code: http://www.py4e.com/code3/count1.py counts[word]+=1 التعليمة البديلة املختصرة للزيادة العددية حيثelse لقد استخدمنا في تعليمة أي منهما لتغيير القيمة العددية بأي ٍ ويمكن استخدامcounts[word]=counts[word]+1 تكافئ وعند تنفيذ البرنامج سنحصل على سطر/= و =* و-= قيمة مطلوبة حيث توجد بدائل شبيهة مثل منromeo.txt من العدادات بصيغة غير مرتبة كما يأتي (يمكن الحصول على امللف :)www.py4e.com/code3/romeo.txt python count1.py Enter the file name: romeo.txt {'and': 3, 'envious': 1, 'already': 1, 'fair': 1, 'is': 3, 'through': 1, 'pale': 1, 'yonder': 1, 'what': 1, 'sun': 2, 'Who': 1, 'But': 1, 'moon': 1, 'window': 1, 'sick': 1, 'east': 1, 'breaks': 1, 'grief': 1, 'with': 1, 'light': 1, 'It': 1, 'Arise': 1, 'kill': 1, 'the': 3, 'soft': 1, 'Juliet': 1} لذلك سنضيف بعض التعليمات،ولكنه من غير املريح البحث عن أكثر الكلمات تكر ًارا في القاموس .البرمجية للحصول على الخرج املطلوب الفصل التاسع :القواميس 149 3.9الحلقات والقواميس إن حلقة forتمر على مفاتيح القاموس وفي مثالنا اآلتي فإنها ستطبع املفتاح مع القيمة املوافقة له: }counts = { 'chuck': 1 , 'annie': 42, 'jan': 100 for key in counts: )]print(key, counts[key فيكون الخرج: jan 100 chuck 1 annie 42 وكما ذكرنا ً بترتيب معين ،ويمكننا استخدام هذا النمط لتنفيذ ما تعلمناه سابقا فاملفاتيح غير مرتبة ٍ ً سابقا ،فعلى سبيل املثال سنكتب البرنامج اآلتي للحصول على عناصر القاموس ذات قيمة أكبر من عشرة: }counts = { 'chuck': 1 , 'annie': 42, 'jan': 100 for key in counts: if counts[key] > 10 : )]print(key, counts[key ستمر الحلقة على مفاتيح القاموس لذلك نستخدم عامل الفهرس الستدعاء القيمة املوافقة للمفتاح ويكون الخرج: jan 100 annie 42 أي أننا حصلنا فقط على العناصر ذات القيم األكبر من عشرة ،أما لعرض املفاتيح بترتيب أبجدي ً فيجب علينا أوال إنشاء قائمة من مفاتيح القاموس باستخدام التابع keysثم ترتيبها ،ثم طباعة األزواج مفتاح-قيمة بالترتيب األبجدي: }counts = { 'chuck': 1 , 'annie': 42, 'jan': 100 ))(lst = list(counts.keys الفصل التاسع :القواميس 150 )print(lst )(lst.sort for key in lst: )]print(key, counts[key ويكون الخرج: ]'['jan', 'chuck', 'annie annie 42 chuck 1 jan 100 ً نرى أوال قائمة املفاتيح غير املرتبة التي حصلنا عليها باستخدام التابع keysثم نرى األزواج مفتاح- قيمة املرتبة. 4.9التعامل مع النصوص لقد جعلنا النص في املثال السابق بأبسط شكل بإزالة كل عالمات الترقيم منه ،إال أن النص األصلي يحتوي على العديد من عالمات الترقيم كما نالحظ: ?But, soft! what light through yonder window breaks It is the east, and Juliet is the sun. Arise, fair sun, and kill the envious moon, Who is already sick and pale with grief, وبما أن التابع splitيعامل الكلمات كرموز تفصل بينها فراغات فستعامل "! "softو" "softككلمتين مختلفتين وسيتم إنشاء مكان منفرد لكل منهما ضمن القاموس .و ً أيضا سنعامل " "whoو""Who ٍ ككلمتين مختلفتين باعتبار أن النص يحوي حروف كبيرة وصغيرة ،ولكن نستطيع حل املشكلتين باستخدام التوابع النصية lowerو punctuationو translateحيث أن األخيرة هي األفضل وتوصيفها كما يأتي: ))line.translate(str.maketrans(fromstr, tostr, deletestr والتي تعني :استبدل املحارف في fromstrباملحارف ذات املوقع نفسه في tostrواحذف جميع املحارف القواميس:الفصل التاسع 151 .deletestr سالسل نصية فارغة مع إهمالtostr وfromstr ويمكن أن يكون،deletestr في لحذف عالمات الترقيم كما سنطلب من بايثونdeletestr ولكن سنستخدم معاملtostr لن نعرف :أن تخبرنا بمجموعة املحارف التي تعتبرها كعالمات ترقيم وذلك كما يأتي >>> import string >>> string.punctuation '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~' ثم نطبق،python 2.0 كانت مختلفة فيtranslate ويجب اإلشارة إلى أن املعامالت املستخدمة مع :التعديالت اآلتية على برنامجنا import string fname = input('Enter the file name: ' ) try: fhand = open(fname) except: print( ' File cannot be opened: ' , fname) exit() counts = dict() for line in fhand: line = line.rstrip() line = line.translate(line.maketrans(' ', ' ', string.punctuation)) line = line.lower() words = line.split() for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 print(counts) # Code: http://www.py4e.com/code3/count2.py الفصل التاسع :القواميس 152 إن جزء من تعلم فن بايثون أو التفكير بطريقة بايثون هو إدراك أن بايثون تحتوي على قدرات (توابع جاهزة) لحل العديد من مشاكل تحليل البيانات ،وسترى مع مرور الزمن أمثلة كافية وستقرأ ما يكفي من التوصيفات التي تجعلك تجيد البحث وتستفيد من البرامج املكتوبة من قبل مبرمجين آخرين مما يسهم في تسهيل عملك. يكون الخرج املختصر للبرنامج السابق كما يأتي: Enter the file name: romeo-full.txt {'swearst': 1, 'all': 6, 'afeard': 1, 'leave': 2, 'these': 2, 'kinsmen': 2, 'what': 11, 'thinkst': 1, 'love': 24, 'cloak': 1, 'a': 24, 'orchard': 2, 'light': 5, 'lovers': 2, 'romeo': 40, 'maiden': 1, }'whiteupturned': 1, 'juliet': 32, 'gentleman': 1, 'it': 22, 'leans': 1, 'canst': 1, 'having': 1, ... ولكن البحث عما نريد ضمن هذا الخرج ما يزال غير عملي وبإمكاننا استخدام بايثون للحصول ما ً نريد بالضبط إال أننا سنحتاج للحديث عن الصفوف ) (tuplesأوال وسنعود بعدها إلى هذا املثال. 5.9التنقيح مع زيادة حجم البيانات يصبح من الصعب التنقيح عبر طباعة الخرج والتحقق من البيانات ً يدويا لذا َ هاك بعض املقترحات لحل هذا: .1تقليل حجم الدخل :إن أمكن ،فعلى سبيل املثال إذا كان البرنامج يقرأ ملف نص ي فابدأ بأول عشرة أسطر أو بأصغر مثال يمكنك إيجاده حيث تستطيع التعديل على امللفات ً مباشرة أو تعديل البرنامج ليقرأ أول عدد ما من السطور وهذا محبذ أكثر ،وفي حال وجود ً تدريجيا مع خطأ فيمكنك تقليل عدد األسطر إلى عدد أقل حتى يظهر الخطأ ثم قم بزيادته تصحيح األخطاء. ً .2تفقد موجزالبيانات و أنواعها :اطبع موجز عن البيانات بدال من طباعتها وتفقدها بأكملها .مثل عدد عناصر قاموس ما أو مجموع قيم قائمة من األرقام .و ً أيضا السبب األكثر ً شيوعا لألخطاء أثناء التشغيل ( )runtime errorsهو وجود قيمة معينة من نوع خاطئ، ً ويكفي عادة طباعة نوع هذه القيمة لتنقيح هذا النوع من األخطاء. .3اكتب حاالت اختبارً : ً تلقائيا ،كحالة حساب أحيانا يمكنك أن تكتب برنامج لتفقد األخطاء متوسط قيم قائمة ما ،حيث يمكن التحقق ما إذا كان الناتج أصغر من أعظم قيمة فيها أو الفصل التاسع :القواميس 153 أكبر من أصغر قيمة ويدعى هذا باالختبار املنطقي فهو يكشف األخطاء غير املنطقية على اإلطالق ،كما يوجد اختبار آخر يسمى باختبار االتساق أي يقارن بين ناتجي عمليتين حسابيتين للتأكد من توافقهما. .4اطبع الخرج :إن طباعة خرج عملية التنقيح يسهل كشف األخطاء. وللتذكير فإن الوقت الذي تقضيه في كتابة وبناء أساس البرنامج بشكل صحيح يقلل الوقت الذي تقضيه في التنقيح. 6.9فهرس املصطلحات • القاموس ( :)dictionaryيربط بين مجموعة من املفاتيح مع القيم املقابلة لها. • خوارزمية الهاش ( :)hashtableخوارزمية مستخدمة في القواميس ضمن بايثون. • تابع هاش ( :)hash functionتابع تستخدمه الخوارزمية hashtableلتحديد موقع مفتاح ما. • الهيستوغرام ( :)histogramلتمثيل التكرارات أو التعدادات. • عملية التنفيذ ) :(implementationطريقة تنفيذ عملية حسابية ما. • عنصر ) :(itemاسم آخر لزوج املفتاح-قيمة. • مفتاح ) :(keyكائن يظهر في القاموس كأول جزء من زوج املفتاح-قيمة. • زوج مفتاح-قيمة ) :(key-value pairتمثيل العالقة بين املفتاح والقيمة املوافقة في قاموس ما. • البحث في القاموس ) :(lookupعملية تنفذ في القواميس إليجاد القيمة املوافقة ملفتاح ما. • الحلقات املتداخلة ) :(nested loopsوهذا عند وجود حلقة أو أكثر ضمن حلقة أخرى حيث تنهي الحلقة الداخلية تنفيذ جميع دوراتها من أجل كل دورة للحلقة الخارجية. • قيمة ) :(valueغرض في القاموس يمثل الجزء الثاني من الزوج مفتاح-قيمة وهي تختلف هنا عن االستعماالت السابقة لكلمة .value الفصل التاسع :القواميس 154 7.9تمارين: ً برنامجا يصنف رسائل البريد االلكتروني بحسب يوم إرسالها .ولتنفيذ • التمرين الثاني :اكتب هذا ،ابحث عن األسطر التي تبدأ بكلمة Fromثم ابحث عن الكلمة الثالثة وأنش ئ عداد تكرار أليام اإلرسال ثم اطبع محتوى قاموسك (الترتيب غير مهم). مثال: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 مثال عن الخرج: python dow.py Enter a file name: mbox-short.txt }{'Fri': 20, 'Thu': 6, 'Sat': 1 ً برنامجا لقراءة سجل بريد إلكتروني معين وأنش ئ هيستوغرام • التمرين الثالث :اكتب باستخدام القواميس لتبيان عدد الرسائل الواصلة له من كل إيميل ثم اطبع عناصر القاموس. Enter file name: mbox-short.txt {'gopal.ramasammycook@gmail.com': 1, 'louis@media.berkeley.edu': 3, 'cwen@iupui.edu': 5, 'antranig@caret.cam.ac.uk': 1, 'rjlowe@iupui.edu': 2, 'gsilver@umich.edu': 3, 'david.horwitz@uct.ac.za': 4, 'wagnermr@iupui.edu': 1, }'zqian@umich.edu': 4, 'stephen.marquard@uct.ac.za': 2, 'ray@media.berkeley.edu': 1 • التمرين الرابع :أضف بعض التعليمات لبرنامجك السابق إليجاد الشخص الذي أرسل أكبر عدد من الرسائل اإللكترونية ،أي ابحث في القاموس عن القيمة العظمى باستخدام الحلقات بعد قراءة البيانات وإنشاء القاموس (راجع الفصل الخامس :حلقات القيم العظمى والصغرى) ،ثم اطبع عنوان البريد املطلوب مع عدد الرسائل التي أرسلت منه. Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt الفصل التاسع :القواميس 155 zqian@umich.edu 195 ً ً برنامجا يسجل اسم النطاق ( )domainفقط بدال من العنوان • التمرين الخامس :اكتب الكامل للبريد اإللكتروني .أي ،من أين أرسلت الرسالة ،ال من أرسلها ،مع عدد مرات تكرارها ثم اطبع عناصر القاموس. python schoolcount.py Enter a file name: mbox-short.txt {'media.berkeley.edu': 4, 'uct.ac.za': 6, 'umich.edu': 7, 'gmail.com': 1, 'caret.cam.ac.uk': 1, 'iupui.edu': 8 الفصل العاشر الصفوف الفصل العاشر :الصفوف 157 10الصفوف 1.10الصفوف غيرقابلة للتعديل الصفوف عبارة عن سالسل من القيم ،وكما هو الحال مع القوائم ،يمكن أن نخزن في الصفوف قيم من كافة األنواع ،كما أن هذه القيم تفهرس باستخدام األعداد الصحيحة ،ويكمن االختالف املهم الذي تمتاز به الصفوف في كونها غير قابلة للتعديل .كما أن الصفوف قابلة للمقارنة ،ويمكن تطبيق خوارزمية الهاش ( )Hashعليها ،مما يسمح بترتيب قائمة من الصفوف أو استخدام الصفوف كمفاتيح في قواميس بايثون. عند كتابة صف نجد أنه عبارة عن قائمة تتكون من سلسلة قيم يتخللها فواصل: '>>> t = 'a', 'b', 'c', 'd', 'e وعلى الرغم من عدم الحاجة لوضع الصف بين قوسين يشيع ذلك لتسهيل عملية تمييز الصفوف في البرنامج: )'>>> t = ('a', 'b', 'c', 'd', 'e وعند إنشاء صف مكون من عنصر واحد يجب أن تضيف فاصلة إلى نهاية هذا الصف: ) >>> t1 = ('a' , )>>> type(t1 >'<type 'tuple وفي حال عدم إضافة هذه الفاصلة سيعامل الصف على أنه سلسلة نصية: )'>>> t2 = ('a )>>> type(t2 >'<type 'str ويمكن إنشاء صف باستخدام التابع الجاهز ،tupleوبدون استخدام أي وسائط سنحصل على صف فارغ: )(>>> t = tuple )>>> print(t الفصل العاشر :الصفوف 158 )( وفي حال كون الوسيط املستخدم مع التابع سلسلة من نوع ما (سلسلة نصية أو قائمة أو صف) فإن النتيجة ستكون ً صفا من عناصر هذه السلسلة: )'>>> t = tuple('lupins )>>> print(t )'('l', 'u', 'p', 'i', 'n', 's ً محجوزا كتابع جاهز إلنشاء ينبغي تجنب استخدام كلمة tupleكاسم للمتغيرات ،وذلك باعتباره الصفوف. تعمل غالبية عوامل القوائم على الصفوف .على سبيل املثال ،فإن عامل القوس القائم يستدعي العناصر في الصف كما هو الحال مع القوائم: )'>>> t = ('a', 'b', 'c', 'd', 'e )]>>> print(t[0 ''a ً نطاقا من العناصر ً أيضا: و يحدد عامل التجزئة )]>>> print(t[1:3 )'('b', 'c ولكن إذا حاولت أن تعدل قيمة أحد العناصر في الصف فستحصل على رسالة خطأ: '>>> t[0] = 'A TypeError: object doesn't support item assignment ً ً عنصرا بآخر: عوضا عن ذلك يمكن أن تغير ]>>> t = ('A',) + t[1: )>>> print(t )'('A', 'b', 'c', 'd', 'e الفصل العاشر :الصفوف 159 2.10مقارنة الصفوف يعمل عامل املقارنة مع الصفوف وغيرها من السالسل ،حيث تبدأ املقارنة بالعنصر األول من كل سلسلة ،وفي حال تكافأ الطرفان فتنتقل املقارنة إلى العنصر التالي ،وهكذا حتى العثور على عنصرين مختلفين .العناصر التي تتلو نقطة االختالف ال تؤخذ بعين االعتبار (حتى لو كانت كبيرة ً جدا): )>>> (0, 1, 2) < (0, 3, 4 True )>>> (0, 1, 2000000) < (0, 3, 4 True يعمل التابع sortبنفس الطريقة السابقة ،فيبدأ بالعنصر األول وفي حال التكافؤ ٌيرتب وفق العنصر الثاني وهكذا. ٌ ً اختصارا )DSU تستخدم هذه امليزة ضمن نمط العمليات املسمى ( Decorate, Sort, Undecorateأو الذي يتألف من الخطوات الثالثة السابقة الذكر: َ -1ميز ( )Decorateقيم سلسلة ما بإنشاء قائمة من الصفوف تحوي عنصر ترتيب واحد عالمة التمييز -أو أكثر يليه عنصر من السلسلة. -2رتب ( )Sortالصفوف باستخدام التابع .sort -3إ الة التمييز ) (Undecorateوذلك باستخراج عناصر السلسلة التي ٌرتبت ً سابقا. ز ً فلنفترض مثال حاجتنا لترتيب قائمة من الكلمات من الكلمة األطول إلى األقصر ،فنكتب البرنامج التالي: 'txt = 'but soft what light in yonder window breaks )(words = txt.split )(t = list for word in words: ))t.append((len(word), word )t.sort(reverse=True الفصل العاشر :الصفوف 160 )(res = list for length, word in t: )res.append(word )print(res # Code: http://www.py4e.com/code3/soft.py مسبوقة بعدد أحرفها. تنش ئ الحلقة األولى قائمة من الصفوف ،بحيث يتكون كل صف من كلمة ٍ يقارن تابع الترتيب sortالعنصر األول -طول الكلمة -وال يأخذ العنصر الثاني بعين االعتبار إال لحسم التكافؤات .نستخدم الوسيط ) (reverse=Trueلجعل التابع يرتب القيم تناز ًليا. تمر الحلقة الثانية على قائمة الصفوف وتنش ئ قائمة من الكلمات تناز ًليا حسب طولها والكلمتين املكونتين من أربعة أحرف تم ترتيبهما تناز ًليا حسب الحرف األول ،ولذلك تظهر الكلمة ” “whatقبل الكلمة ” “softفي القائمة املرتبة ،ويكون خرج البرنامج كالتالي: ]'['yonder', 'window', 'breaks', 'light', 'what', 'soft', 'but', 'in 3.10إسناد الصفوف تعتبر إمكانية استخدام تعليمة إسناد متغيرها عبارة عن صف من امليزات الفريدة في بايثون ،حيث أنها تسمح بإسناد قيم ألكثر من متغير ً معا ،عندما تكون القيم عبارة عن سلسلة. نرى في املثال التالي قائمة من عنصرين (سلسلة) نقوم بإسنادهما إلى املتغيرين xو yبتعليمة واحدة. ] '>>> m = [ 'have', 'fun >>> x, y = m >>> x ''have >>> y ''fun تعامل لغة بايثون تعليمة اإلسناد السابقة ً تقريبا كما يلي: ] '>>> m = [ 'have', 'fun الفصل العاشر :الصفوف 161 ]>>> x = m[0 ]>>> y = m[1 >>> x ''have >>> y ''fun ً ً حرفيا ،ففي حال استخدمنا قاموس بدال عن تجدر اإلشارة إلى أن لغة بايثون ال تترجم التعليمات القائمة في املثال السابق فلن يتم تنفيذ البرنامج -كما قد نتوقع.- ً عادة عندما نكتب تعليمة إسناد طرفها اليساري عبارة عن صف ،فإننا نهمل األقواس ،ولكن في حال لم نفعل فإن ذلك مقبول وصحيح: ] '>>> m = [ 'have', 'fun >>> (x, y) = m >>> x ''have >>> y ''fun ومن التطبيقات العملية لهذه امليزة هو القدرة على تبديل قيم متغيرين فيما بينهما: >>> a, b = b, a هنا كل من طرفي التعليمة عبارة عن صف ،القسم األيسر صف متغيرات ،بينما القسم األيمن صف ُ من التعابير .كل قيمة من الطرف األيمن تسند إلى املتغير املقابل لها من الطرف األيسر .يتم حساب كل التعابير في الطرف األيمن قبل أي اسناد. ً مساويا لعدد القيم في الطرف األيمن ،وفي حال عدم يجب أن يكون عدد املتغيرات في الطرف األيسر تساوي الطرفين نحصل على رسالة خطأ: >>> a, b = 1, 2, 3 ValueError: too many values to unpack الفصل العاشر :الصفوف 162 ويمكننا تعميم ذلك حيث أن الطرف األيمن يمكن أن يكون أي نوع من السالسل (نص أو قائمة أو ً صف) .يمكننا مثال أن نقسم عنوان البريد اإللكتروني إلى قسمين ونسند كل قسم إلى متغير: '>>> addr = 'monty@python.org )'@'(>>> uname, domain = addr.split تعطينا تعليمة التقسيم ً split خرجا على شكل قائمة بعنصرين ،األول يسند إلى املتغيرuname والثاني إلى املتغير :domain )>>> print(uname monty )>>> print(domain python.org 4.10القواميس والصفوف ُيستخدم التابع itemsمع القواميس ،ويعيد قائمة من الصفوف ،كل صف عبارة عن زوج من مفتاح وقيمة:}>>> d = {'a':10, 'b':1, 'c':22 ))(>>> t = list(d.items )>>> print(t ])[('b', 1), ('a', 10), ('c', 22 وبطبيعة الحال فإن قيم القاموس غير مرتبة ،ولكن بما أننا حصلنا على قائمة من الصفوف وبما أن الصفوف يمكن مقارنتها فيمكن أن نرتب هذه القائمة .إن تحويل القاموس إلى قائمة من الصفوف هي طريقة تسمح لنا بالحصول على محتويات القاموس مرتبة بطريقة ما: }>>> d = {'a':10, 'b':1, 'c':22 ))(>>> t = list(d.items >>> t ])[('b', 1), ('a', 10), ('c', 22 )(>>> t.sort الفصل العاشر :الصفوف 163 >>> t ])[('a', 10), ('b', 1), ('c', 22 ً وينتج لدينا قائمة مرتبة ً أبجديا حسب قيمة املفتاح. ترتيبا 5.10اإلسناد املتعدد مع القواميس عند استخدام كل من التابع itemsوعملية اإلسناد للصفوف وحلقة ،forيمكن أن نحصل على شيفرة نموذجية تستخدم للمرور على القيم واملفاتيح لقاموس باستخدام حلقة واحدة: for key, val in list(d.items()): )print(val, key تحوي هذه الحلقة متغيري تكرار ،ألن التابع itemsتعيد قائمة من الصفوف ،واملتغيرين keyوval يشكالن تعليمة إسناد لصف يتكرر تنفيذ الحلقة عليه لكل زوج (مفتاح ،قيمة) في القاموس ،فينتقل املتغيران في كل تكرار للحلقة إلى القيمتين التاليتين في القاموس ،ويكون خرج الحلقة كالتالي: 10 a 22 c 1b في حال دمجنا األسلوبين السابقين يمكن أن نحصل على محتويات القاموس مرتبة وفق القيمة لألزواج (مفتاح ،قيمة). ً للقيام بهذه العملية يجب علينا أوال إنشاء قائمة مكونة من صفوف ،يتكون كل صف منها من زوج ً (قيمة ،مفتاح) -بدال من (مفتاح ،قيمة) ،-حيث يعطينا التابع itemsقائمة من الصفوف كل منها مكون من (مفتاح ،قيمة) موافقة له ،ولكننا نريد في هذا املثال أن نرتب القاموس حسب القيم وليس حسب املفاتيح. بمجرد حصولنا على قائمة مكونة من صفوف يحوي كل منها (قيمة ،مفتاح) ،يسهل علينا ترتيب هذه ً قاموسا بالترتيب املطلوب. القائمة ،ومن ثم ننش ئ منها }>>> d = {'a':10, 'b':1, 'c':22 )(>>> l = list الفصل العاشر :الصفوف 164 >>> for key, val in d.items() : ) )... l.append( (val, key ... >>> l ])'[(10, 'a'), (22, 'c'), (1, 'b )>>> l.sort(reverse=True >>> l ])'[(22, 'c'), (10, 'a'), (1, 'b >>> بترو ،بحيث تكون القيمة في بداية كل صف من نستطيع من خالل إنشاء قائمة الصفوف هذه ٍ صفوفها ،أن نرتب هذه القائمة ،ومن ثم يمكن أن ننش ئ منها القاموس املطلوب. 6.10الكلمات األكثرتكر ًارا بالعودة إلى التمرين السابق ،الذي طبقناه على نص املشهد الثاني من الفصل الثاني من مسرحية ً برنامجا يستخدم الطريقة التالية ،للحصول الكلمات العشر األكثر روميو وجولييت ،يمكن أن نكتب تكر ًارا في النص: import string )'fhand = open('romeo-full.txt )(counts = dict for line in fhand: ))line = line.translate(str.maketrans(' ', ' ', string.punctuation )(line = line.lower )(words = line.split for word in words: if word not in counts: counts[word] = 1 else: counts[word] += 1 # Sort the dictionary by value الفصل العاشر :الصفوف 165 )(lst = list for key, val in list(counts.items()): ))lst.append((val, key )lst.sort(reverse=True for key, val in lst[:10]: )print(key, val # Code: http://www.py4e.com/code3/count3.py بقي القسم األول من البرنامج على حاله (القسم الذي يقرأ امللف النص ي وينش ئ القاموس الذي يحص ي عدد الكلمات املوجودة فيه) ،ولكن ً عوضا عن طباعة أعداد الكلمات وإنهاء البرنامج ببساطة، فسننش ئ قائمة من الصفوف لألزواج (قيمة ،مفتاح) ثم سنرتب هذه القيم ً ترتيبا تناز ًليا. ً بما أن القيم مذكورة أوال في الصفوف ،سنستخدمها عند املقارنة ،وعند وجود أكثر من صف بنفس القيمة سيؤخذ العنصر الثاني (املفتاح) بعين االعتبار ،ولذلك فإن الصفوف التي تبدأ بقيم متماثلة ً أبجديا حسب املفتاح. سترتب في نهاية البرنامج سنكتب حلقة forتقوم بعملية إسناد متعدد مع تكرار ،لتقوم بطباعة الكلمات العشر األكثر تكر ًارا عن طريق اجتزاء القائمة األساسية باستخدام األمر ] ،lst [:10وستظهر الكلمات األكثر ً تكررا حسب التحليل الذي أجريناه: 61 i 42 and 40 romeo 34 to 34 the 32 thou 32 juliet 30 that 29 my 24 thee ً يوضح املثال السابق ً جليا لم ُتعد بايثون ً مناسبا كلغة برمجة مستخدمة الكتشاف املعلومات خيارا الفصل العاشر :الصفوف 166 حيث استطعنا اجراء تحليل لبيانات معقدة عبر كتابة برنامج بسيط من ً 19 سطرا. 7.10استخدام الصفوف كمفاتيح ضمن القواميس تتميز الصفوف بإمكانية تطبيق خوارزمية الـهاش ( )Hashعليها على عكس القوائم ،ولذلك فإنها الحل املثالي عند الرغبة في إنشاء قاموس بمفاتيح مركبة. سنتعامل مع املفاتيح املركبة في حال الرغبة في إنشاء دليل هاتف يستخدم االسم والكنية كمفتاح ورقم الهاتف كقيمة ،وإذا أردنا أن نكتب تعليمة إسناد إلنشاء قاموس ،فيمكننا أن نستخدم املتغيرين ) (first, lastكمفتاح واملتغير numberكقيمة ،كما في التالي: directory[last,first] = number يمثل التعبير املكتوب بين األقواس القائمة ً صفا ،كما يمكن أن نستخدم تعليمة إسناد لصف ضمن حلقة forلتبديل االسم بموضع الكنية والعكس في هذا القاموس: for last, first in directory: )]print (first, last, directory[last,first تمر هذه الحلقة على املفاتيح (والتي هي عبارة عن صفوف) في القاموس ،حيث أنها تسند عناصر كل صف إلى املتغيرين lastو firstثم تطبع االسم ورقم الهاتف املقابل له. 8.10السالسل :النصوص والقوائم والصفوف ركزنا في هذا الفصل على استخدام قوائم من الصفوف ،ولكن كل األمثلة التي طرحناها ً تقريبا قابلة ً وتجنبا لتكرار وتعداد للتطبيق على قوائم من القوائم ،وصفوف من الصفوف ،وصفوف من القوائم، ً كل التركيبات املمكنة ،فسنشير إليها بسالسل من السالسل تبسيطا. يمكن استخدام السالسل املختلفة (السالسل النصية والقوائم والصفوف) بشكل متبادل في غالب ً األحيان ،ولذلك يطرح السؤال التالي :كيف نختار أحد أنواع هذه السالسل بدال من البقية وملاذا؟ ً ً نالحظ بداية أن السالسل النصية أكثر السالسل محدودية ألن عناصرها يجب أن تكون محارفا ً فقط ،كما أنها غير قابلة للتعديل فإذا أردت أن تعدل املحارف املوجودة في نص ما (بدال عن انشاء نص جديد) ،فيفضل أن تستخدم قائمة من املحارف ً عوضا عن سلسلة نصية. تستخدم القوائم بشكل أكثر شيوعا من الصفوف ،ويعود ذلك بشكل أساس ي إلى كونها قابلة الفصل العاشر :الصفوف 167 للتعديل ،ولكن هناك بعض الحاالت التي قد يكون استخدام الصفوف أفضل فيها: ً ً صفا بدال -1من األبسط في بعض الحاالت كما هو الحال مع تعليمة ،returnأن ننش ئ ُ عن قائمة ،ولكن هذا غير مطلق ،فقد تفضل القائمة في بعض الحاالت. ً ً قابل للتعديل -2إذا رغبت أن تستخدم تسلسال كمفتاح في قاموس ،فستحتاج نوعا غير ٍ كالسالسل النصية أو الصفوف. -3في حال كنت تستخدم سلسلة ما كوسيط لتابع ما ،فإن استخدام الصفوف يقلل احتمالية السلوك غير املتوقع بسبب مشكلة التسمية البديلة ( .)aliasingلن تستطيع استخدام التوابع sortو reverseمع الصفوف كونها غير قابلة للتعديل ،وهذه التوابع تستخدم لتعديل القوائم املوجودة مسب ًقا ،لكن حال الرغبة بالحصول على نتائج هذه ً التوابع ،فإن لغة بايثون توفر ً توابعا جاهزة بديلة كالتابعين sortedو reversedالذين يأخذان أي سلسلة ُ كمدخل ،ويعيدان سلسلة جديدة بنفس العناصر ولكن بترتيب آخر. 9.10التنقيح ُيطلق اسم بنى البيانات ( )data structuresعلى كل من القوائم والقواميس والصفوف بشكل عام، ً ً وقوائما وقد تناولنا بعض البنى املركبة كقوائم من الصفوف ،والقواميس التي تحوي صفوفا كمفاتيح كقيم .تعد هذه البنى مفيدة في االستخدام ،ولكنها عرضة ملا يسمى بأخطاء الشكل )،(shape errors وهي األخطاء التي تحدث عندما تكون بنية البيانات املستخدمة ذات نوع أو حجم أو كالهما غير مناسب؛ أو حتى من املمكن أن تحدث هذه األخطاء عند كتابة شيفرة ما ونسيانك لنوع البيانات التي استخدمتها .وكمثال عن ذلك ،ففي حال كان لدينا برنامج يتوقع أن تكون البيانات املدخلة له عبارة عن قائمة مكونة من رقم وحيد ،وقمنا بتزويده برقم (غير محتوى ضمن قائمة) فسنحصل على هذا النوع من األخطاء. 10.10فهرس املصطلحات • قابل للمقارنة ) :(comparableنوع بيانات يمكن أن يحوي على مجموعة قيم نستطيع أن نفحص فيما إذا كانت أكبر أو أصغر أو تساوي قيم أخرى ضمن نفس النوع ،يمكن أن توضع األنواع القابلة للمقارنة في قائمة ثم يتم ترتيبها بشكل ما. الفصل العاشر :الصفوف 168 • بنى البيانات ( :)data structureوهي مجموعة من القيم التي يتم ترتيبها عادة في قوائم أو قواميس أو صفوف أو غيرها. ً اختصارا للتعبير(:)Decorate, Sort, Undecorate • النمط ّميز ،رتبِّ ،أزل التمييز ()DSU وهو نمط يستخدم لتشكيل قوائم من صفوف ،ليتم ترتيبها واستخراج جزء من النتيجة التي نحصل عليها. • التجميع ( :)gatherوهي العملية التي يتم فيها تجميع وسيط مكون من صف ذو طول متغير. • خاضع لخوارزمية الهاش ( :)hashableأي نوع بيانات يمكن تنفيذ تابع الهاش ()hash عليه ،األنواع غير القابلة للتعديل مثل ) (float, integers, stringتقبل هذا التابع ،أما البنى القابلة للتعديل ال تقبله. • التفريق ( :)scatterوهي العملية التي يتم فيها التعامل مع سلسلة من البيانات على أنها قائمة من الوسائط. • شكل بنية البيانات ( :)shapeملخص يصف نوع وحجم وتركيب بنية معطيات ما. ً ً • ذو العنصر الوحيد ) :(singletonقائمة (أو سلسلة من نوع آخر) تحوي واحدا عنصرا فقط. • الصف ( :)tupleسلسلة من العناصر غير القابلة للتعديل. • إسناد الصفوف ( :)tuple assignmentوهي تعليمة إسناد لسلسلة من القيم موجودة في ً طرفها األيمن ،وصف من املتغيرات في طرفها األيسر ،يتم حساب الطرف األيمن أوال ،ثم يتم إسناد العناصر املوجودة فيه إلى املتغيرات املوجودة في الطرف األيسر. 11.10تمارين ً برنامجا يقوم بقراءة وتجزئة السطور التي • التمرين األول :راجع تمريننا السابق ،واكتب تبدأ بكلمة ،Fromويستخرج العنوان من كل سطر ،ثم يقوم بحساب عدد الرسائل الواردة من كل شخص باستخدام القاموس. بعد قراءة كل البيانات اعرض اسم الشخص ذو عدد الرسائل األكبر ،عن طريق إنشاء قائمة الفصل العاشر :الصفوف 169 ً صفوفا (لعدد الرسائل ،وعنوان البريد) من القاموس الذي تم إنشاؤه ً سابقا ،ثم رتب تتضمن القيم من األكبر إلى األصغر ،واعرض عنوان البريد الذي ورد منه أكبر عدد من الرسائل. مثال: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 Enter a file name: mbox-short.txt cwen@iupui.edu 5 Enter a file name: mbox.txt zqian@umich.edu 195 • التمرين الثاني :يعد البرنامج الذي سنكتبه في هذا التمرين تكرار الساعات التي وصلت فيها رسائل البريد االلكتروني ،حيث سنستخرج ساعة ورود الرسالة من السطر املبدوء بالكلمة ،Fromعن طريق العثور على النص الذي يرمز ساعة الوصول ،ومن ثم تجزئته باستخدام عامل النقطتين ، :بمجرد القيام بعد جميع ساعات وصول الرسائل ،اعرض تكرار كل ساعة في سطر كالتالي: python timeofday.py Enter a file name: mbox-short.txt 04 3 06 1 07 1 09 2 10 3 11 6 14 1 15 2 16 4 الفصل العاشر :الصفوف 170 17 2 18 1 19 1 برنامجا يقرأ ً ً ملفا ً نصيا ليعرض عدد تكرار األحرف فيه بترتيب • التمرين الثالث :اكتب تنازلي .يجب أن يحول البرنامج كل األحرف إلى حالة الحرف الصغير ،وأن يعد األحرف من aإلى zفقط (أال يعد أي ش يء أخر عدا األحرف كاملسافات وعالمات الترقيم) ،بعد ذلك استخدم ملفات نصية من عدة لغات ُ كمدخل للبرنامج ،وقارن تباين األحرف األكثر تكر ًارا بين هذه اللغات وقارن النتائج التي توصلت إليها مع الجدول املوجود في الرابط التالي: https://wikipedia.org/wiki/Letter_frequencies الفصل الحادي عشر التعابير النمطية الفصل الحادي عشر :التعابير النمطية 172 11التعابيرالنمطية حتى اآلن كنا نقرأ امللفات ونبحث عن األنماط ونقوم باستخراج بيانات مهمة بالنسبة لنا من األسطر، حيث كنا نستخدم توابع السالسل النصية مثل splitو ،findونستخدم القوائم وتجزئة السالسل النصية الستخراج أجزاء من األسطر. جدا ،لذلك تتوفر في لغة بايثون مكتبة برمجية فعالة ً مهمة البحث واالستخراج هذه شائعة ً جدا تسمى مكتبة التعابير النمطية ( )regular expressionsوالتي تتعامل مع العديد من هذه املهام برتابة مطلقة ،وإن السبب في عدم طرح التعابير النمطية ً سابقا في الكتاب هو أنه بالرغم من أن هذه ً ً التعابير فعالة لكن بنفس الوقت معقدة قليال والقواعد الخاصة بها تتطلب ممارسة لالعتياد عليها. يمكن أن نقول عن التعابير النمطية أنها لغة برمجة خاصة بعمليات البحث والتحليل في السالسل النصية. ٌ لقد نشرت كتب كاملة عن التعابير النمطية لذلك سنغطي في هذا الفصل أساسيات التعابير النمطية فقط ،وللمزيد من التفاصيل حول التعابير النمطية راجع الرابطين التاليين: https://en.wikipedia.org/wiki/Regular_expression https://docs.python.org/library/re.html ُ يجب أن تستدعى مكتبة التعبير النمطي reضمن برنامجك قبل استخدامها ،وأبسط استخدام لها هو التابع )( searchوالبرنامج التالي يوضح أحد استخداماته: '# Search for lines that contain 'From import re )'hand = open ('mbox-short.txt for line in hand: )(line = line.rstrip )if re.search('From:', line )print(line # Code: http://www.py4e.com/code3/re01.py الفصل الحادي عشر :التعابير النمطية 173 نفتح امللف ،ثم نمر على كل السطور باستخدام حلقة forثم نستخدم التعبير النمطي )(search فقط لطباعة األسطر التي تحوي السلسلة النصية "."From هذا البرنامج ال يظهر الفعالية الحقيقية للتعابير النمطية حيث كان بإمكاننا الحصول على نفس النتائج بالسهولة ذاتها باستخدام التابع )( ،line.findوتظهر الفعالية الحقيقية للتعابير النمطية عندما يمكننا إضافة الرموز الخاصة بالتعابير النمطية للسلسلة النصية والتي تسمح لنا بالتحكم بدقة أكبر باألسطر التي تطابق سلسلة نصية ما. تسمح إضافة هذه الرموز الخاصة لتعبيرنا النمطي بالقيام بعمليات مطابقة واستخراج متقدمة باستخدام عدد قليل من السطور البرمجية ،فعلى سبيل املثال الرمز ^ يستخدم في التعبير النمطي ملطابقة بداية السطر بحيث بإمكاننا تغيير البرنامج السابق ملطابقة األسطر بحيث " "Fromفي بداية السطر فقط كما يلي: '# Search for lines that start with 'From import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip if re.search('^From:', line): )print(line # Code: http://www.py4e.com/code3/re02.py هكذا نكون حصلنا فقط على األسطر التي تبدأ ب " "From:وهذا مثال بسيط ً جدا كان باإلمكان تنفيذه باستخدام التابع )(. startswith لكنه يهدف لتوضيح حقيقة بأن التعابير النمطية تستخدم رموز خاصة ملنحنا املزيد من التحكم بعمليات املطابقة. 1.11مطابقة املحارف في التعابيرالنمطية ً استخداما هناك عدد من الرموز الخاصة التي تسمح لنا ببناء تعابير نمطية أكثر فعالية ومن أكثرها ً وشيوعا هي النقطة .والتي تمثل أي محرف. في املثال التالي التعبير النمطي F..m:سيطابق أي من السالسل النصية Fromأو Fxxmأو F12mأو الفصل الحادي عشر :التعابير النمطية 174 F!@mحيث النقط في التعبير النمطي تطابق أي محرف. # Search for lines that start with 'F', followed by '# 2 characters, followed by 'm: import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip if re.search('^F..m:', line): )print(line # Code: http://www.py4e.com/code3/re03.py تزداد أهمية هذه امليزة عندما يمكننا اإلشارة إلمكانية تكرار املحرف ً عددا من املرات باستخدام رمز النجمة * أو رمز الزائد +في تعبيرك النمطي حيث تدعى الرموز * و +بـ ( (wildcardتعني هذه املحارف ً الخاصة أنه بدال من مطابقة محرف واحد في السلسلة النصية فإنها تطابق في حال الرمز * صفر محرف أو أكثر من املحارف ،أما في حال الرمز +تطابق محرف واحد أو أكثر. يمكننا تضييق نطاق األسطر التي نطابقها باستخدام الرموز السابقة في املثال التالي: # Search for lines that start with From and have an at sign import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip if re.search('^From:.+@', line): )print(line # Code: http://www.py4e.com/code3/re04.py السلسلة النصية @ ^From:.+ستطابق األسطر التي تبدأ بـ From:متبوعة بمحرف أو أكثر .+ثم بإشارة @ لذلك هذا سوف يطابق السطر التالي: From: stephen.marquard@uct.ac.za الفصل الحادي عشر :التعابير النمطية 175 يمكننا بهذه الحالة أن نقول أن الرمز .+يطابق جميع املحارف بين النقطتين :وإشارة @ @From:.+ يمكن االعتبار أن الرمزين * و +رموز متعدية (أي أنها تطابق أكبر قدر ممكن من املحارف) ،فعلى سبيل املثال إن السلسلة النصية أدناه التي تتضمن عدة محارف @ لكن سيكمل الرمز .+املطابقة حتى محرف @ األخير. From: stephen.marquard@uct.ac.za, csev@umich.edu, and cwen @iupui.edu ً لكن من املمكن توظيف رمز * أو +بحيث ال يكون متعديا في املطابقة عبر إضافة رمز خاص في التعبير النمطي ،لذا راجع ملفات توثيق هذا املكتبة للحصول على معلومات عن إيقاف تشغيل السلوك الطماع لتلك الرموز. 2.11استخراج البيانات باستخدام التعابيرالنمطية إذا أردنا استخراج البيانات من سلسلة نصية في لغة بايثون فبإمكاننا استخدام التابع )(findall الستخراج السالسل النصية الجزئية ) )substringsالتي تطابق التعبير النمطي. على سبيل املثال الستخراج أي سلسلة نصية قد تبدو كبريد االلكتروني من كل من األسطر التالية: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 >Return-Path: <postmaster@collab.sakaiproject.org ;>for <source@collab.sakaiproject.org )Received: (from apache@localhost Author: stephen.marquard@uct.ac.za لن نرغب بكتابة شيفرة تتضمن تعليمات تجزئة وتقطيع مختلفة للتعامل مع كل سطر على حدة ،بل نستخدم تابع )( findallإليجاد األسطر التي تحوي عناوين البريد اإللكتروني واستخراج واحد أو أكثر من العناوين في كل األسطر. import re 's = 'A message from csev@umich.edu to cwen@iupui.edu about meeting @2PM )lst = re.findall('\S+@\S+', s )print(lst # Code: http://www.py4e.com/code3/re05.py الفصل الحادي عشر :التعابير النمطية 176 يبحث التابع )( findallفي الوسيط الثاني للتابع – من نوع سلسلة نصية -ويعيد قائمة بكل سلسلة نصية تبدو كالبريد االلكتروني أما الرمز \Sفيستخدم للتعبير عن عدم وجود مسافات فارغة. فيكون خرج البرنامج: ]'['csev@umich.edu', 'cwen@iupui.edu وتفسير هذا التعبير النمطي يكون بأننا نبحث عن سلسلة نصية جزئية تحوي على األقل محرف واحد ال يمثل مسافة فارغة متبوع بإشارة @ متبوعة على األقل برمز واحد ال يمثل مسافة فارغة حيث الرمز \S+يعني مطابقة أي عدد من املحارف باستثناء املسافة الفارغة. سيطابق التعبير النمطي مرتين مع ))csev@umich.edu , cwen@iupui.edu ولكن لن يطابق @2PMبسبب وجود مسافة فارغة قبل إشارة @ بإمكاننا استخدام التعبير النمطي السابق في البرنامج لقراءة كل األسطر في امللف وطباعة أي ش يء يشبه البريد اإللكتروني كما يلي: # Search for lines that have an at sign between characters import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip )x = re.findall('\S+@\S+', line if len(x) > 0: )print(x # Code: http://www.py4e.com/code3/re06.py إننا نقرأ كل سطر ثم نستخرج كل سلسلة نصية جزئية والتي تطابق تعبيرنا النمطي. بما أن التابع )( findallيعيد قائمة فيمكن ببساطة أن نتحقق إذا كان عدد العناصر في القائمة املعادة أكبر من صفر. إذا شغلنا البرنامج على امللف mbox.txtسنحصل على الخرج التالي: ]'['wagnermr@iupui.edu الفصل الحادي عشر :التعابير النمطية 177 ]'['cwen@iupui.edu ]'>['<postmaster@collab.sakaiproject.org ]'>['<200801032122.m03LMFo4005148@nakamura.uits.iupui.edu ]';>['<source@collab.sakaiproject.org ]';>['<source@collab.sakaiproject.org ]';>['<source@collab.sakaiproject.org ]')['apache@localhost ]';['source@collab.sakaiproject.org تحوي بعض عناوين البريد اإللكتروني رموز مثل > أو ; في بدايتها أو نهايتها ،ولنوضح أننا فقط مهتمين في الجزء الذي يبدأ أو ينتهي بحرف أو رقم ،لذلك نستخدم ميزات أخرى من ميزات التعبير النمطي، ُ فاألقواس القائمة ] [ تستخدم لتوضيح مجموعة من الرموز املتعددة املقبولة والتي نرغب باعتبارها ً فسابقا تعلمنا أن \Sتطابق أي محرف بخالف املسافات الفارغة .اآلن سنكون أكثر دقة في متطابقة املحارف التي سنطابقها. هنا هو تعبيرنا النمطي الجديد: ][a-zA-Z0-9]\S*@\S*[a-zA-Z ً تعقيدا وقد تدرك ملاذا التعابير النمطية هي لغة خاصة بذاتها. يصبح املوضوع أكثر إن تفسير هذا التعبير النمطي هو أننا نبحث عن سلسلة نصية جزئية تبدأ بحرف صغير أو حرف كبير أو رقم ] ،[a-zA-Z0-9ثم متبوع بصفر أو أي عدد من املحارف بخالف املسافة الفارغة * \Sثم بإشارة @ ،ثم بصفر أو عدد أكبر من املحارف خالف املسافة الفارغة * \Sمتبوع بحرف كبير أو صغير. الحظ أننا أبدلنا من +إلى * لنشير لصفر أو أكثر من املحارف خالف املسافة الفارغة حيث ] [a-zA-Z0-9هي واحدة من املحارف خالف املسافة الفارغة. تذكر أن رمزي * أو +تطبق للرمز مباشرة املوجود إلى يسارهما. عندما نستخدم هذا التعبير في برنامجنا ستكون بياناتنا أكثر رتابة: # Search for lines that have an at sign between characters # The characters must be a letter or number import re الفصل الحادي عشر :التعابير النمطية 178 )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip )x = re.findall('[a-zA-Z0-9]\S+@\S+[a-zA-Z]', line if len(x) > 0: )print(x # Code: http://www.py4e.com/code3/re07.py ... ]'['wagnermr@iupui.edu ]'['cwen@iupui.edu ]'['postmaster@collab.sakaiproject.org ]'['200801032122.m03LMFo4005148@nakamura.uits.iupui.edu ]'['source@collab.sakaiproject.org ]'['source@collab.sakaiproject.org ]'['source@collab.sakaiproject.org ]'['apache@localhost الحظ في األسطر source@collab.sakaiproject.orgإن تعبيرنا النمطي استبعد حرفين من نهاية السلسة النصية ;> ،وذلك ألنه عندما نضيف ] [a-zA-Zلنهاية التعبير النمطي فإننا نطلب أنه مهما كانت السلسلة النصية فإن عليها أن تنتهي بحرف لذلك عندما توجد < في نهاية ";˃ "sakaiproject.orgفستتوقف املطابقة عند أخر حرف. الحظ ً أيضا أن خرج البرنامج هو قائمة كل عنصر فيها هو من النوع سلسلة نصية. َ 3.11تنفيذ عمليتي البحث واالستخراج معا إذا أردنا الحصول على األرقام في األسطر التي تبدأ بسلسلة نصية " "X-مثل: X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 ال نريد فقط أي أعداد عشرية من أي سطر إنما نريد استخراج األرقام من األسطر ذات الصيغة أعاله الفصل الحادي عشر :التعابير النمطية 179 لنستخدم التعبير النمطي التالي الختيار األسطر: ^X-.*: [0-9.]+ أي أننا نريد األسطر التي تبدأ بـ X-متبوعة بصفر أو أكثر من املحارف * .ومتبوعة بنقطتين :ثم فراغ وبعد الفراغ نبحث عن محرف أو مجموعة من املحارف والتي ممكن أن تكون أرقام بين صفر حتى تسعة أو ذات فاصلة عشرية [0-9.]+ الحظ داخل األقواس املربعة إن النقطة تطابق فاصلة عشرية (ليست رمز النقطة الخاص بالتعابير النمطية). إن التعبير التالي دقيق ً جدا وسيطابق ً تماما األسطر املطلوبة: # Search for lines that start with 'X' followed by any non '# whitespace characters and ': # followed by a space and any number. # The number can include a decimal. import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip if re.search('^X\S*: [0-9.]+', line): )print(line # Code: http://www.py4e.com/code3/re10.py عندما نقوم بتشغيل البرنامج نرى البيانات تظهر بشكل واضح األسطر التي نبحث عنها فقط. X-DSPAM-Confidence: 0.8475 X-DSPAM-Probability: 0.0000 X-DSPAM-Confidence: 0.6178 X-DSPAM-Probability: 0.0000 لحل مشكلة استخراج األرقام بإمكاننا استخدام التابع splitأو نستطيع استخدام ميزة أخرى من ميزات التعابير النمطية بحيث نقوم بعمليتي البحث وتحليل السطور في نفس الوقت. إن إشارة القوسين () هي أحد رموز التعابير النمطية الخاصة لكنها ال تستخدم في عمليات املطابقة الفصل الحادي عشر :التعابير النمطية 180 بل مع التابع )( findallحيث تشير إلى أنه بالرغم من سعيك ملطابقة كل التعبير لكنك فقط مهتم باستخراج جزء محدد من السلسلة النصية الجزئية املطابقة. لذا قم بإجراء التغيير التالي لبرنامجنا: # Search for lines that start with 'X' followed by any # non whitespace characters and ':' followed by a space # and any number. The number can include a decimal. # Then print the number if it is greater than zero. import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip )x = re.findall('^X\S*: ([0-9.]+)', line if len(x) > 0: )print(x # Code: http://www.py4e.com/code3/re11.py ً بدال من استدعاء )( searchبإمكاننا إضافة قوسين حول جزء من التعبير النمطي الذي يمثل عدد عشري ،ليوضح أننا فقط نريد من التابع )( findallأن يعطينا العدد ذي الفاصلة العشرية من السلسة النصية املطابقة. يظهر خرج البرنامج كما يلي: ]'['0.8475 ]'['0.0000 ]'['0.6178 ]'['0.0000 ]'['0.6961 ]'['0.0000 بالرغم أن األرقام خزنت في قائمة ،علينا إجراء تحويل من النوع سلسلة نصية إلى نوع عدد ذي الفاصلة العشرية ،لكن يظهر املثال السابق فعالية التعابير النمطية لكل من عمليتي البحث واالستخراج. الفصل الحادي عشر :التعابير النمطية 181 كمثال آخر عن هذه التقنية إذا ألقينا نظرة على امللف ،نالحظ أنه يتضمن عدد من األسطر بالصيغة ٍ التالية: Details: http://source.sakaiproject.org/viewsvn/?view=rev&rev=39772 إذا أردنا استخراج كل أرقام املراجعة )( (revالعدد الصحيح في نهاية هذه األسطر) باستخدام نفس الطريقة أعاله فبإمكاننا كتابة البرنامج التالي: '=for lines that start with 'Details: rev # Search '# followed by numbers and '. # Then print the number if it is greater than zero import re )'hand = open('mbox-short.txt for line in hand: )(line = line.rstrip )x = re.findall('^Details:.*rev=([0-9.]+)', line if len(x) > 0: )print(x # Code: http://www.py4e.com/code3/re12.py لتفسير تعبيرنا النمطي فنحن نبحث عن أسطر والتي تبدأ بكلمة Details:متبوعة بأي عدد من املحارف * .متبوعة بـ = revوثم بواحد أو أكثر من األرقام .وألننا ال نريد إيجاد األسطر التي تطابق كل التعبير بل فقط نريد استخراج العدد الصحيح في نهاية السطر لذلك نحيط [0-9]+بقوسين. عندما نقوم بتشغيل البرنامج فنحصل على الخرج التالي: ]'['39772 ]'['39771 ]'['39770 ]'['39769 ... متعد أي سيحاول الحصول على أكبر سلسلة نصية ممكنة قبل تذكر أن في التعبير [0-9]+رمز ٍ + استخراج األرقام ،يفسر هذا السلوك ملاذا نحصل على خمس خانات لكل رقم. انتبه إلى أن مكتبة التعابير النمطية تتوسع في كال االتجاهين حتى تقابل محرف غير الرقم ،أي نحو الفصل الحادي عشر :التعابير النمطية 182 بداية ونهاية السطر. اآلن يمكننا استخدام التعابير النمطية لحل تمارين سابقة حيث كان محط اهتمامنا هو الوقت واليوم لكل رسالة بريدية: حيث نظرنا سابقا إلى األسطر بالصيغة: From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008 ً فسابقا فعلنا ذلك باستدعاء التابع splitمرتين: وأردنا استخراج الوقت لكل سطر، ً ً مجددا عبر عامل النقطتين أوال عبر تجزئة السطر إلى كلمات ثم ُسحبت الكلمة الخامسة ثم جزأناه :لسحب املحرفين املهتمين بهما ،ولقد نجح ذلك ولكن هذه الطريقة ليس عملية حيث تفترض أن األسطر ذات صيغة قياسية. إذا َ أردت إضافة عملية تحقق من األخطاء (أو كتلة تعليمات لبنية ،)try/exceptلضمان عدم إخفاق ً ً صحيحا فسيزداد حجم الشيفرة ً 15-10 سطرا تنسيقا برنامجك عندما تدخل له أسطر غير منسقة ً برمجيا مما يجعل البرنامج صعب الفهم. يمكن تبسيط ذلك باستخدام التعبير النمطي: ^From .* [0-9][0-9]: ً متبوعا بأي عدد تفسير هذا التعبير النمطي أننا نبحث عن األسطر التي تبدأ بالكلمة Fromثم فراغ ً ً ً متبوعا بنقطتين : متبوعا برقمين ][0-9] [0-9 متبوعا بفراغ من املحارف *. هذا التعبير مناسب لألسطر التي نبحث عنها. الستخراج الساعة فقط باستخدام )( findallنضيف قوسين حول الرقمين كما يلي: ^From .* ([0-9][0-9]): فيكون البرنامج كالتالي: # Search for lines that start with From and a character '# followed by a two digit number between 00 and 99 followed by ': # Then print the number if it is greater than zero import re )'hand = open('mbox-short.txt الفصل الحادي عشر :التعابير النمطية 183 for line in hand: )(line = line.rstrip )x = re.findall('^From .* ([0-9][0-9]):', line )print(x if len(x) > 0: # Code: http://www.py4e.com/code3/re13.py وستعطي الخرج التالي عندما يتم تشغيل البرنامج: ]'['09 ]'['18 ]'['16 ]'['15 ... 4.11محرف الهروب عند استخدامنا لرموز التعابير النمطية ملطابقة بداية أو نهاية السطر أو الرموز الخاصة كـ * و + فإننا نحتاج طريقة لتفريقها عن املحارف العادية والتي قد نريد مطابقتها كإشارة $أو ^ نضع رمز \ (الشرطة املائلة للخلف) لتبيان أننا نبحث عن مطابقة هذا املحرف وليس ً رمزا من رموز التعابير النمطية .فعلى سبيل املثال بإمكاننا إيجاد قيم مالية في نص باستخدام التعبير النمطي التالي: import re 'x = 'We just received $10.00 for cookies. )y = re.findall('\$[0-9.]+',x عندما نضع الشرطة املائلة للخلف قبل عالمة الدوالر $فإنها تبحث ً حقا عن إشارة $في السلسلة ً النصية بدال من مطابقتها في "نهاية السطر" ،ويطابق بقية التعبير النمطي رقم أو مجموعة أرقام. الحظ أنه داخل األقواس القائمة ،املحارف ليست خاصة بالتعبير النمطي ،لذلك عندما نقول ] [0-9.فهو يعني ً حقا أرقام أو ذات فاصلة عشرية ،أما خارج تلك األقواس تعد النقطة أحد رموز التعبير النمطي وتطابق أي محرف .أي أن النقطة داخل األقواس املربعة هي نقطة عادية تشير لألرقام ذات الفاصلة العشرية. الفصل الحادي عشر :التعابير النمطية 184 5.11ملخص ً هذا الفصل هو ملحة عن التعابير النمطية فقد تعلمنا قليال عن لغة التعابير النمطية .فهي طريقة للبحث في السالسل النصية تعتمد على رموز خاصة تمكنك من التعبير عما تريد البحث عنه بلغة التعابير النمطية وهذا ما يعرف باملطابقة وتمكنك من استخراج أجزاء محددة من تلك السالسل النصية املطابقة. إليك بعض الرموز الخاصة: • ^ تطابق بداية السطر • $تطابق نهاية السطر • .تطابق أي محرف تسمى ))wildcard • \sتطابق املسافات الفارغة -انتبه حرف sهنا حرف صغير.- • \Sتطابق أي محرف خالف املسافات الفارغة (أي عكس )\sتطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة صفر أو أكثر من املرات • ?* تطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة صفر أو أكثر من املرات (في الوضع غير املتعدي (أي غير الطماع)) • +تطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة مرة أو أكثر من املرات • ? +تطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة مرة أو أكثر من املرات (في الوضع غير املتعدي) • ؟ تطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة صفر أو مرة واحدة • ؟؟ تطبق على املحرف أو املحارف التي تسبقها بشكل مباشر وتشير ملطابقة صفر أو مرة واحدة (في الوضع غير املتعدي) • ] [aeiouتطابق حرف وحيد طاملا أن املحرف في مجموعة معينة في هذا املثال ستطابق الفصل الحادي عشر :التعابير النمطية 185 " "aأو " "eأو " "Iأو " "oأو " "uلكن لن تطابق أي محارف أخرى. • ] [a-z0-9بإمكانك تحديد نطاق املحارف باستخدام إشارة الناقص ، -وهذا املثال هو محرف وحيد يجب أن يكون حرف صغير أو رقم. • ] [^A-Za-zعندما أول رمز في مجموعة الرموز هو ^ فهو يعكس الحالة ،وهذا املثال يطابق محرف وحيد مطابق ألي ش يء إال حرف كبير أو صغير. ُ • () حين تضاف األقواس للتعابير النمطية ال تكون بغرض املطابقة ،بل الستخراج مجموعة فرعية معينة من السلسة النصية التي تمت مطابقتها. • \bتطابق سلسلة نصية فارغة ،لكن فقط في بداية أو نهاية الكلمة. • \Bتطابق سلسلة نصية فارغة ،لكن ليست في بداية أو نهاية الكلمة. • \dتطابق أي رقم من أرقام النظام العشري ،وهذا مماثل للتعبير ][0-9 • \Dتطابق أي محرف ليس رقم ،وهذا مماثل ][^0-9 6.11معلومات إضافية ملستخدمي نظامي Unixو Linux أضيف البحث عن امللفات باستخدام التعابير النمطية في نظام تشغيل Unixعام 1960وهو متاح في أغلب لغات البرمجة بشكل أو بآخر. في الواقع يوجد برنامج أوامر( )command-lineضمن Unixويسمى ( grepمحلل التعابير النمطية العام) والذي يعمل ً تقريبا مثل األمثلة التي استخدمنا فيها تابع )( searchفي هذا الفصل ،لذا إذا كان لديك نظام Macintoshأو Linuxفبإمكانك تجربة األوامر التالية في نافذة برنامج األوامر: $ grep '^From:' mbox-short.txt From: stephen.marquard@uct.ac.za From: louis@media.berkeley.edu From: zqian@umich.edu From: rjlowe@iupui.edu يطلب األمر السابق من برنامج grepأن يظهر لك األسطر التي تبدأ بالسلسلة النصية Fromفي امللف mbox-short.txt. الفصل الحادي عشر :التعابير النمطية 186 ً إذا جربت برنامج grepقليال وقرأت ملفات التوثيق الخاصة به سترى بعض االختالفات الدقيقة بين ً التعابير النمطية في لغة بايثون والتعابير النمطية في ،grepفمثال grepال يدعم رمز \Sفستحتاج إلى ً تعقيدا ] ^[ والذي يعني ببساطة مطابقة أي محرف عدا الفراغ. مجموعة رموز أكثر 7.11التنقيح تحوي لغة بايثون ملفات توثيق سهلة ومفيدة ً جدا في حال احتجت منشط سريع لتحفيز ذاكرتك السترجاع اسم تابع ما ،حيث يمكن عرض هذه امللفات في مفسر لغة بايثون في الوضع التفاعلي. يمكنك جلب نظام املساعدة التفاعلي باستخدام )(help )(>>> help help> modules إذا كنت تعلم أي وحدة ( )moduleتريد استخدامها يمكنك استخدام أمر )( dirإليجاد التوابع في الوحدة كما يلي: >>> import re )>>> dir(re [.. 'compile', 'copy_reg', 'error', 'escape', 'findall', 'finditer' , 'match', 'purge', 'search', 'split', 'sre_compile', ]''sre_parse' , 'sub', 'subn', 'sys', 'template بإمكانك أيضا الحصول على توثيق مختصر عن أحد التوابع باستخدام األمر help )>>> help (re.search Help on function search in module re: )search(pattern, string, flags=0 Scan through string looking for a match to the pattern, returning a match object, or None if no match was found. >>> إن ملفات التوثيق ليست شاملة لكنها مفيدة في حال احتجت ملعلومة بسرعة أو عندما ال يكون لديك وصول إلى متصفح ويب أو محرك بحث. الفصل الحادي عشر :التعابير النمطية 187 8.11فهرس املصطلحات • الشيفرة الهشة ( :)brittle codeهي الشيفرة التي تعمل عندما تكون بيانات الدخل في صيغة معينة قياسية لكنها ضعيفة ً جدا إذا كان هناك بعض التغيرات عن الصيغة القياسية ،ونسميها هشة ألنه من السهل كسرها. • املطابقة الطماعة ( :)greedy matchingالفكرة أن رموز +و * في التعبير النمطي تمتد ملطابقة أكبر عدد ممكن من محارف السلسلة النصية. • محلل التعابير النمطية العام ( :)grepأمر متاح في أنظمة Unixيبحث عبر امللفات النصية إليجاد أسطر تطابق التعابير النمطية ،وهو اختصار لجملة (Generalized )regular expression parser • التعبيرالنمطي ( :)regular expressionلغة للبحث في السالسل النصية ،حيث يحوي التعبير النمطي ً رموزا خاصة تظهر أن البحث فقط سيطابق بداية ونهاية أسطر باإلضافة العديد من امليزات املماثلة. • الرموز البديلة ( :)Wildcardرمز خاص يطابق أي محرف ،أحدها هو النقطة. 9.11تمارين • التمرين األول :اكتب برنامج بسيط ملحاكاة عملية أمر grepفي نظام ،Unixواطلب من املستخدم إدخال تعبير نمطي واحسب عدد األسطر التي تطابق التعبير النمطي. $ python grep.py Enter a regular expression: ^Author mbox.txt had 1798 lines that matched ^Author $ python grep.py Enter a regular expression: ^Xmbox.txt had 14368 lines that matched ^X- الفصل الحادي عشر :التعابير النمطية 188 $ python grep.py Enter a regular expression: java$ mbox.txt had 4175 lines that matched java$ • التمرين الثاني :اكتب برنامج ليبحث عن أسطر تحوي صيغة مشابهة ملا يلي: New Revision: 39772 استخرج العدد من كل سطر باستخدام تعبير نمطي والتابع )( findallواحسب متوسط األعداد واطبع املتوسط كعدد صحيح. Enter file:mbox.txt 38549 Enter file:mbox-short.txt 39756 الفصل الثاني عشر البرامج املرتبطة بالشبكات الفصل الثاني عشر :البرامج املرتبطة بالشبكات 190 12البرامج املرتبطة بالشبكات ركزنا في العديد من األمثلة الواردة في هذا الكتاب على قراءة امللفات والبحث عن بيانات ضمنها ،إال أن هناك العديد من مصادر املعلومات املختلفة كشبكة اإلنترنت. في هذا الفصل ،سنعمل عمل ُمتصفح اإلنترنت الذي يسترجع صفحات الويب باستخدام بروتوكول ُ نقل النص التشعبي ) ،(Hypertext Transfer Protocolبعد ذلك سنقرأ ونحلل بيانات تلك الصفحات. ّ التشعبي HTTP 1.12برتوكول نقل النص إن بروتوكول الشبكة الذي يحكم عمل شبكة الويب بسيط للغاية .كما تسهل املكتبة البرمجية الجاهزة في بايثون socketعملية إنشاء اتصاالت عبر الشبكة واسترجاع البيانات عبر مآخذ الشبكة ( )Socketsفي برنامج بايثون. ُ تشبه مآخذ الشبكة امللف إلى حد ما ،لكن يكمن االختالف في أنها تؤمن إمكانية اتصال ثنائي االتجاه بين برنامجين .حيث تستطيع القراءة والكتابة عبر مآخذ الشبكة ذاتها. ُ فإذا ُق َ مت بكتابة ش يء ما إلى مآخذ الشبكة ،فإنه ُي َ رسل إلى التطبيق في الجانب اآلخر .بينما إذا قمت بالقراءة منه فإن البيانات الواردة إليك ُمرسلة من قبل تطبيق آخر. يجب عليك االنتظار عند محاولة قراءة مآخذ الشبكة في حال لم يرسل البرنامج في الطرف اآلخر أي بيانات .إذا انتظرت البرامج في طرفي مآخذ الشبكة وصول بيانات بدون إرسال أي ش يء ،فال شك أنها ً ً ً محددا. ستنتظر طويال .لذلك من املهم أن تتبع البرامج التي تتواصل عبر اإلنترنت بروتوكوال ً أوال وماذا ُ البروتوكول ،هو مجموعة من القواعد ُتحدد ُّ سينفذان، أي طرف سيبدأ في االتصال ثم ما هي الردود لتلك الرسالة ،ومن ُ سيرسل ً تاليا ،وهكذا. بمعنى أن التطبيقين على طرفي مآخذ الشبكة يتبعان خطوات متوافقة بدون أي تعارض. تتوفر العديد من املستندات التي تشرح برتوكوالت الشبكة .تجد بروتوكول نقل النص التشعبي ُ HTTPموض ًحا في املستند التاليhttps://www.w3.org/Protocols/rfc2616/rfc2616.txt : ُ هذا املستند طويل ومعقد من 176صفحة مليء بالكثير من التفاصيل. الفصل الثاني عشر :البرامج املرتبطة بالشبكات 191 َ وجدت أنه مهم فال تتردد بقراءته بالكامل ،لكن إذا أردت العثور على القواعد حول طلبات GET إذا فعليك االطالع على الصفحة رقم 36من املستند املوافق للرقم .RFC2616 ً لطلب ُمستند من مخدم ويب ُ سنجري اتصاال مع مخدم املوقع www.pr4e.orgعلى املنفذ )(port رقم 80ثم نرسل ً أمرا كالتالي: GET http://data.pr4e.org/romeo.txt HTTP/1.0 بحيث يكون املعامل الثاني هو صفحة الويب التي طلبناها ،ثم نقوم ً أيضا بإرسال سطر فارغ. ً متبوعا بمحتوى سيستجيب خادم الويب بإرسال بعض املعلومات الرئيسية عن املستند وسطر فارغ املستند. ّ ُ 2.12متصفح الويب األبسط في العالم ربما الطريقة األسهل إليضاح آلية عمل بروتوكول HTTPهي بكتابة برنامج بايثون بسيط يقوم باالتصال بخادم الويب وفق قواعد بروتوكول HTTPلطلب املستند ثم عرض الرد الذي ُيرسله املخدم. import socket )mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM ))mysock.connect(('data.pr4e.org', 80 )(cmd = 'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode )mysock.send(cmd while True: )data = mysock.recv(512 if len(data) < 1: break )' '=print(data.decode(),end )(mysock.close # Code: http://www.py4e.com/code3/socket1.py الفصل الثاني عشر :البرامج املرتبطة بالشبكات 192 يقوم البرنامج في البداية باالتصال مع املنفذ 80على الخادم www.py4e.com ُ بما أن برنامجنا يؤدي دور ُمتصفح اإلنترنت فإن بروتوكول نقل النص التشعبي يفرض علينا أن نرسل ً متبوعا بسطر فارغ. أمر GET َ ُ ُ الرموز \r\nتشير إلى ) EOL (End Of Lineأي "نهاية السطر" .لذا فإن الرموز \r\n\r\nتشير إلى عدم وجود ش يء بين تتابعي نهاية سطرين .وهذا ُيكافئ السطر الفارغ. بمجرد إرسال السطر الفارغ نقوم بإنشاء حلقة تستقبل البيانات على شكل أجزاء بحجم 512محرف للجزء الواحد من مآخذ الشبكة ،ونستمر بطباعة البيانات حتى ال يبقى أي بيانات للقراءة ،أي حتى ُيعيد التابع )( recvسلسلة نصية فارغة. الشكل : 13نموذج اتصال عبر مآخذ الشبكة ُينتج البرنامج الخرج التالي: HTTP/1.1 200 OK Date: Wed, 11 Apr 2018 18:52:55 GMT )Server: Apache/2.4.7 (Ubuntu Last-Modified: Sat, 13 May 2017 11:22:22 GMT "ETag: "a7-54f6609245537 Accept-Ranges: bytes Content-Length: 167 Cache-Control: max-age=0, no-cache, no-store, must-revalidate Pragma: no-cache Expires: Wed, 11 Jan 1984 05:00:00 GMT الفصل الثاني عشر :البرامج املرتبطة بالشبكات 193 Connection: close Content-Type: text/plain But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief ُ يظهر في بداية الخرج الترويسة ( )headerالتي أرسلها الخادم لوصف املستند. على سبيل املثال ،تشير عبارة Content_Typeإلى أن املستند هو مستند نص ي عادي (.)text/plain ُيضيف الخادم بعد أن ُيرسل لنا الترويسة سطر فارغ لإلشارة إلى نهايتها ،ثم بعد ذلك ُيرسل البيانات الفعلية وهي امللف النص ي .romeo.txt ُيوضح هذا املثال كيفية إجراء اتصال شبكي منخفض املستوى بواسطة مآخذ الشبكة .حيث يمكن أن تستخدم مآخذ الشبكة لالتصال بخادم الويب أو خادم البريد أو أي خوادم أخرى .فكل ما هو مطلوب هو العثور على املستند الذي يشرح مبدأ عمل البروتوكول ومن ثم كتابة الشيفرة البرمجية إلرسال واستقبال البيانات ً وفقا له. على أي حال ،بما أن البروتوكول الشائع استخدامه هو بروتوكول الويب HTTPفإن لغة بايثون تحتوي مكتبة ُ ً ً وخصيصا عمليات استرجاع املستندات والبيانات عبر خصيصا لتدعمه صممت الويب. أحد ُمتطلبات استخدام بروتوكول HTTPهو إرسال واستقبال البيانات على أنها سلسلة من البايتات ً ( )Bytes Objectsبدال من اعتبارها سالسل نصية ،ففي املثال السابق ،يحول التابعان )(َ encodeو )( decodeالسالسل النصية إلى سلسلة من البايتات وبالعكس. يستخدم املثال التالي الرمز ' ' bلتخزين املتغير كسلسلة بايتات .إن كل من ' 'َ bو )(ُ encodeمتكافئان. '>>> b'Hello world 'b'Hello world )(>>> 'Hello world'.encode 'b'Hello world الفصل الثاني عشر :البرامج املرتبطة بالشبكات 194 3.12استعادة صورة عن طريق بروتوكول HTTP في املثال أعاله ،استعدنا ملف نص ي ،وعرضنا ببساطة البيانات إلى الشاشة عند تنفيذ البرنامج. ً يمكننا استخدام برنامج مشابه الستعادة صورة عن طريق ،HTTPفبدال من عرض البيانات على الشاشة عند تنفيذ البرنامج ،نقوم بتجميع البيانات في سلسلة وبعدها نحذف الترويسة ثم نحفظ بيانات الصورة في ملف كما هو موضح: import socket import time 'HOST = 'data.pr4e.org PORT = 80 )mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM ))mysock.connect((HOST, PORT )'mysock.sendall(b'GET http://data.pr4e.org/cover3.jpg HTTP/1.0\r\n\r\n count = 0 " "picture = b while True: )data = mysock.recv(5120 if len(data) < 1: break )#time.sleep(0.25 )count = count + len(data )print(len(data), count picture = picture + data )(mysock.close 195 البرامج املرتبطة بالشبكات:الفصل الثاني عشر # Look for the end of the header (2 CRLF) pos = picture.find(b"\r\n\r\n") print('Header length', pos) print(picture[:pos].decode()) # Skip past the header and save the picture data picture = picture[pos+4:] fhand = open("stuff.jpg", "wb") fhand.write(picture) fhand.close() # Code: http://www.py4e.com/code3/urljpeg.py :عند تشغيل البرنامج فإنه ُيولد الخرج التالي $ python urljpeg.py 5120 5120 5120 10240 4240 14480 5120 19600 ... 5120 214000 3200 217200 5120 222320 5120 227440 3167 230607 الفصل الثاني عشر :البرامج املرتبطة بالشبكات 196 Header length 393 HTTP/1.1 200 OK Date: Wed, 11 Apr 2018 18:54:09 GMT )Server: Apache/2.4.7 (Ubuntu Last-Modified: Mon, 15 May 2017 12:27:40 GMT "ETag: "38342-54f8f2e5b6277 Accept-Ranges: bytes Content-Length: 230210 Vary: Accept-Encoding Cache-Control: max-age=0, no-cache, no-store, must-revalidate Pragma: no-cache Expires: Wed, 11 Jan 1984 05:00:00 GMT Connection: close Content-Type: image/jpeg تستطيع أن ُتالحظ أنه من أجل الرابط املستخدم يشير Content_Typeفي الترويسة إلى أن محتوى املستند هو عبارة عن صورة ) .(image/jpegبمجرد أن يتم تنفيذ البرنامج ،بإمكانك استعراض بيانات الصورة عبر فتح امللف stuff.jpgفي برنامج عرض الصور. ستالحظ عند تنفيذ البرنامج أننا ال نستقبل 5120م َ حرف في كل مرة نستدعي التابع )( ،recvفحين نستدعي )( recvنحصل على املحارف التي تم نقلها إلينا عبر الشبكة عن طريق خادم الويب .ففي هذا املثال ،حصلنا على دفعات من البيانات تتراوح بين 3200حتى 5120محرف. اعتمادا على سرعة الشبكة .ضع بالحسبان ً ً أيضا أنه عند االستدعاء األخير قد تكون نتائجك مختلفة لـ )( recvنحصل على 3167بايت وهي أخر جزء من البيانات .وفي االستدعاء التالي لـ )( recvنحصل على سلسلة بطول صفري ( )Zero-length stringوالتي تشير إلى أن الخادم استدعى التابع )(close عند طرف مآخذ الشبكة ،وأنه ال يوجد املزيد من البيانات القادمة. بإمكاننا إبطاء عملية االستدعاء املتتالية لـ )( recvعن طريق إلغاء تعليق استدعاء التابع )( .time.sleepحيث ننتظر بهذه الطريقة ربع ثانية بعد كل استدعاء (نضيف ً تأخيرا بمقدار ربع ثانية) البرامج املرتبطة بالشبكات:الفصل الثاني عشر 197 . مرة أخرىrecv() بحيث يمكن للخادم مجاراتنا وإرسال املزيد من البيانات لنا قبل أن نستدعي :مع هذا التأخير يتم تنفيذ البرنامج على النحو التالي $ python urljpeg.py 5120 5120 5120 10240 5120 15360 ... 5120 225280 5120 230400 207 230607 Header length 393 HTTP/1.1 200 OK Date: Wed, 11 Apr 2018 21:42:08 GMT Server: Apache/2.4.7 (Ubuntu) Last-Modified: Mon, 15 May 2017 12:27:40 GMT ETag: "38342-54f8f2e5b6277" Accept-Ranges: bytes Content-Length: 230210 Vary: Accept-Encoding Cache-Control: max-age=0, no-cache, no-store, must-revalidate Pragma: no-cache Expires: Wed, 11 Jan 1984 05:00:00 GMT Connection: close Content-Type: image/jpeg َ م5120 نحصل علىrecv() وبغض النظر عن االستدعاء األول واألخير لـ،اآلن حرف في كل مرة نطلب .بيانات جديدة الفصل الثاني عشر :البرامج املرتبطة بالشبكات 198 ُهناك ذاكرة مؤقتة ( )Bufferبين الخادم الذي ُينش ئ طلبات التابع )( sendوالتطبيق الخاص بنا الذي ُينش ئ طلبات )(.recv في مرحلة ما ،وعند تشغيل البرنامج مع التأخير ،قد يتسبب الخادم في ملء الذاكرة املؤقتة في مآخذ الشبكة ويجبره على التوقف حتى يبدأ برنامجنا بإفراغها. إن عملية إيقاف كل من تطبيق اإلرسال أو االستقبال ُيدعى التحكم في التدفق (.)flow control 4.12استعادة صفحات الويب باستخدام مكتبة urllib أرسلنا واستقبلنا ً سابقا البيانات عن طريق ُ HTTPمستخدمين مكتبة ،socketلكن هنالك طريقة أسهل لتنفيذ هذه املهمة مستخدمين مكتبة .urllib ُ تستطيع باستخدامك ملكتبة urllibالتعامل مع صفحة الويب كما لو أنها ملف ،فتشير ببساطة إلى ُ صفحة الويب التي تريد استعادتها لتقوم املكتبة بالتعامل مع تفاصيل بروتوكول HTTPوتفاصيل الترويسة. ُ إن الشيفرة املكافئة لقراءة ملف romeo.txtمن الويب باستخدام مكتبة urllibهي كالتالي: import urllib.request )'fhand = urllib.request.urlopen('http://data.pr4e.org/romeo.txt for line in fhand: ))(print(line.decode().strip # Code: http://www.py4e.com/code3/urllib1.py ُ ُبمجرد أن تفتح صفحة الويب باستخدام تعليمة ُ ،urllib.urlopenيصبح بإمكاننا التعامل معها مثل امللف وقراءتها باستخدام حلقة .for عند تشغيل البرنامج ،نرى محتويات امللف فقط في الخرج ،بالرغم أن الترويسة أرسلت بالفعل لكن شيفرة urllibتتجاهلها وتعيد فقط محتوى امللف. الفصل الثاني عشر :البرامج املرتبطة بالشبكات 199 But soft what light through yonder window breaks It is the east and Juliet is the sun Arise fair sun and kill the envious moon Who is already sick and pale with grief على سبيل املثال ،يمكننا كتابة برنامج السترداد البيانات الخاصة بـ romeo.txtوحساب تكرار كل كلمة في امللف على النحو التالي: import urllib.request, urllib.parse, urllib.error )'fhand = urllib.request.urlopen('http://data.pr4e.org/romeo.txt )(counts = dict for line in fhand: )(words = line.decode().split for word in words: counts[word] = counts.get(word, 0) + 1 )print(counts # Code: http://www.py4e.com/code3/urlwords.py من جديد ،بمجرد أن نفتح صفحة الويب بإمكاننا قراءتها كملف محلي (متوفر على جهازك). ُ ّ شفرة ً ثنائيا باستخدام urllib 5.12قراءة امللفات امل قد ترغب ً أحيانا في استعادة ملف غير نص ي مرمز ً ثنائيا ( )binaryمثل صورة أو فيديو. ً ُ عموما ،تعتبر البيانات املوجودة في هذه امللفات غير ُمفيدة عند عرضها على الخرج .لكنك ببساطة تستطيع إنشاء نسخة من عنوان URLإلى ملف محلي على قرصك الصلب باستخدام .urllib ُ اإلجراء املتبع هنا هو فتح عنوان URLواستعمال التعليمة readلتخزين جميع محتويات امللف في ُمتغير من نوع سلسلة نصية وليكن اسمه imgثم اكتب تلك املعلومات في ملف محلي كما هو موضح في الشيفرة التالية: الفصل الثاني عشر :البرامج املرتبطة بالشبكات 200 import urllib.request, urllib.parse, urllib.error )(img = urllib.request.urlopen('http://data.pr4e.org/cover3.jpg').read )'fhand = open('cover3.jpg', 'wb )fhand.write(img )(fhand.close # Code: http://www.py4e.com/code3/curl1.py يقرأ هذا البرنامج جميع البيانات دفعة واحدة ُويخزنها في املتغير imgفي الذاكرة الرئيسية لحاسوبك. ثم يفتح امللف cover.jpgويكتب البيانات على قرصك الصلب. يفتح الوسيط wbفي التابع )(ً open ملفا ً ثنائيا للكتابة فقط مع العلم أن هذا البرنامج يعمل في حال كان حجم امللف أقل من حجم ذاكرة حاسوبك. أما في حال كان الفيديو أو امللف الصوتي ذو حجم كبير ،فإن البرنامج قد يتوقف ،أو على أقل تقدير سوف يعمل ببطء شديد بينما تنفد ذاكرة حاسوبك. سعيا ُّ ً لتجنب نفاد الذاكرة ،فإننا نسترجع البيانات ككتل ثم نكتب كل كتلة بيانات على القرص قبل استعادة الكتلة التالية .بهذه الطريقة يستطيع البرنامج قراءة أي ملف مهما كان حجمه دون استهالك الذاكرة املوجودة في حاسوبك. import urllib.request, urllib.parse, urllib.error )'img = urllib.request.urlopen('http://data.pr4e.org/cover3.jpg )'fhand = open('cover3.jpg', 'wb size = 0 while True: )info = img.read(100000 if len(info) < 1: break )size = size + len(info الفصل الثاني عشر :البرامج املرتبطة بالشبكات 201 )fhand.write(info )'print(size, 'characters copied. )(fhand.close # Code: http://www.py4e.com/code3/curl2.py حرف ً في هذا املثال ،نقرأ فقط 100,000م َ معا ثم نكتب هذه املحارف في ملف cover.jpgقبل استعادة الـ 100,000محرف التالية من الويب .حيث يظهر خرج البرنامج على النحو التالي: python curl2.py 230210 characters copied. 6.12تحليل واستخراج البيانات من صفحات HTML ُ تعتبر عملية استخراج البيانات من صفحات الويب أحد االستخدامات الشائعة ملكتبة urllibفي لغة بايثون. ً برنامجا يتصرف ُ كمتصفح يتمثل مفهوم استكشاف أو تعقب الويب ( )Web scrapingعندما نكتب ً إنترنت ويقوم باسترجاع الصفحات ،ثم يفحص البيانات املوجودة في تلك الصفحات بحثا عن أنماط ما. كمثال على ذلك ،تعاين محركات البحث مثل غوغل Googleمصدر صفحة ويب ما لتستخرج روابط الصفحات األخرى ثم تستعيد هذه الصفحات ومن ثم تعود لتستخرج الروابط وهكذا.. بفضل هذه التقنية ،يستطيع غوغل الوصول إلى كل الصفحات في الويب ً تقريبا. يستخدم غوغل ً أيضا معدل تكرار رابط صفحة ما في باقي الصفحات على أنها معيار ملدى "أهمية" الصفحة ولتحديد ترتيبها في قائمة نتائج البحث. 7.12تحليل صفحات HTMLباستخدام التعابيرالنمطية يعتبر استخدام التعابير النمطية أحد األساليب البسيطة لتحليل صفحات HTMLوخاصة ألجل عمليات البحث املتكررة واستخراج سالسل نصية فرعية التي تتطابق مع نمط معين. الفصل الثاني عشر :البرامج املرتبطة بالشبكات 202 فيما يلي صفحة ويب بسيطة: ><h1>The First Page</h1 ><p If you like, you can switch to the >"<a href="http://www.dr-chuck.com/page2.htm Second Page</a>. ></p ُيمكننا إنشاء تعبير نمطي الستخراج الرابط من النص أعاله على النحو التالي: "?href="http[s]?://.+ يبحث هذا التعبير النمطي عن السالسل النصية التي تبدأ بـ href="http://أو href="https:// ُ متبوعة بمحرف أو أكثر ? .+ثم بعالمة اقتباس أخرى .كما تشير عالمة االستفهام في التعبير ?] [sإلى البحث عن السلسلة httpمتبوعة بـ صفر أو واحد ( sأي وجود sواحدة أو عدمها). ً ُ عالمة االستفهام في ? .+تشير إلى أن التطابق سيكون من النمط غير املتعدي بدال من النمط املتعدي ( )Pushyحيث يسعى النمط غير املتعدي إليجاد أصغر سلسلة نصية مطابقة ممكنة ،بينما يسعى النمط املتعدي إلى العثور على أكبر سلسلة نصية مطابقة ممكنة. ُ سنضيف األقواس إلى التعبير النمطي لإلشارة إلى الجزء الذي نريد استخراجه من السلسلة املطابقة. ليصبح البرنامج كالتالي: # Search for link values within URL input import urllib.request, urllib.parse, urllib.error import re import ssl # Ignore SSL certificate errors )(ctx = ssl.create_default_context البرامج املرتبطة بالشبكات:الفصل الثاني عشر 203 ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE url = input('Enter - ') html = urllib.request.urlopen(url, context=ctx).read() links = re.findall(b' href="(http[s]?://.*?)" ', html) for link in links: print(link.decode()) # Code: http://www.py4e.com/code3/urlregex.py .HTTPS لهذا البرنامج بالوصول إلى مواقع الويب التي تستخدم بروتوكولssl تسمح مكتبة ً كسلسلة من البايت بدال من إرجاعها ككائنHTML الشيفرة املصدرية لـread ٌيرجع التابع .HTTPResponse حيث يعيد فقط الرابط، قائمة من السالسل النصية املطابقة لتعبيرنا النمطيfindall يعيد التابع .بين عالمتي االقتباس املزدوجة :عند تشغيل البرنامج وإدخال رابط ما نحصل على الخرج التالي Enter - https://docs.python.org https://docs.python.org/3/index.html https://www.python.org/ https://docs.python.org/3.8/ https://docs.python.org/3.7/ https://docs.python.org/3.5/ https://docs.python.org/2.7/ https://www.python.org/doc/versions/ https://www.python.org/dev/peps/ https://wiki.python.org/moin/BeginnersGuide الفصل الثاني عشر :البرامج املرتبطة بالشبكات 204 https://wiki.python.org/moin/PythonBooks https://www.python.org/doc/av/ https://www.python.org/ https://www.python.org/psf/donations/ http://sphinx.pocoo.org/ تعمل التعابير النمطية بشكل رائع للغاية عندما تكون الشيفرة املصدرية لصفحة ال HTMLمكتوبة نظرا لوجود الكثير من صفحات HTMLغير املنسقة ً بشكل منسق وقابل ُّ للتنبؤ .لكن ً جيدا فإن هذا الحل (أي استخدام التعابير النمطية) قد يتسبب بفقدان بعض الروابط املتاحة أو الحصول على بيانات غير مفيدةُ .يمكن حل هذه املشكلة باستخدام مكتبة خاصة للتعامل مع صفحات .HTML 8.12تحليل صفحات HTMLباستخدام مكتبة BeautifulSoup على الرغم من أن صفحات HTMLتبدو ُمشابهة لـ ( XMLسيتم شرح ماهية XMLفي الفصل القادم) وبعض الصفحات مبنية على أساس ،XMLإال أن معظم صفحات HTMLتكون غير منسقة ً جيدا، األمر الذي يؤدي إلى رفض برمجية " "XML parserصفحة HTMLبأكملها بسبب تنسيقها غير الصحيح. يوجد العديد من املكتبات في لغة بايثون ملساعدتك في تحليل صفحات HTMLواستخراج البيانات منهاُ .كل مكتبة من هذه املكتبات تمتلك نقاط قوة ونقاط ضعف وتستطيع اختيار املكتبة ً بناء على احتياجاتك. كمثال على ذلكُ ، سنحلل ببساطة بعض مدخالت HTMLوسنستخرج الروابط باستخدام مكتبة .BeautifulSoup تتساهل مكتبة BeautifulSoupمع صفحات HTMLالتي تحوي ً عيوبا كثيرة وتسمح لك باستخراج البيانات التي تحتاجها بسهولة .بإمكانك تحميل وتنصيب شيفرة البرنامج من الرابط: https://pypi.python.org/pypi/beautifulsoup4 ً اختصارا " "pipمعلومات تنصيب مكتبة تتيح أداة فهرسة حزم بايثون ()Python Package Index BeautifulSoupفي الرابط التالي: https://packaging.python.org/tutorials/installing-packages/ 205 البرامج املرتبطة بالشبكات:الفصل الثاني عشر منhref الستخراج الخاصيةBeautifulSoup لقراءة الصفحة ثم نستخدمurllib سنستخدم مكتبة .<a> الوسم # To run this, download the BeautifulSoup zip file # http://www.py4e.com/code3/bs4.zip # and unzip it in the same directory as this file import urllib.request, urllib.parse, urllib.error from bs4 import BeautifulSoup import ssl # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE url = input('Enter - ') html = urllib.request.urlopen(url, context=ctx).read() soup = BeautifulSoup(html, 'html.parser') # Retrieve all of the anchor tags tags = soup('a') for tag in tags: print(tag.get('href', None)) # Code: http://www.py4e.com/code3/urllinks.py بعدها ُيمرر هذه البيانات، ثم يفتح صفحة الويب ويقرأ البيانات،يطلب البرنامج عنوان صفحة ويب . لكل وسمhref < ليطبع قيمة الخاصيةa> ثم يسترجع كل وسوم،BeautifulSoup إلى ُمحلل مكتبة :عندما نشغل البرنامج فإنه ُينتج الخرج التالي 206 Enter - https://docs.python.org genindex.html py-modindex.html https://www.python.org/ # whatsnew/3.6.html whatsnew/index.html tutorial/index.html library/index.html reference/index.html using/index.html howto/index.html installing/index.html distributing/index.html extending/index.html c-api/index.html faq/index.html py-modindex.html genindex.html glossary.html search.html contents.html bugs.html about.html license.html copyright.html البرامج املرتبطة بالشبكات:الفصل الثاني عشر البرامج املرتبطة بالشبكات:الفصل الثاني عشر 207 download.html https://docs.python.org/3.8/ https://docs.python.org/3.7/ https://docs.python.org/3.5/ https://docs.python.org/2.7/ https://www.python.org/doc/versions/ https://www.python.org/dev/peps/ https://wiki.python.org/moin/BeginnersGuide https://wiki.python.org/moin/PythonBooks https://www.python.org/doc/av/ genindex.html py-modindex.html https://www.python.org/ # copyright.html https://www.python.org/psf/donations/ bugs.html http://sphinx.pocoo.org/ (relative path) هي مسارات نسبيةHTML < فيa> هذه القائمة أطول بكثير مما أردنا ألن بعض وسوم ً " أوhttp://" ') التي ال تتضمن#' :) أو مراجع داخلية (مثالtutorial/index.html :(على سبيل املثال ." والذي كان أحد املتطلبات في تعبيرنا النمطيhttps://" ً يمكنك : الستخراج أجزاء أخرى من أي وسمBeautifulSoup أيضا استخدام # To run this, download the BeautifulSoup zip file # http://www.py4e.com/code3/bs4.zip # and unzip it in the same directory as this file from urllib.request import urlopen 208 البرامج املرتبطة بالشبكات:الفصل الثاني عشر from bs4 import BeautifulSoup import ssl # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE url = input('Enter - ') html = urlopen(url, context=ctx).read() soup = BeautifulSoup(html, "html.parser") # Retrieve all of the anchor tags tags = soup('a') for tag in tags: # Look at the parts of a tag print('TAG:', tag) print('URL:', tag.get('href', None) print('Contents:', tag.contents[0]) print('Attrs:', tag.attrs) # Code: http://www.py4e.com/code3/urllink2.py :فيكون الخرج python urllink2.py Enter - http://www.dr-chuck.com/page1.htm TAG: <a href="http://www.dr-chuck.com/page2.htm"> Second Page</a> URL: http://www.dr-chuck.com/page2.htm Content: ['\nSecond Page'] الفصل الثاني عشر :البرامج املرتبطة بالشبكات 209 ])'Attrs: [('href', 'http://www.dr-chuck.com/page2.htm إن املحلل " "html.parserهو محلل HTMLاملتضمن في مكتبة Python 3املعيارية. تستطيع الحصول على معلومات عن محلالت HTMLأخرى عبر الرابط: http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser ُ تظهر هذه األمثلة مدى قوة مكتبة BeautifulSoupعندما يتعلق األمر بتحليل صفحات .HTML ُ ُ 9.12ميزات خاصة ملستخدمي أنظمة لينكس أو يونيكس إذا كان لديك حاسوب يعمل بنظام تشغيل ُ لينكس ( )Linuxأو يونيكس ( (Unixأو ماكنتوش ) (Macintoshفعلى األرجح أنك تمتلك أوامر جاهزة في نظام التشغيل .حيث تسترجع هذه األوامر النصوص وامللفات املرمزة ً ثنائيا باستعمال بروتوكول نقل النص التشعبي HTTPأو بروتوكول نقل امللفات .)FTP) File Transfer Protocolوأحد هذه األوامر هو :curl $ curl -O http://www.py4e.com/cover.jpg إن األمر curlهو اختصار للتعبير .copy URL ُ إن املثالين الذين ُذكرا ً سابقا السترجاع امللفات املرمزة ً ثنائيا باستخدام urllibأطلق عليهما curl1.py َو curl2.pyعلى املوقع www.py4e.com/code3حيث ُينفذان وظائف مشابهة لألمر .curl ُهناك ً أيضا البرنامج curl3.pyالذي ُينجز هذه املهمة بفعالية أكبر ،في حال كنت تريد استخدام هذا النمط في البرنامج الذي تكتبه. األمر الثاني الذي يؤدي الوظيفة بشكل مشابه هو :wget $ wget http://www.py4e.com/cover.jpg كال األمرين يسهالن عملية استرجاع صفحات الويب وامللفات غير املخزنة ً محليا. 10.12فهرس املصطلحات • مكتبة :BeautifulSoupمكتبة في لغة بايثون نستخدمها لتحليل صفحات HTML ً واستخراج البيانات منها والتي عادة ما يتجاهلها املتصفح .بإمكانك تحميل شيفرة مكتبة BeautifulSoupمن املوقع www.crummy.com الفصل الثاني عشر :البرامج املرتبطة بالشبكات 210 َ • املنفذ ) :(Portرقم ُيشير بشكل عام إلى التطبيق املتصل به عندما تقوم بإجراء اتصال عبر ً مآخذ الشبكة مع الخادم .كمثال على ذلكُ :يستخدم عادة املنفذ 80في عملية إرسال واستقبال البيانات عبر الويب ،بينما للبريد اإللكتروني يستخدم املنفذ .25 • استكشاف أو تعقب الويب ) :(Scrapeعندما يتظاهر البرنامج بأنه متصفح ويب ويسترجع ً صفحة ويب ،ثم ُيعاين محتواها .تتبع البرامج عادة الروابط املوجودة في صفحة واحدة للعثور على الصفحة التالية لذلك بإمكانهم املرور على شبكة من الصفحات أو على شبكة اجتماعية. • مآخذ الشبكة ) :(Socketاتصال شبكي بين تطبيقين ،حيث ُيتاح للتطبيقات تبادل البيانات في كال االتجاهين (إرسال واستقبال). ٌ • املتعقب ) :(Spiderعندما يقوم محرك البحث باستعادة صفحة ثم كل الصفحات املرتبطة بهذه الصفحة وهكذا حتى يصل ً تقريبا إلى كل الصفحات في اإلنترنت ،حيث يتم استخدام هذا في بناء فهرس البحث. 11.12تمارين • التمرين ّ األول :عدل البرنامج socket1.pyبحيث يطلب عنوان URLمن املستخدم ليتمكن َ البرنامج من الوصول إلى أي صفحة ويبُ .يمكنك استخدام التابع (' split)'/من أجل تجزئة ُ عنوان URLإلى مكوناته بحيث تتمكن من استخراج اسم املضيف من أجل استدعاء التابع .connectأضف ميزة تجنب األخطاء باستخدام تعليمتي َ tryو exceptللتعامل مع الحالة التي ُيدخل بها املستخدم روابط URLخاطئة أو غير موجودة. • التمرين الثاني :عدل البرنامج السابق بحيث يحسب عدد املحارف التي استقبلها ،ثم يتوقف َ ُ عن إظهار أي نص بعد عرض 3000محرف .يجب على البرنامج استعادة املستند بالكامل وحساب العدد اإلجمالي للمحارف وعرضه في نهاية املستند. • التمرين الثالث :استخدم مكتبة urllibلتكرار التمرين السابق من أجل )1( :استعادة ُ ُ املستند من عنوان (2) ،URLعرض قرابة الـ 3000محرف (3) ،حساب العدد اإلجمالي للمحارف في املستند .ال تقلق بشأن الترويسة في هذا التمرين ،ما عليك سوى إظهار أول الفصل الثاني عشر :البرامج املرتبطة بالشبكات 211 3000محرف من محتويات املستند. ُ • التمرين الرابع :قم بتعديل برنامج urllinks.pyالستخراج وحساب وسوم الفقرات > <pمن ُمستند HTMLالذي تم استعادته ،ثم اعرض عدد الفقرات كخرج لبرنامجك. ال تعرض َنص الفقرة بل قم بإحصائهم فقطَ . اختبر البرنامج على عدة صفحات ويب صغيرة باإلضافة إلى بعض صفحات الويب الكبيرة. • التمرين الخامس(ُ :متقدم) غير برنامجك socket1.pyبحيث يعرض البيانات فقط بعد استقبال الترويسة وسطر فارغ. تذكر أن التابع recvيستقبل البيانات كمحارف (محرف السطر الجديد أحدها) وليس كأسطر. الفصل الثالث عشر استخدام خدمات الويب الفصل الثالث عشر :استخدام خدمات الويب 213 13استخدام خدمات الويب ً لم يستغرق األمر طويال لتطوير منهجية إلنشاء ملفات صممت لتستخدمها برامج أخرى (مثال :فتح صفحة غير مبنية باستخدام HTMLبواسطة املتصفح) بعد أن أصبحت عملية استدعاء امللفات وتحليلها سهلة التنفيذ عبر برامج تستخدم برتوكول ،HTTPحيث يوجد صيغتين نستخدمهما عند تبادل البيانات عبر الويب ،أولها لغة التوصيف املوسعة ،XMLوالتي استخدمت لزمن طويل وتعتبر األنسب لتبادل البيانات على شكل ملفات ،بينما تستخدم البرامج ترميز جافا سكربت الغرض ي ( JSONللمزيد تصفح املوقع )www.json.orgلتبادل القواميس والقوائم فيما بينها أو أي معلومات داخلية ،وسنشرح كلتا الصيغتين. 1.13لغة التوصيف املوسعة XML ً تنظيما ،ونرى هذا في املثال اآلتي: تشبه XMLالـ HTMLولكنها أكثر ><person ><name> Chuck </name >"<phone type="intl +1 734 303 4456 ></phone ><email hide="yes" / ></person كما نالحظ ،يمثل كل زوج من وسوم االفتتاح مثل < >personواإلغالق مثل < >/personعنصر أو عقدة ( )Nodeبنفس اسم الوسم مثل ،personويمكن أن يكون لكل عنصر نص معين أو خصائص "سمات" مثل hideوعناصر متداخلة أخرى ،وإذا كان العنصر فارغ بال محتوى فيمكن أن ٌيغلق ً ذاتيا مثل < ،<email /أي من املفيد أن تنظر إلى ملف XMLعلى أنه ذو بنية شجرية ،حيث يوجد عنصر رئيس في مثالنا السابق personووسوم أخرى مثل phoneوكأنها فروع من العناصر الرئيسية (األبوية). الفصل الثالث عشر :استخدام خدمات الويب 214 الشكل :14تمثيل شجري للغةXML 2.13تحليل نصوص XML فيما يلي تطبيق عن تحليل نص XMLواستخراج بعض عناصر البيانات منه: import xml.etree.ElementTree as ET ' ' ' = data ><person ><name>Chuck</name >"<phone type="intl +1 734 303 4456 ></phone ><email hide="yes" / ' ' ' ></person )tree = ET.fromstring(data )print('Name: ', tree.find('name').text ))'print('Attr: ', tree.find('email').get('hide # Code: http://www.py4e.com/code3/xml1.py تسمح إشارات التنصيص (االقتباس) األحادية واملزدوجة الثالثية (' ' ' و""") بإنشاء سالسل نصية تمتد على عدة أسطر ،كما أن استدعاء fromstringيحول السالسل النصية في XMLإلى شجرة من العناصر ،فعندما تكون XMLفي نمط شجرة يكون لدينا عدة توابع يمكننا استدعاؤها الستخراج أجزاء من البيانات من السالسل النصية ،أما التابع findفيبحث في شجرة XMLعن الوسم املطابق ملا حدد ضمنه ويستدعيه. استخدام خدمات الويب:الفصل الثالث عشر 215 Name: Chuck Attr: yes بدون القلق حولXML باستخراج البيانات منElementTree مثلXML يسمح لنا محلل نصوص . والتي تتوضح لنا في املثال السابق البسيط الذي عرضناه،القواعد الكتابية لها استخدام الحلقات للمرورعلى العقد3.13 ً كما في البرنامج، عدة عقد حيث نحتاج لكتابة حلقة ملعالجة كل تلك العقدXML عادة ما تحوي :user اآلتي حيث نمر على كل عقد املستخدم import xml.etree.ElementTree as ET input = ' ' ' <stuff> <users> <user x="2"> <id>001</id> <name>Chuck</name> </user> <user x="7"> <id>009</id> <name>Brent</name> </user> </users> </stuff>' ' ' stuff = ET.fromstring(input) lst = stuff.findall('users/user') print('User count:', len(lst)) for item in lst: print('Name', item.find('name').text) print('Id', item.find('id').text) print('Attribute', item.get('x')) # Code: http://www.py4e.com/code3/xml2.py الفصل الثالث عشر :استخدام خدمات الويب 216 ٌيرجع التابع findallقائمة مكونة من تفرعات تمثل بنية الوسم userفي شجرة ،XMLنكتب بعدها ً حلقة forتمر على كل عقدة من عقد الوسم userوتطبع العناصر النصية nameو idإضافة إلى الخاصية xمن عقدة الوسم :user User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Id 009 Attribute 7 ومن املهم تضمين جميع العناصر الرئيسية (األبوية) في تعليمة ( findallمثل )users/userباستثناء أي من العقد املطلوبة: عند التعامل مع عناصر املستوى الرئيس ي األول وإال لن تجد بايثون ٍ import xml.etree.ElementTree as ET ' ' ' = input ><stuff ><users >"<user x="2 ><id>001</id ><name>Chuck</name ></user >"<user x="7 ><id>009</id ><name>Brent</name ></user ></users ' ' ' ></stuff )stuff = ET.fromstring(input )'lst = stuff.findall('users/user الفصل الثالث عشر :استخدام خدمات الويب 217 ))print('User count:', len(lst )'lst2 = stuff.findall('user ))print('User count:', len(lst2 تخزن القائمة lstكل عناصر الوسم userاملضمنة في الوسم ،usersبينما تبحث lst2عن عناصر الوسم userاملضمنة في وسم املستوى األول stuffلكن ال تجد ًأيا منها. User count: 2 User count: 0 JSON 4.13 ُ استوحت هذه الصيغة من الصيغة الغرضية واملصفوفية في لغة جافا سكربت ،إال أن قواعد كتابة بايثون فيما يتعلق بالقواميس والقوائم أثرت على قواعد JSONباعتبار أنها ُوجدت قبل جافا سكربت ،لذلك تعتبر هذه الصيغة خليط من قوائم وقواميس بايثون ،وفيما يأتي مثال عن ترميز JSONمكافئ لبرنامج XMLاملذكور ً سابقا: { "name" : "Chuck", { "phone" : "type" : "intl", ""number" : "+1 734 303 4456 }, { "email" : ""hide" : "yes } } قد تالحظ بعض الفروق ففي XMLنستطيع إضافة السمة intlإلى الوسم phoneبينما لدينا أزواج ُ مفتاح-قيمة في JSONكما يختفي الوسم personهنا فقد استبدل باألقواس الخارجية. ً عموما ،فإن بنية JSONأبسط من بنية XMLحيث تملك إمكانيات أقل ،ولكن تملك األفضلية من حيث االرتباط مباشرة مع تركيبة القواميس والقوائم ،كما أنها صيغة بسيطة لجعل برنامجين ً يعمالن ً معا ويتبادالن البيانات باعتبار أن جميع لغات البرمجة ً مكافئا لقواميس وقوائم تقريبا تملك الفصل الثالث عشر :استخدام خدمات الويب 218 ً إضافة إلى أنها سرعان ما أصبحت ً خيارا لصيغة معظم عمليات تبادل البيانات بين بايثون، ً التطبيقات بسبب بساطتها مقارنة مع .XML 5.13تحليل نصوص JSON ننش ئ ملفات JSONبترتيب القواميس والقوائم داخل بعضهم البعض كما نحتاج ،وفي هذا املثال نمثل قائمة مستخدمين بحيث يكون كل مستخدم عبارة عن مجموعة من أزواج مفتاح-قيمة (أي قاموس) أي لدينا قائمة من القواميس ،كما سنستخدم مكتبة جاهزة لتحليل نص JSONوقراءة البيانات ،وبإمكانك إجراء املقارنة مع املثال السابق في ،XMLحيث JSONتحوي تفاصيل أقل أي ً مسبقا أننا سنحصل على قائمة تمثل املستخدمين حيث كل مستخدم هو مجموعة يجب أن نعلم من أزواج مفتاح-قيمة فـ JSONأكثر ً إيجازا (وهي نقطة إيجابية) ولكنها صعبة التوصيف الذاتي (وهذه سلبية): import json ' ' '= data [ { "id" : "001", "x" : "2", ""name" : "Chuck }, { "id" : "009", "x" : "7", ""name" : "Brent } '''] )info = json.loads(data ))print('User count:', len(info for item in info: )]'print('Name', item['name )]'print('Id', item['id )]'print('Attribute', item['x # Code: http://www.py4e.com/code3/json2.py الفصل الثالث عشر :استخدام خدمات الويب 219 إذا قارنت شيفرة استخراج البيانات بين XMLو JSONفستالحظ أننا نحصل من التابع ً قاموسا، () json.loadsعلى قائمة نمر على عناصرها بحلقة forويمثل كل عنصر في تلك القائمة ونستطيع استخدام عامل الفهرس الستخراج البيانات املختلفة لكل مستخدم بمجرد تحليل نص ،JSONكما لسنا مضطرين الستخدام مكتبة JSONإلجراء عملية التحليل باعتبار أن بنية البيانات هي بنية معروفة لبايثون ،ويكون خرج هذا البرنامج مطابق لخرج البرنامج السابق في XMLوهو: User count: 2 Name Chuck Id 001 Attribute 2 Name Brent Id 009 Attribute 7 َ ً عموما ،يوجد توجه منهي نحو JSONبدال من XMLفيما يتعلق بخدمات الويب ،ألنها أبسط وتعبر ً عن بنى البيانات األساسية املوجودة في لغات البرمجة بشكل أكبر إضافة إلى كون عملية التحليل واستخراج البيانات أبسط ومباشرة بشكل أكبر ،إال أن XMLقابلة للتوصيف الذاتي بشكل أفضل مما يجعل استخدامها أفضلية في بعض التطبيقات ،فعلى سبيل املثال ،معظم معالجات النصوص ً ً داخليا باستخدام XMLبدال من .JSON تخزن امللفات 6.13واجهات برمجة التطبيقات API نتمتع اليوم بالقدرة على تبادل البيانات بين التطبيقات باستخدام بروتوكول HTTPمع طريقة لتمثيل البيانات املعقدة املتبادلة باستخدام لغة التوصيف املوسعة XMLأو ترميز جافا سكربت الغرض ي ،JSONوتكمن الخطوة التالية في تحديد وتوثيق "االتفاقيات" بين تلك التطبيقات عبر هذه التقنيات ،االسم العام لهذه االتفاقيات بين التطبيقات هو واجهات برمجة التطبيقات API فعند استخدامها يجعل أحد البرامج مجموعة من الخدمات متاحة لتستخدمها تطبيقات أخرى كما بنشر تلك الواجهات (أي القواعد) التي يجب اتباعها للوصول إلى الخدمات التي يقدمها .ندعو النهج الذي يتضمن تصميم البرامج التي تتطلب وظيفتها الوصول إلى خدمات برامج أخرى ،باسم البنية خدمية التوجه SOAأي استخدام برنامجنا النهائي لخدمات تطبيقات أخرى .بينما يعرف نهج البنية ال خدمية التوجه non-SOAبأنه تطبيق قائم بذاته يحتوي على جميع التعليمات البرمجية الالزمة ليقدم خدماته. الفصل الثالث عشر :استخدام خدمات الويب 220 ً عادة نالحظ العديد من أمثلة SOAأثناء استخدام الويب ،فبإمكاننا الدخول إلى موقع ما وحجز تذكرة طيران أو إجراء حجز فندقي أو حجز سيارة من نفس املوقع ،إال أن بيانات الفنادق غير مخزنة على حواسيب خطوط الطيران ،بل تتواصل هذه الحواسيب مع الخدمات على حواسيب الفندق الستدعاء بياناته وعرضها للمستخدم ،أي أن موقع خطوط الطيران يستخدم خدمة ويب أخرى موجودة في أنظمة الفندق عندما يوافق املستخدم على إجراء حجز في ذلك الفندق من خالل هذا املوقع ،وبالتالي تدخل عدة حواسيب في هذه العملية حتى عند دفعك لألجور املستحقة. خدمة حجز السيارات خدمة الحجز الفندقي خدمة حجز رحلة الطيران API API API برنامج سفريات الشكل : 15البنية خدمية التوجه ومن فوائد البنى خدمية التوجه (:)SOA ً .1نحتفظ بنسخة واحدة من البيانات فقط (وهذا مهم خاصة فيما يشابه حجوزات الفنادق حيث ال يتم االلتزام ملدة طويلة). .2بإمكان مالكي البيانات وضع قواعد الستخدامها. ومع هذه الفوائد يجب أن يصمم نظام SOAبحذر ليتميز باألداء الجيد ويلبي حاجات املستخدم، ويظهر هنا مصطلح خدمات الويب حيث يجعل تطبيق ما مجموعة من الخدمات في واجهته متاحة عبر الويب. الفصل الثالث عشر :استخدام خدمات الويب 221 7.13األمان واستخدام واجهات برمجة التطبيقات من الشائع احتياجك إلى مفتاح معين الستخدام واجهة برمجة التطبيقات العائدة لشركة ما، والهدف رغبتهم في معرفة من يستخدم خدماتهم ،وكمية استخدامه ،لربما لديهم خدمات مدفوعة أو مجانية أو سياسة تحديد عدد الطلبات املتاحة للفرد خالل مدة زمنية معينة ،وأحيانا بمجرد حصولك على املفتاح تضمنه كجزء من بيانات رسالة POSTأو كمعامل في الرابط ( )URLعند استدعاء الواجهة البرمجية ،وفي بعض األحيان تطلب الشركة ضمان أكبر فيما يتعلق بمصدر الطلبات لهذا يطلبون منك إرسال رسائل موقعة ومشفرة باستخدام املفاتيح املشاركة ،أما التقنية الشائعة لتوقيع الطلبات عبر اإلنترنت فتدعى OAuthوبإمكانك التعرف على هذا البروتوكول عبر الرابط ،www.oauth.netولحسن الحظ توجد بعض مكتبات OAuthاملجانية واملناسبة لتجنب كتابة تطبيق OAuthمن الصفر من خالل قراءة املواصفات فقط .كما تختلف تلك املكتبات بدرجة تعقيدها وسعتها ،و ً أيضا تستطيع الحصول على معلومات أكثر عن مكتبات OAuthمن خالل زيارة املوقع املذكور أعاله. 8.13فهرس املصطلحات • واجهة برمجة التطبيقات ( :)APIاتفاقية بين التطبيقات تحدد أنماط التفاعل بين مكونات تطبيقين. • مكتبة :ElementTreeمكتبة برمجية مضمنة في لغة بايثون تستخدم لتحليل نصوص .XML ً اعتمادا على القواعد الكتابية للكائنات في جافا • :JSONصيغة تسمح بترميز بيانات مهيكلة سكربت. • البنى خدمية التوجه ( :)SOAمصطلح يستخدم عند بناء تطبيق من مكونات متصلة ببعضها عبر شبكة ما. • لغة التوصيف املوسعة ( :)XMLصيغة تسمح بترميز بيانات مهيكلة. الفصل الثالث عشر :استخدام خدمات الويب 222 9.13التطبيق األول :خدمة الترميزالجغرافي من غوغل لغوغل خدمة ذات فائدة كبرى ،إذ تسمح لنا باستخدام قاعدة بياناتهم الضخمة الخاصة باملعلومات الجغرافية ،حيث نستطيع إجراء بحث جغرافي نص ي مثل " "Ann Arbor, MITضمن واجهة برمجة التطبيقات للترميز الجغرافي من غوغل لتعيد لنا أفضل تخمين للمكان التي يمكن أن يجد فيه العنوان املطلوب على الخريطة الجغرافية ويخبرنا باملعالم املحيطة به .هذه الخدمة مجانية ولكنها محدودة ،أي أن استخدامك للواجهة في التطبيقات التجارية محدود ،ولكن إن كانت لديك بيانات حيث يدخل املستخدم موقع ما ً مجانا فبإمكانك استخدام هذه الواجهة للتعامل مع البيانات بشكل جيد. ً يجب أن تكون معتدال عند استخدام الواجهات املجانية كواجهة غوغل للترميز الجغرافي حيث يمكن لغوغل إلغاءها أو تقليل الخدمات املتاحة إن أساء عدد كبير من الناس استخدامها ،كما يمكنك قراءة توصيف تلك الخدمة على اإلنترنت وهو بسيط للغاية وتستطيع اختباره على أحد املتصفحات بكتابة الرابط اآلتي: http://maps.googleapis.com/maps/api/geocode/json?address=Ann+Arbor%2C+MI ً لكن تأكد من إزالة الفراغات منه قبل لصقه إلى املتصفح ،وسنضع مثاال عن تطبيق يطلب من املستخدم إدخال مكان ما لنبحث عنه ثم يستدعي واجهة الترميز الجغرافي لغوغل ليستخرج املعلومات من ترميز JSONاملعاد: import urllib.request, urllib.parse, urllib.error import json import ssl api_key = False # If you have a Google Places API key, enter it here # api_key = AIzaSy___IDByT70 #https://developers.google.com/maps/documentation/geocoding/intro if api_key is False: api_key = 42 ' ?serviceurl = 'http://py4e-data.dr-chuck.net/json else : ' ?serviceurl = ' https://maps.googleapis.com/maps/api/geocode/json استخدام خدمات الويب:الفصل الثالث عشر 223 # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE while True: address = input('Enter location: ' ) if len(address) < 1: break parms = dict() parms['address'] = address if api_key is not False: parms['key'] = api_key url = serviceurl + urllib.parse.urlencode(parms) print('Retrieving', url) uh = urllib.request.urlopen(url, context=ctx) data = uh.read().decode() print('Retrieved', len(data), 'characters') try: js = json.loads(data) except: js = None if not js or 'status' not in js or js['status'] != 'OK': print('==== Failure To Retrieve ====') print(data) continue print(json.dumps(js, indent=4)) lat = js['results'][0]['geometry']['location']['lat'] lng = js['results'][0]['geometry']['location']['lng'] print('lat', lat, 'lng', lng) location = js['results'][0]['formatted_address'] print(location) # Code: http://www.py4e.com/code3/geojson.py الفصل الثالث عشر :استخدام خدمات الويب 224 مستخدما إياه كمعامل َّ ً مشفر ثم يستخدم urllib يستقبل البرنامج نص البحث وينش ئ رابط )(URL الستدعاء النص من واجهة غوغل للترميز الجغرافي ،كما تعتمد البيانات التي نحصل عليها على املعامالت التي نرسلها والبيانات الجغرافية املخزنة في خوادم غوغل على عكس صفحات الويب الثابتة ،وبمجرد حصولنا على بيانات JSONنحللها باستخدام مكتبة JSONلنجري بعدها عدة َ املستقبلة ،ثم نستخرج املعلومات التي نبحث عنها. اختبارات للتأكد من جودة البيانات ويكون خرج البرنامج كاآلتي ُ (حذفت بعض بيانات JSONاملستقبلة): $ python3 geojson.py Enter location: Ann Arbor, MI Retrieving http://py4e-data.dr-chuck.net/json?address=Ann+Arbor%2C+MI&key=42 Retrieved 1736 characters { [ "results": { [ "address_components": { "long_name": "Ann Arbor", "short_name": "Ann Arbor", [ "types": "locality", ""political ] }, { "long_name": "Washtenaw County", "short_name": "Washtenaw County", [ "types": "administrative_area_level_2", ""political ] }, { استخدام خدمات الويب:الفصل الثالث عشر 225 "long_name": "Michigan", "short_name": "MI", "types": [ "administrative_area_level_1", "political" ] }, { "long_name": "United States", "short_name": "US", "types": [ "country", "political" ] } ], "formatted_address": "Ann Arbor, MI, USA", "geometry": { "bounds": { "northeast": { "lat": 42.3239728, "lng": -83.6758069 }, "southwest": { "lat": 42.222668, "lng": -83.799572 } }, "location": { "lat": 42.2808256, "lng": -83.7430378 }, الفصل الثالث عشر :استخدام خدمات الويب 226 "location_type": "APPROXIMATE", { "viewport": { "northeast": "lat": 42.3239728, "lng": -83.6758069 }, { "southwest": "lat": 42.222668, "lng": -83.799572 } } }, "place_id": "ChIJMx9D1A2wPIgR4rXIhkb5Cds", [ "types": "locality", ""political ] } ], ""status": "OK } lat 42.2808256 lng -83.7430378 Ann Arbor, MI, USA Enter location: ويمكنك تنزيل البرنامج www.py4e.com/code3/geoxml.pyالكتشاف اختالف البرنامج بحالة استخدام XMLلواجهة ترميز غوغل الجغرافي. التمرين األول :عدل أحد البرنامجين geojson.pyأو geoxml.pyلطباعة رمز الدولة الثنائي من البيانات املستقبلة وأضف تعليمات للتحقق من األخطاء كي ال يفشل برنامجك إن لم يكن رمز الفصل الثالث عشر :استخدام خدمات الويب 227 الدولة موجود ،وبمجرد عمله ابحث عن املحيط األطلس ي " "Atlantic Oceanوتأكد أنه يستطيع التعامل مع مواقع غير موجودة ضمن حدود أي دولة. 10.13التطبيق الثاني :تويتر انتقلت تويتر من الواجهات مفتوحة املصدر والعامة إلى الواجهات التي تتطلب استخدام تواقيع OAuthلكل طلب وذلك مع ازدياد أهمية واجهاتها ،وألجل املثال التالي نزل امللفات twurl.py و hidden.pyو oauth.pyو twitter1.pyمن www.py4e.com/codeوضعهم في مجلد واحد ً معا على حاسوبك ،والستخدام هذه البرامج تحتاج حساب على تويتر وتفويض برنامجك كتطبيق وإعداد املفتاح وكلمة سر والرمز ( )tokenوكلمة سر الرمز ومن ثم عدل امللف hidden.pyوضع هذه السالسل النصية ضمن متحوالت مناسبة في البرنامج: # Keep this file separate # https://apps.twitter.com/ # Create new App and get the four strings def oauth(): return {"consumer_key": "h7Lu...Ng", "consumer_secret" : "dNKenAC3New...mmn7Q", "token_key" : "10185562-eibxCp9n2...P4GEQQOSGI", }""token_secret" : "H0ycCFemmC4wyf1...qoIpBo # Code: http://www.py4e.com/code3/hidden.py نصل لخدمات تويتر عبر الرابط اآلتي: https://api.twitter.com/1.1/statuses/user_timeline.json ولكن بمجرد إضافة جميع معلومات األمان فسيبدو الرابط كاآلتي: https://api.twitter.com/1.1/statuses/user_timeline.json?count=2 &oauth_version=1.0&oauth_token=101...SGI&screen_name=drchuck &oauth_nonce=09239679&oauth_timestamp=1380395644 &oauth_signature=rLK...BoD&oauth_consumer_key=h7Lu...GNg استخدام خدمات الويب:الفصل الثالث عشر 228 &oauth_signature_method=HMAC-SHA1 في حال أردت املزيد من املعلومات حول معاني املعامالت املختلفةOAuth ويمكنك قراءة توصيف twurl.py وoauth.py سنخفي كل التعقيدات في امللفات، لألمانOAuth املضافة لتلبية متطلبات ً ثم نرسل الرابطhidden.py بداية نضيف كلمة السر في.من أجل البرامج التي تعمل مع تويتر . لتضيف املكتبة جميع املعامالت الالزمة إلى الرابط ألجلناtwurl.augment املطلوب إلى التابع JSON يحدد هذا البرنامج منشورات (تغريدات) مستخدم تويتر محدد ويعيدها إلينا في صيغة : محرف منها على الشاشة250 كسلسلة نصية لنظهر أول import urllib.request, urllib.parse, urllib.error import twurl import ssl # https://apps.twitter.com/ # Create App and get the four strings, put them in hidden.py TWITTER_URL = 'https://api.twitter.com/1.1/statuses/user_timeline.json' # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE while True: print('') acct = input('Enter Twitter Account:') if (len(acct) < 1): break url = twurl.augment(TWITTER_URL,{'screen_name': acct, 'count': '2'}) print('Retrieving', url) connection = urllib.request.urlopen(url, context=ctx) data = connection.read().decode() print(data[:250]) استخدام خدمات الويب:الفصل الثالث عشر 229 headers = dict(connection.getheaders()) # print headers print('Remaining', headers['x-rate-limit-remaining']) # Code: http://www.py4e.com/code3/twitter1.py :وعند تشغيل البرنامج نحصل على الخرج اآلتي Enter Twitter Account: drchuck Retrieving https://api.twitter.com/1.1/ … [{"created_at":"Sat Sep 28 17:30:25 +0000 2013"," id":384007200990982144,"id_str":"384007200990982144", "text":"RT @fixpert: See how the Dutch handle traffic intersections: http:\/\/t.co\/tIiVWtEhj4\n#brilliant", "source":"web","truncated":false,"in_rep Remaining 178 Enter Twitter Account: fixpert Retrieving https://api.twitter.com/1.1/ … [{"created_at":"Sat Sep 28 18:03:56 +0000 2013", "id":384015634108919808,"id_str":"384015634108919808", "text":"3 months after my freak bocce ball accident, my wedding ring fits again! :)\n\nhttps:\/\/t.co\/2XmHPx7kgX", "source":"web","truncated":false, Remaining 177 Enter Twitter Account: ً ً تعيد تويتر أي إضافة إلى بياناتHTTP ضا بيانات وصفية حول الطلب في ترويسة استجابة بعدد الطلبات التيx-rate-limit-remaining ويخبرنا أحد البيانات الوصفية وهو،املنشورات ً نستطيع إرسالها قبل إيقاف الخدمة كما يمكنك مالحظة أن عدد مرات االستدعاء تقل،مؤقتا .بواحد بعد كل طلب 230 استخدام خدمات الويب:الفصل الثالث عشر املستقبلة الستخراجJSON نستدعي قائمة أصدقاء مستخدم تويتر ونحلل نصوص،في املثال التالي ً و،بعض املعلومات حول أولئك األصدقاء بعد تحليله ثم نطبع مؤشرJSON أيضا نتخلص من ملف :معبر عنه من أربع محارف يسمح لنا بمسح البيانات إذا أردنا استخراج حقول معلومات إضافية import urllib.request, urllib.parse, urllib.error import twurl import json import ssl # https://apps.twitter.com/ # Create App and get the four strings, put them in hidden.py TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json' # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE while True: print('') acct = input('Enter Twitter Account:') if (len(acct) < 1): break url = twurl.augment(TWITTER_URL, {'screen_name': acct, 'count': '5'}) print('Retrieving', url) connection = urllib.request.urlopen(url, context=ctx) data = connection.read().decode() js = json.loads(data) print(json.dumps(js, indent=2)) headers = dict(connection.getheaders()) print('Remaining', headers['x-rate-limit-remaining']) for u in js['users']: استخدام خدمات الويب:الفصل الثالث عشر 231 print(u['screen_name']) if 'status' not in u: print(' * No status found') continue s = u['status']['text'] print(' ', s[:50]) # Code: http://www.py4e.com/code3/twitter2.py تتحول إلى قوائم وقواميس بايثون متداخلة فنستطيع استخدام مزيج من عاملJSON وبما أن ، لنمر عبر بنى البيانات املستقبلة باستخدام عدد قليل من تعليمات بايثونfor الفهرس وحلقات :)وسيبدو خرج البرنامج كما يأتي (اختصرت بعض عناصر البيانات لتسع الصفحة Enter Twitter Account:drchuck Retrieving https://api.twitter.com/1.1/friends ... Remaining 14 { "next_cursor": 1444171224491980205, "users": [ { "id": 662433, "followers_count": 28725, "status": { "text": "@jazzychad I just bought one .__.", "created_at": "Fri Sep 20 08:36:34 +0000 2013", "retweeted": false, }, "location": "San Francisco, California", "screen_name": "leahculver", "name": "Leah Culver", }, { "id": 40426722, استخدام خدمات الويب:الفصل الثالث عشر 232 "followers_count": 2635, "status": { "text": "RT @WSJ: Big employers like Google ...", "created_at": "Sat Sep 28 19:36:37 +0000 2013", }, "location": "Victoria Canada", "screen_name": "_valeriei", "name": "Valerie Irvine", } ], "next_cursor_str": "1444171224491980205" } leahculver @jazzychad I just bought one .__. _valeriei RT @WSJ: Big employers like Google, AT&T are h ericbollens RT @lukew: sneak peek: my LONG take on the good &a halherzog Learning Objects is 10. We had a cake with the LO, scweeker @DeviceLabDC love it! Now where so I get that "etc Enter Twitter Account: @ (حساب املؤلف) فيdrchuck تقرأ بيانات أحدث خمس أصدقاء لحساب تويترfor نرى أن حلقة إال أنه توجد بيانات أكثر متاحة،القسم األخير من الخرج وتطبع آخر تغريدة (منشور) لكل صديق "بالنظر إلى خرج البرنامج أن خدمة "جد األصدقاء- كما ستالحظ، املستقبلJSON ضمن ملف الفصل الثالث عشر :استخدام خدمات الويب 233 لحساب تويتر له معدل محدد ومختلف القيمة عن عدد طلبات الحصول على املنشورات املسموح لنا إجراؤها خالل مدة زمنية معينة. إن هذه املفاتيح املؤمنة الخاصة بالواجهات تسمح لتويتر بتكوين معرفة عميقة ملن يستخدم واجهاتهم وبياناتهم وعلى أي مستوى ،بينما يسمح لنا مفهوم تحديد معدل االستخدام بإجراء استدعاءات بسيطة وشخصية للبيانات ولكن ال يسمح بتصميم منتج يسحب البيانات من واجهاتهم مليون مرة باليوم الواحد. الفصل الرابع عشر البرمجة كائنية التوجه الفصل الرابع عشر :البرمجة كائنية التوجه 235 14البرمجة الكائنية التوجه 1.14إدارة البرامج الكبيرة مررنا في الفصول األولى من الكتاب على أربع أنماط برمجية لبناء البرامج املختلفة وهي: الشيفرة التسلسلية الشيفرة الشرطية (بنية )if الشيفرة التكرارية )الحلقات) التخزين وإعادة االستخدام (التوابع)ثم تعرفنا في الفصول الالحقة إلى املتغيرات إلى جانب بعض بنى البيانات مثل القوائم والصفوف والقواميس. َ كتبت حتى اآلن العديد من البرامج ،منها املمتاز ومنها غير املتقن وبالرغم من أن هذه البرامج لقد بسيطة ولكن البد أن تكون قد أدركت اآلن أن البرمجة فن. من املهم للغاية كتابة شيفرة سهلة الفهم خاصة حين يتكون البرنامج من ماليين األسطر ،فحينها لن يستطيع عقلك استيعابه .لذا اقتضت الحاجة أن يتم تقسيم البرنامج إلى قطع صغيرة حتى يتسنى لنا التركيز على حل مشكلة وإصالح خطأ أو إضافة ميزة جديدة. وهنا يأتي دور البرمجة كائنية التوجه ،فهي طريقة لترتيب الشيفرات تمكنك من التركيز على 50سطر من الشيفرة وفهمها وتجاهل األسطر 999950األخرى. 2.14مقدمة كباقي النواحي البرمجية من الضروري تعلم مفاهيم البرمجة كائنية التوجه قبل استخدامها ،فعليك التركيز في هذا الفصل على تعلم بعض مصطلحاتها ومفاهيمها وتنفيذ بعض األمثلة البسيطة لوضع آت. حجر األساس ملا هو ٍ ُ ً مبدئيا كيف تبنى الكائنات وطريقة عملها واألهم من ذلك كيف نستفيد هدفنا األساس ي هو أن تفهم من الكائنات الجاهزة التي تزودنا بها لغة بايثون ومكتباتها. الفصل الرابع عشر :البرمجة كائنية التوجه 236 3.14استخدام الكائنات دعني أخبرك بش يء ،لقد كنا نستخدم الكائنات بكثرة في هذا الكتاب حيث توفر لغة بايثون العديد من الكائنات الجاهزة ،إليك بعض الشيفرات البسيطة ،الحظ األسطر األولى منها فستجدها مألوفة لديك: )(stuff = list )'stuff.append('python )'stuff.append('chuck )(stuff.sort )]print (stuff[0 ))print (stuff.__getitem__(0 ))print (list.__getitem__(stuff,0 # Code: http://www.py4e.com/code3/party1.py لندع اآلن ما تنفذه هذه األسطر ولنلقي نظرة على ماذا يحدث ً حقا من وجهة نظر البرمجة كائنية التوجه ،ال تقلق إذا شعرت أن الفقرات التالية بال أي معنى عند قراءتها للمرة األولى فأنت لم تتعرف على جميع املفاهيم بعد. يبني السطر األول كائنا من نوع قائمة listفي حين يستدعي السطر الثاني والثالث تابع () appendلهذا الكائن ،ثم استدعينا في السطر الرابع التابع () sortوفي السطر الخامس نحصل على أول عنصر في القائمة. ننتقل إلى السطر السادس حيث نستدعي تابع ()__ __getitemفي القائمة stuffبمعامل صفري (لنستعيد العنصر ذو الفهرس صفر في القائمة). ))print (stuff.__getitem__(0 السطر السابع هو مجرد طريقة مطولة السترجاع العنصر الصفري في القائمة. ))print (list.__getitem__(stuff,0 في هذه الشيفرة استدعينا التابع __ __getitemمن الصنف ) list (classومررنا القائمة والعنصر الذي نريد استرجاعه من القائمة كمعامل. الفصل الرابع عشر :البرمجة كائنية التوجه 237 إن األسطر الثالث األخيرة من البرنامج متكافئة ،لكن من األنسب استخدم األقواس املربعة [ ] للبحث عن عنصر محدد في قائمة. يمكننا التعرف على قدرات الكائن عبر النظر إلى خرج التابع )(: dir )(>>> stuff = list )>>> dir(stuff ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', ]''insert', 'pop', 'remove', 'reverse', 'sort >>> سيتضح لك في بقية هذا الفصل كل املصطلحات املبهمة في األعلى لذلك أحرص على العودة عندما تنهي الفصل وأعد قراءة الفقرات السابقة كي تتحقق من فهمك. 4.14البدء مع البرامج تعلمنا ً سابقا أن البرنامج في أبسط أشكاله يأخذ بعض املدخالت ،ليعالجها ،ثم ٌينتج بعض من املخرجات .فلننظر إلى برنامج تحويل أرقام الطوابق في املصاعد القصير ً جدا لكنه كامل ُويظهر كال من تلك الخطوات الثالث. )' usf = input('Enter the US Floor Number: wf = int(usf) - 1 )print('Non-US Floor Number is',wf Code: http://www.py4e.com/code3/elev.py # إذا تأملنا هذا البرنامج بتمعن فسنرى البرنامج وما يمكن أن نسميه بالعالم الخارجي حيث يتفاعل الفصل الرابع عشر :البرمجة كائنية التوجه 238 البرنامج مع العالم الخارجي فيستقبل منه ويرسل إليه ،وفي قلب البرنامج نفسه لدينا شيفرة وبيانات إلنجاز املهمة التي صمم البرنامج لحلها. ولقد أخذت البرمجة كائنية التوجه هذا املفهوم وطورته أكثر فهي تقسم برنامجنا إلى نطاقات متعددة ،ولكل نطاق شيفراته وبياناته (كأنه برنامج مستقل) وتفاعالته املحددة جي ًدا مع العالم ً مجددا إلى تطبيق استخراج الرابط الخارجي والنطاقات األخرى ضمن البرنامج الرئيس ي .إذا نظرنا التشعبي حين استخدمنا مكتبة BeautifulSoup ً مثاال لبرنامج ُمنشأ عبر ربط الكائنات املختلفة ً سويا لتحقيق املهمة. سنرى بوضوح الشكل : 17البرنامج # To run this, download the BeautifulSoup zip file # http://www.py4e.com/code3/bs4.zip # and unzip it in the same directory as this file import urllib.request, urllib.parse, urllib.error from bs4 import BeautifulSoup import ssl # Ignore SSL certificate errors )(ctx = ssl.create_default_context ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE )' url = input('Enter - )(html = urllib.request.urlopen(url, context=ctx).read )'soup = BeautifulSoup(html, 'html.parser # Retrieve all of the anchor tags )'tags = soup('a for tag in tags: الفصل الرابع عشر :البرمجة كائنية التوجه 239 ))print(tag.get('href', None # Code: http://www.py4e.com/code3/urllinks.py لقد خزنا الرابط في متغير من نوع سلسلة نصية ثم مررناه إلى urllibلجلب البيانات من الويب ،حيث تستخدم مكتبة urllibمكتبة socketإلنشاء اتصال الشبكة الفعلي الستعادة البيانات .بعد ذلك نأخذ النص الناتج عن urllibونسلمه إلى BeautifulSoupلتحليله ،حيث تستعين BeautifulSoup بالكائن html.parserلتعيد ً كائنا. ً قاموسا من الوسوم ،ثم نمر على عناصر القاموس باستخدام حلقة ونستدعي التابع نخزن في tags () getلكل وسم لطباعة الخاصية .href بإمكاننا رسم مخطط لهذا البرنامج وكيف تعمل هذه الكائنات معا. ً الغرض من هذا املثال ليس معرفة كيف نستخرج رابطا من صفحة ويب بل رؤية كيف نبني شبكة كائنات متفاعلة وكيفية انسياب املعلومات بين تلك الكائنات إلنشاء البرنامج ،لعلك الحظت عندما استخدمت هذا البرنامج في فصل سابق من هذا الكتاب أمكنك فهم ماذا يقوم به بدون أن تدرك كيف كان ينسق البرنامج حركة البيانات بين الكائنات ،فما هي إال أسطر من الشيفرة التي تؤدي املطلوب. الشكل :18البرنامج كشبكة من الكائنات 5.14تقسيم املشكلة ً يتميز أسلوب البرمجة كائنية التوجه أنه بإمكانه إخفاء التعقيد ،فمثال عندما نحتاج ملعرفة كيف ً داخليا، نستخدم مكتبتي urllibو BeautifulSoupفنحن ال نحتاج ملعرفة كيف تعمل هذه املكتبات الفصل الرابع عشر :البرمجة كائنية التوجه 240 مما يسمح لنا بالتركيز على املشكلة الذي نريد حلها وتجاهل ما سواها. الشكل :19تجاهل التفصيل عند استخدام الكائن تعد القدرة على التركيز على جزء من البرنامج وتجاهل ما سواه ً مفيدا ً أيضا ملطوري الكائنات التي ً نستخدمها ،فمثال ال يحتاج املبرمجون الذين يطورون BeautifulSoupملعرفة أو لالهتمام كيف نحصل على صفحة HTMLأو ماهية الصفحات التي نريد قراءتها أو ما الذي نخطط لفعله مع البيانات التي نستخرجها من صفحة ويب. 6.14إنشاء كائن في لغة بايثون الكائن ببساطة هو جزء صغير من البرنامج يحتوي على بعض الشيفرات باإلضافة إلى بعض من بنى البيانات. اسما ً لنتذكر مفهوم التابع الذي يسمح لنا بتخزين بعض الشيفرة ويمنحها ً معينا ،ثم يمكننا استحضار تلك الشيفرة ً الحقا بكتابة اسم التابع فقط. الشكل :20تجاهل التفاصيل عند إنشاء الكائن قد يحوي الكائن العديد من التوابع تسمى ( )methodsإلى جانب البيانات التي تستخدمها هذه الفصل الرابع عشر :البرمجة كائنية التوجه 241 التوابع ،ونسمي عناصر البيانات التي هي جزء من الكائن بالخواص (.)properties نستخدم الكلمة املفتاحية classلنحدد البيانات والشيفرة التي سنستخدمها إلنشاء الكائنات حيث يأتي بعد الكلمة املفتاحية اسم الصنف يليها الشيفرة املتضمنة للخواص (البيانات) والتوابع (الشيفرة). class PartyAnimal: x=0 def party(self) : self.x = self.x + 1 )print("So far",self.x )(an = PartyAnimal )(an.party )(an.party )(an.party )PartyAnimal.party(an # Code: http://www.py4e.com/code3/party2.py هذا الكائن يحوي خاصية واحدة xوتابع واحد هو ،partyيحوي التابع على عامل خاص نطلق عليه .selfكما أن الكلمة املفتاحية defال تؤدي إلى تنفيذ شيفرة التابع كذلك فالكلمة املفتاحية classال تصنع ً كائنا ،فالصنف يمثل القالب الذي يتضمن البيانات والشيفرة التي سيتكون منها كل كائن من الشكل : 21صنف وكائنان الفصل الرابع عشر :البرمجة كائنية التوجه 242 نوع .PartyAnimalللتوضيح ،اعتبر الصنف كقالب صنع الكعك والكائنات املنشأة منه هي الكعك، فنحن ال نضع الزينة على القالب بل على الكعك ،وبإمكانك وضع زينة مختلفة على كل قطعة. لنتابع اآلن شرح البرنامج ونأتي للسطر التالي )(an = PartyAnimal نأمر هنا لغة بايثون ببناء كائن أو نموذج من الصنف PartyAnimalويبدو األمر كأنه استدعاء تابع للصنف نفسه. تبني لغة بايثون الكائن ببياناته وتوابعه ثم تعيده إلى املتغير ،anما سبق يشبه األمر التالي الذي كنا نستخدمه في الفصول السابقة: )(counts = dict حيث نأمر بايثون ببناء كائن باستخدام قالب القاموس ( dictالجاهز في بايثون) ونسنده إلى متغير .counts تذكر عندما نستخدم صنف PartyAnimalلبناء كائن فإن املتغير anيستخدم ليشير إلى ذلك الكائن ،ويحوي كل كائن أو نموذج من PartyAnimalاملتغير xوتابع يدعى .party نستدعي التابع partyفي هذا السطر )(an.party ً اصطالحا )selfيشير إلى الكائن بذاته من بين عند استدعاء التابع partyفإن العامل (الذي نسميه كائنات الصنف PartyAnimalوالذي تم استدعاء التابع عبره. في التابع partyنرى السطر: self.x = self.x + 1 يستخدم هذا السطر عامل النقطة التي تعني (استخدم xالتي تنتمي للكائن) وفي كل مرة تستدعى فيها التابع partyفإن قيمة xالداخلية تزداد بمقدار 1ثم تعرض النتيجة على الخرج. يمثل السطر التالي طريقة أخرى الستدعاء التابع partyعبر الكائن :an )PartyAnimal.party(an االختالف هنا أننا نستدعي الشيفرة من داخل الصنف نفسه ثم نمرر مؤشر الكائن anكمعامل (أي املعامل املسمى selfضمن التابع) ،وبإمكاننا التفكير أن an.partyهي اختصار للسطر أعاله. الفصل الرابع عشر :البرمجة كائنية التوجه 243 عندما ينفذ البرنامج فإنه سيعطي الخرج التالي: So far 1 So far 2 So far 3 So far 4 فالكائن ٌبني ثم استدعى التابع partyأربع مرات ،بحيث يزيد بمقدار 1ويطبع القيمة xاملوجودة في الكائن .an 7.14الصنف كنوع بيانات في لغة بايثون كل املتغيرات لها نوع محدد .استخدم التابع الجاهز dirملعرفة قدرات أي متغير ً وأيضا بإمكاننا استخدام typeو dirمع األصناف التي انشأناها class PartyAnimal: x=0 def party(self) : self.x = self.x + 1 )print("So far",self.x )(an = PartyAnimal ))print ("Type", type(an ))print ("Dir ", dir(an ))print ("Type", type(an.x ))print ("Type", type(an.party # Code: http://www.py4e.com/code3/party3.py عندما ينفذ البرنامج سينتج الخرج التالي: >'Type <class '__main__.PartyAnimal Dir ['__class__', '__delattr__', ... '__sizeof__', '__str__', '__subclasshook__', ]''__weakref__', 'party', 'x >'Type <class 'int الفصل الرابع عشر :البرمجة كائنية التوجه 244 >'Type <class 'method يمكنك القول إننا باستخدام الكلمة املفتاحية classصنعنا نوع بيانات جديد. يمكن باستخدام التابع dirرؤية كل من خواص العدد الصحيح xوالتابع partyفي الكائن. 8.14دورة حياة الكائن في األمثلة السابقة عرفنا صنف (أي قالب) واستخدمناه إلنشاء نموذج منه (كائن) ثم استخدمنا هذا الكائن. عندما ينتهي البرنامج ُتهمل كل املتغيرات .عادة ال نفكر ً كثيرا في عملية إنشاء وهدم املتغيرات ،لكن ً تعقيدا نحتاج التخاذ إجراءات معينة أثناء إنشاء الكائن ،وحذف األشياء عندما يصبح كائننا أكثر عند إهماله. إذا أردنا تبيان عمليات البناء والهدم نضيف توابع خاصة لكائنا. class PartyAnimal: x=0 def __init__(self): )'print('I am constructed def party(self) : self.x = self.x + 1 )print('So far',self.x def __del__(self): )print('I am destructed', self.x )(an = PartyAnimal )(an.party )(an.party an = 42 )print('an contains',an الفصل الرابع عشر :البرمجة كائنية التوجه 245 # Code: http://www.py4e.com/code3/party4.py عندما ينفذ البرنامج فإنه يعطي الخرج التالي: I am constructed So far 1 So far 2 I am destructed 2 an contains 42 عندما ٌتنشأ لغة بايثون الكائن فإنها تستدعي تابع __ __initلتعطينا فرصة لضبط القيم االبتدائية للكائن. عندما تصادف لغة بايثون السطرan = 42 : فإن بايثون تتخلص من الكائن عن طريق إعادة استخدام املتغير anلتخزين القيمة ،42وعند تدمير الكائن تستدعى شيفرة الهادم __.__del ال يمكننا حماية املتغيرات في الكائن من عملية الهدم ،كل ما هنالك أننا نقوم بالعمليات الضرورية قبل أن يختفي الكائن ً نهائيا. دائما عند تطوير الكائنات فمن الشائع ً تذكر ً جدا إضافة التابع الباني للكائن لضبط القيم االبتدائية لهً ، ونادرا ما نحتاج تابع الهادم للكائن. 9.14تعدد الكائنات حتى اآلن عرفنا ما هو الصنف وبنينا كائن وحيد واستخدمناه ثم تخلصنا منه. صنف واحد ،حيث تظهر القوة الحقيقية للبرمجة كائنية التوجه عندما نبني كائنات متعددة من ٍ نعطي قيم ابتدائية مختلفة لكل من الكائنات. هنا سنقوم بتمرير البيانات إلى الباني إلعطاء كل كائن قيمة ابتدائية مختلفة: class PartyAnimal: x=0 ' ' = name def __init__(self, nam): البرمجة كائنية التوجه:الفصل الرابع عشر 246 self.name = nam print(self.name,'constructed') def party(self) : self.x = self.x + 1 print(self.name,'party count',self.x) s = PartyAnimal('Sally') j = PartyAnimal('Jim') s.party() j.party() s.party() # Code: http://www.py4e.com/code3/party5.py الذي يشير إلى حالة العنصر وعوامل إضافية تمرر عبر الباني أثناءself تضم عوامل الباني العامل :إنشاء الكائن s = PartyAnimal('Sally') self للكائن عبرname ) إلى خاصيةnam( أثناء عملية اإلنشاء فإن السطر الثاني ينسخ العامل self.name = nam name وx تحوي نسخ مستقلة من قيمj وs إن خرج البرنامج يظهر أن كل من تلك الكائنات Sally constructed Jim constructed Sally party count 1 Jim party count 1 Sally party count 2 الفصل الرابع عشر :البرمجة كائنية التوجه 247 10.14الوراثة ُ تعد القدرة على إنشاء صنف جديد عبر توسيع صنف موجود ميزة أخرى للبرمجة كائنية التوجه، فعند توسيع الصنف ندعو الصنف األصلي بالصنف األب ( )parent classوالصنف الجديد بالصنف االبن ()child class فلننقل صنف PartyAnimalإلى ملف منفصل ،الستيراده في ملف جديد وتوسيعه كما يلي: from party import PartyAnimal class CricketFan(PartyAnimal): points = 0 def six(self): self.points = self.points + 6 )(self.party )print(self.name,"points",self.points )"s = PartyAnimal("Sally )(s.party )"j = CricketFan("Jim )(j.party )(j.six ))print(dir(j # Code: http://www.py4e.com/code3/party6.py نشير عند تعريف الصنف CricketFanإلى الصنف ،PartyAnimalهذا يعني أن كل من املتغيرات x والتوابع partyفي الصنف PartyAnimalستورث إلى الصنف ،CricketFanفعلى سبيل املثال استدعينا التابع partyمن صنف PartyAnimalفي تابع sixللصنف .CricketFan عند تنفيذ البرنامج ننشأ sو jككائنات مستقلة من الصنفين PartyAnimalوCricketFan الحظ أن الكائن jلديه قدرات إضافية تفوق الكائن s الفصل الرابع عشر :البرمجة كائنية التوجه 248 Sally constructed Sally party count 1 Jim constructed Jim party count 1 Jim party count 2 Jim points 6 ['__class__', '__delattr__', ... '__weakref__', ]''name', 'party', 'points', 'six', 'x في خرج التابع dirللكائن ( jذو الصنف )CricketFanنرى أن له خواص وتوابع من الصنف األب و ً أيضا الخواص والتوابع التي أضفناها عندما وسعنا الصنف إلنشاء .CricketFan 11.14ملخص هذه مقدمة مختصرة للبرمجة كائنية التوجه التي تركز بصورة أساسية على قواعد تعريف واستخدام الكائنات. لنراجع الشيفرة التي رأيناها في بداية الفصل ،اآلن لن تجد أدنى صعوبة في فهمها. )(stuff = list )'stuff.append('python )'stuff.append('chuck )(stuff.sort )]print (stuff[0 ))print (stuff.__getitem__(0 ))print (list.__getitem__(stuff,0 # Code: http://www.py4e.com/code3/party1.py ٌينش ئ في السطر األول كائن من الصنف ،listعندها تستدعي بايثون التابع الباني وهو ( __)__init ُ لضبط البيانات الداخلية التي سوف تستخدم لتخزين قائمة من البيانات. الحظ أننا لم نمرر أي عوامل إلى هذا الباني ،وعندما ينتهي الباني من عمله نستخدم املتغير stuff لإلشارة إلى الكائن الناتج من الصنف .list الفصل الرابع عشر :البرمجة كائنية التوجه 249 في السطرين الثاني والثالث نستدعي التابع appendإلضافة عنصر جديد إلى نهاية القائمة عبر تحديث خواص الكائن .stuffثم في السطر الرابع نستدعي تابع sortبال أي عوامل لترتيب بيانات الكائن. ً ً مختصرا نستخدم عندما نريد طباعة أول عنصر في القائمة األقواس املربعة [] والتي تعد بديال الستدعاء __ __getitemباستخدام ،stuffوهذا يكافئ استدعاء تابع __ __getitemعلى صنف List وتمرير كائن stuffكمعامل أول والفهرس التي نرغب بعرض محتواه كمعامل ثاني. نستدعي في نهاية البرنامج التابع الهادم (والذي يسمى __ )__delليتمكن الكائن من التعامل مع أي بيانات سائبة قبل هدم الكائن .stuffهذه هي أساسيات البرمجة كائنية التوجه وهناك تفاصيل ُ إضافية تتبع عند تطوير تطبيقات ضخمة أو مكتبات لكنها خارج نطاق هذا الفصل. 12.14فهرس املصطلحات • الخاصية ( :)attributeمتغير جزء من الصنف. • الصنف ( :)classقالب يستخدم لبناء كائن ،ويحدد الخواص والتوابع التي تشكل الكائن. • الصنف االبن ( :)child classصنف جديد ينشأ من توسيع الصنف األب ،ويرث جميع الخواص والتوابع من الصنف األب. • التابع الباني ( :)constructorتابع اختياري يسمى (__ )__initيستدعى لحظة بناء الكائن ويستخدم عادة لضبط القيم االبتدائية. • التابع الهادم ( :)destructorتابع اختياري يسمى (__ )__delيستدعى في اللحظة قبل إزالة الكائن ،نادر االستخدام. • الوراثة ( :)inheritanceعندما يتم إنشاء صنف جديد (االبن )childعند توسيع صنف موجود (أب )parentيحصل الصنف االبن على جميع الخواص والتوابع من الصنف األب باإلضافة لخواص وتوابع محددة له. • التابع ( :)methodتابع موجود في صنف والكائنات املبنية من الصنف ،وبعض املنهجيات ً في البرمجة كائنية التوجه تستخدم عبارة رسالة messageبدال من methodللتعبير عن هذا املفهوم. الفصل الرابع عشر :البرمجة كائنية التوجه 250 • الكائن ( :)objectنموذج يتم إنشاؤه من الصنف ،يحوي كل من الخواص والتوابع املعرفة ً في الصنف ،وبعض وثائق البرمجة كائنية التوجه تستخدم مصطلح instanceبدال من .object • الصنف األب ( :)parent classالصنف الذي تم توسيعه لصنع صنف ابن جديد ،يشارك الصنف األب كل الخواص والتوابع مع الصنف االبن. الفصل الخامس عشر استخدام قواعد البيانات ولغة SQL الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 252 15استخدام قواعد البيانات ولغة SQL 1.15ما هي قاعدة البيانات؟ إن قاعدة البيانات هي ملف منظم لتخزين البيانات ،وتكون معظم هذه القواعد منظمة بطريقة مشابهة للقواميس حيث تربط بين مفاتيح وقيم ،لكن االختالف الرئيس ي بينهما أن قاعدة البيانات موجودة على القرص الصلب (أو أي أداة تخزين دائمة أخرى) ،أي تحتفظ بالبيانات حتى بعد انتهاء البرنامج ،وبإمكانها تخزين بيانات أكثر من القواميس بسبب وجودها على وحدة تخزين دائمة ،بينما يكون حجم القاموس مرتبط بحجم ذاكرة الحاسوبٌ . صممت برمجيات قواعد البيانات بشكل يجعل سريعا ً ً جدا مهما ك َبر حجمها ً تماما كالقواميس ،وتحافظ هذه إدخال البيانات والوصول إليها ً البرمجيات على األداء السريع بإنشاء فهارس تز ً امنا مع إدخال بيانات جديدة سامحة للحاسوب َ بالوصول إلى ُمدخل معين بسرعة. توجد أنظمة مختلفة لقواعد البيانات تستخدم ألهداف متعددة ومنها Oracleو MySQL و Microsoft SQL Serverو PostgreSQLو . SQLite َّ ومضمن في بايثون ،كما سنركز في هذا الكتاب على SQLiteلكونه قاعدة بيانات شائعة االستخدام صممت بطريقة تسمح بتضمينها في التطبيقات املختلفة لتأمين دعم قواعد البيانات فيها .على سبيل ً داخليا كحال تطبيقات أخرى وموقعها املثال يستخدم متصفح Firefoxقاعدة بيانات SQLite http://sqlite.org/وهي مناسبة للتعامل مع مسائل التالعب بالبيانات كالتي نشهدها في مجال املعلوماتية مثل استكشاف ( )spideringموقع تويتر (آلية تستخدم في محركات البحث لالكتشاف والوصول إلى جميع صفحات الويب على شبكة االنترنت لفهرستها في هذا البرنامج ،يكتشف البرنامج قائمة أصدقاء حساب ما على تويتر ويستخدمه لكشف أصدقائهم وهكذا) الذي سنتحدث عنه في هذا الفصل. 2.15مفاهيم في قواعد البيانات للوهلة األولى ،تشبه قاعدة البيانات الجدول املليء بالحقول ،حيث أن بنى البيانات الرئيسية فيها هي: الجداول واألسطر واألعمدة .بينما يشار إليهم في قواعد البيانات العالئقية كـ :العالقة ((relation والصف ) (tupleوالسمة ) (attributeعلى الترتيب ،لذلك سنستخدم الكلمات الشائعة في هذا الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 253 الكتاب. الشكل :22قاعدة بيانات عالئقية 3.15متصفح قاعدة البيانات في SQLite سنركز في هذا الفصل على استخدام بايثون للتعامل مع البيانات في ملفات قاعدة بيانات ،SQLite يسهل برنامج يدعى متصفح قاعدة البيانات في SQLiteالعديد من العمليات وهو متاح ً مجانا على املوقع. http://sqlitebrowser.org/ بإمكانك إنشاء الجداول بسهولة بواسطة املتصفح وإدخال بيانات أو التعديل عليها أو إجراء استعالم بسيط حول البيانات املوجودة في تلك القاعدة ،أي أن متصفح قاعدة البيانات يشبه محرر النصوص عند التعامل مع امللفات النصية .فعندما تحتاج لتنفيذ عملية أو عدة عمليات على امللف النص ي ستفتحه باستخدام محرر النصوص وتجري التعديالت التي ترغب بها ،إال إن كان لديك العديد من التعديالت والعمليات لتجريها فستنش ئ برنامج بايثون يساعدك في تنفيذ هذا ،وهذا مشابه ملا يتعلق بقواعد البيانات حيث نجري عمليات بسيطة عبر مدير قاعدة البيانات بينما نفضل ً تعقيدا. بايثون للعمليات األكثر 4.15إنشاء جدول قاعدة بيانات تتطلب قواعد البيانات بنية محددة أكثر من قوائم وقواميس بايثون (تتيح SQLمرونة أكبر فيما يتعلق بنوع البيانات املخزنة ضمن عمود ما ،ولكن سنبقي أنماط البيانات التي سنستخدمها محددة بحيث تنطبق املبادئ بشكل مشابه على أنظمة قواعد بيانات أخرى مثل ، MySQLيجب علينا تحديد ً أسماء أعمدة الجدول قبل إنشائه إضافة إلى نوع البيانات التي ننوي تخزينها في تلك األعمدة ليتمكن البرنامج من اختيار الطريقة األكثر فعالية لتخزين املعلومة والبحث عنها ،كما يمكنك االطالع على أنماط البيانات التي تدعمها SQLiteعبر الرابط اآلتي. http://www.sqlite.org/datatypes.html : الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 254 ً ً ً أمرا شاقا في بداية األمر ولكن النتيجة تكون الوصول السريع قد يبدو لك تحديد بنية بياناتك مسبقا إلى تلك البيانات بالرغم من احتواء قاعدة بياناتك على حجوم كبيرة من املعلومات. إلنشاء ملف قاعدة بيانات مع جدول اسمه Tracksذو عمودين بلغة بايثون نكتب الشيفرة التالية: import sqlite3 )'conn = sqlite3.connect('music.sqlite )(cur = conn.cursor )'cur.execute('DROP TABLE IF EXISTS Tracks )')cur.execute('CREATE TABLE Tracks (title TEXT, plays INTEGER )(conn.close # Code: http://www.py4e.com/code3/db1.py ً تنش ئ تعليمة connectاتصاال مع قاعدة البيانات املوجودة ضمن امللف music.sqliteفي املجلد ً الحاليٌ ، مسبقا وسبب تسمية هذه العملية باالتصال فهو بسبب وسينشأ امللف في حال عدم وجوده احتمال وجود قاعدة البيانات على خادم قواعد بيانات منفصل وهو الخادم الذي شغلنا تطبيقنا عن طريقه ،أما في أمثلتنا القادمة فستكون قاعدة البيانات ملف محلي موجود بنفس مجلد برنامج بايثون الذي سننفذه. يشبه املؤشر )َ (cursor معرف امللف ( )file handleحيث نستخدمه لتنفيذ عمليات معينة على قاعدة البيانات ،استدعاء التابع )( cursorيشبه من حيث املبدأ استدعاء التابع )( openعند التعامل مع امللفات النصية. الشكل :23مؤشر قاعدة البيانات الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 255 نستطيع بدء تنفيذ األوامر على محتويات قاعدة البيانات مستخدمين التابع )( excuteبمجرد حصولنا على املؤشرُ ،وي َّ عبر عن تلك األوامر بلغة خاصة موحدة من قبل مجموعة من شركات قواعد ً اختصارا SQL البيانات ،األمر الذي يتيح لنا تعلم لغة واحدة وتسمى لغة االستعالم البنيوية أو ويمكنك االطالع على معلومات عنها عبر الرابط. http://en.wikipedia.org/wiki/SQL : نفذنا تعليمتين من تعليمات قواعد البيانات في مثالنا السابق حيث سنكتب الكلمات املفتاحية لهذه اللغة بأحرف كبيرة واألجزاء التي سنضيفها على األوامر املستخدمة بأحرف صغيرة (كأسماء الجداول واألعمدة). ً مسبقا مما يسمح لنا تحذف التعليمة األولى الجدول Tracksمن قاعدة البيانات إذا كان موجود ً بإنشاء الجدول مجددا في كل مرة تشغيل بدون حدوث أخطاء ،مع مالحظة أن تعليمة DROP TABLE تحذف الجدول مع جميع محتوياته من قاعدة البيانات (ال يمكن التراجع عن العملية). )'cur.execute('DROP TABLE IF EXISTS Tracks بينما تنش ئ التعليمة الثانية جدول اسمه Tracksذو عمود باسم titleمحتوياته نصية وعمود باسم playمحتوياته أعداد صحيحة. )')cur.execute('CREATE TABLE Tracks (title TEXT, plays INTEGER نستطيع بعد إنشاء الجدول إضافة بعض البيانات إليه باستخدام عملية INSERTوهذا بعد إنشاء اتصال جديد مع قاعدة البيانات والحصول على املؤشر لنتمكن من تنفيذ أوامر SQLباستخدام ذلك املؤشر. ً ً جديدا بتحديد الحقول التي نريد سطرا يشير األمر INSERTإلى الجدول الذي نستخدمه ثم يعرف تضمينها ) (title, playsمتبوعة بالقيم التي نريد إدخالها إلى السطر الجديد ،كما نكتب القيم ستدخل ً كعالمات استفهام (? )?,لنبين أن تلك القيم الفعلية ُ الحقا كصف ) ('My way', 15في املعامل الثاني للتابع )( execute import sqlite3 )'conn = sqlite3.connect('music.sqlite )(cur = conn.cursor ))cur.execute('INSERT INTO Tracks (title, plays) VALUES (?, ?)', ('Thunderstruck', 20 ))cur.execute('INSERT INTO Tracks (title, plays) VALUES (?, ?)', ('My Way', 15 الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 256 )(conn.commit )'print('Tracks: )'cur.execute('SELECT title, plays FROM Tracks for row in cur: )print(row )'cur.execute('DELETE FROM Tracks WHERE plays < 100 )(conn.commit )(cur.close # Code: http://www.py4e.com/code3/db2.py الشكل : 24األسطر في الجدول ً نضيف بداية سطرين إلى الجدول باستخدام INSERTثم نستخدم )( commitلكتابة البيانات ضمن قاعدة البيانات ،ثم نستخدم األمر SELECTالستدعاء الصفوف التي أدخلناها ً سابقا إلى الجدول ونحدد فيه األعمدة التي نريد ) (title, playsكما نحدد أي جدول نريد استخراج البيانات منه ،وبعد تنفيذ SELECTيصبح بإمكاننا املرور على محتويات املؤشر باستخدام حلقة ،forمع العلم أن املؤشر ال يقرأ جميع محتويات قاعدة البيانات عند استخدام تعليمة SELECTوذلك لزيادة الكفاءة حيث يقرأ البيانات التي نحتاجها وفق تكرارات حلقة forويكون خرج البرنامج كما يأتي: Tracks: )('Thunderstruck', 20 )('My Way', 15 تستخرج الحلقة سطرين عبارة عن صفوف بحيث تكون القيمة األولى هي العنوان titleوالقيمة الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 257 الثانية عبارة عن عدد مرات تشغيل األغنية .plays ً مالحظة :قد تجد سالسل نصية تبدأ بحرف ' 'uفي كتب أخرى أو على اإلنترنت حيث كان هذا دليال في إصدار بايثون 2على كون السالسل مرمزة بترميز Unicodeأي سالسل تتضمن مجموعة املحارف غير الالتينية لكن في بايثون اإلصدار 3جميع السالسل هي Unicodeافتر ً اضيا. ننفذ في نهاية البرنامج أمر الحذف DELETEإلزالة الصفوف التي أنشأناها لنتمكن من إعادة تشغيل البرنامج عدة مرات ،كما يظهر هذه األمر استخدام عبارة WHEREوالتي تسمح لنا بتحديد الصفوف التي ستنفذ عليها تعليمة الحذف ،ولكن صدف في هذا املثال أن طابق معيار التحديد جميع صفوف قاعدة البيانات إلخالء الجدول وتشغيل البرنامج بشكل متكرر ،ونستدعي )( commitبعد تنفيذ DELETEلتأكيد حذف البيانات من قاعدة البيانات. ّ البنيوية SQL 5.15ملخص عن لغة االستعالم استخدمنا لحد اآلن لغة SQLفي برامج بايثون السابقة وذكرنا العديد من أوامرها األساسية ،لذا سنركز عليها بشكل أكبر في هذا القسم وسنقدم نظرة عامة على قواعد هذه اللغة ،وباعتبار وجود شركات عدة مختصة بقواعد البيانات فقد ُحددت SQLكلغة معيارية لنتمكن من التواصل باستخدام مختلف أنظمة قواعد البيانات التابعة لتلك الشركات. إن قواعد البيانات العالئقية مكونة من جداول وسطور وأعمدة حيث تكون األعمدة ذات نوع معين نص ي أو رقمي أو تواريخ وعند إنشاء جدول نصرح بأسماء وأنواع األعمدة مثال: )CREATE TABLE Tracks (title TEXT, plays INTEGER وإلضافة سطر جديد ضمن الجدول نستخدم األمر INSERTفي لغة SQLمثال: )INSERT INTO Tracks (title, plays) VALUES ('My Way', 15 تحدد هذه التعليمة اسم الجدول ومجموعة من الحقول (األعمدة) التي تود إضافتها للسطر الجديد، كما تضيف الكلمة املفتاحية VALUESمجموعة من القيم املوافقة لكل حقل. ُيستخدم األمر SELECTالستدعاء السطور واألعمدة التي نحتاجها من قاعدة البيانات أما عبارة WHEREتظهر السطور املطلوبة ،كما يمكن استخدام عبارة ORDER BYعند الحاجة للتحكم بترتيب الصفوف املستدعاة مثال: 'SELECT * FROM Tracks WHERE title = 'My Way الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 258 يدل استخدام رمز النجمة * على استدعاء جميع أعمدة لكل األسطر التي تحقق شرط عبارة ً ،WHEREوعلى عكس بايثون نستخدم هنا إشارة يساوي واحدة في هذا الشرط بدال من إشارتين، بينما تكون بقية العمليات املنطقية املتاحة مع WHEREهي نفسها < ،!= ،<= ،>= ،> ،إضافة إلى األقواس واستخدام ANDو.OR ً اعتمادا على أحد الحقول مثال: تستطيع تحديد ترتيب الصفوف SELECT title,plays FROM Tracks ORDER BY title ولحذف سطر ما تحتاج الستخدام تعليمة DELETEوعبارة WHEREلتحديد أي السطور تريد حذفها مثال: 'DELETE FROM Tracks WHERE title = 'My Way يمكن ً أيضا تحديث قيمة أحد األعمدة أو كلها ضمن سطر أو أكثر في جدول ما باستخدام تعليمة UPDATEكما يأتي: 'UPDATE Tracks SET plays = 16 WHERE title = 'My Way ٌتحدد هذه التعليمة جدول معين ثم مجموعة القيم املطلوب تغييرها بعد تعليمة SETأما عبارة ُ WHEREفلتحديد الصفوف املراد تحديثها ،وتعدل تعليمة UPDATEكافة السطور التي توافق شرط WHEREأو جميع سطور الجدول في حال عدم استخدام .WHERE تسمح تعليمات SQLاألربعة هذه ( INSERTو SELECTو UPDATEو (DELETEبتنفيذ عمليات إنشاء وتعديل البيانات. 6.15استكشاف تويترباستخدام قواعد البيانات سنكتب في هذا القسم برنامج استكشاف أو تعقب يمر على حسابات تويتر ويسجل بياناتهم ضمن قاعدة بيانات (كن ً حذرا عند تشغيل هذا البرنامج كي ال تتسبب في إلغاء وصولك إلى تويتر إن استخرجت كم كبير من البيانات أو استخدمت البرنامج ً كثيرا). إحدى مشاكل هذه البرامج احتياجنا إلعادة تشغيله عدة مرات دون فقد البيانات التي قد استخرجتها وإعادة استدعائها مرة أخرى من البداية لذلك نود تخزين تلك البيانات ليتمكن برنامجنا من إكمال العمل من نقطة توقفه. الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 259 سنبدأ باستخراج قائمة أصدقاء حساب تويتر معين ومنشوراته (تغريداته) ثم سنمر باستخدام ً الحلقات على قائمة األصدقاء لنضيفهم إلى قاعدة بيانات الستدعائهم مستقبال ،بعد ذلك نأخذ اسم حساب أحد األصدقاء لنستدعي قائمة أصدقائه ونضيف أسماء األصدقاء التي لم ترد في قاعدة البيانات ً سابقا ونتابع هذه العملية للصديق التالي وهكذا ،ثم نحسب عدد مرات تكرار اسم أحد األصدقاء كتعبير عن شعبيته ،ويصبح بإمكاننا بعد انتهاء هذه العملية إعادة تشغيل البرنامج مر ًارا ً معقدا بعض الش يء حيث يعتمد على البرامج املكتوبة في تمارين وتكر ًارا ،كما يعتبر هذا البرنامج سابقة والتي تستخدم واجهة برمجية APIلتويتر ،وتكون الشيفرة املصدرية له كاآلتي: from urllib.request import urlopen import urllib.error import twurl import json import sqlite3 import ssl 'TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json )'conn = sqlite3.connect('spider.sqlite )(cur = conn.cursor ' ' ' (cur.execute CREATE TABLE IF NOT EXISTS Twitter )' ' ')(name TEXT, retrieved INTEGER, friends INTEGER # Ignore SSL certificate errors )(ctx = ssl.create_default_context ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 260 while True: acct = input('Enter a Twitter account, or quit: ') if (acct == quit): break if (len(acct) < 1) : cur.execute('SELECT name FROM Twitter WHERE retrieved = 0 LIMIT 1') try: acct = cur.fetchone()[0] except: print('No unretrieved Twitter accounts found') continue url = twurl.augment(TWITTER_URL, {'screen_name': acct, 'count': '20'} ) print('Retrieving', url) connection = urlopen(url, context=ctx) data = connection.read().decode() headers = dict(connection.getheaders()) print('Remaining', headers['x-rate-limit-remaining']) js = json.loads(data) # Debugging # print json.dumps(js, indent=4) cur.execute('UPDATE Twitter SET retrieved=1 WHERE name = ? ', (acct, )) countnew = 0 countold = 0 for u in js['users']: friend = u['screen_name'] الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 261 )print(friend cur.execute('SELECT friends FROM Twitter WHERE name = ? LIMIT 1', )) (friend, try: ]count = cur.fetchone()[0 cur.execute('UPDATE Twitter SET friends = ? WHERE name ))=?', (count+1,friend countold = countold + 1 except: cur.execute(''' INSERT INTO Twitter (name, retrieved, friends) VALUES )) (?, 0, 1) ''', (friend, countnew = countnew + 1 )print('New accounts=', countnew, 'revisited=', countold )(conn.commit )(cur.close # Code: http://www.py4e.com/code3/twspider.py إن قاعدة بياناتنا مخزنة في امللف spider.sqliteوتحتوي جدول واحد اسمه ،Twitterحيث كل سطر في هذا الجدول يحوي عمود باسم nameالسم الحساب وعمود باسم retrievedيدل إن كنا قد استخرجنا قائمة أصدقائه وعمود باسم friendsيمثل عدد مرات إضافته كصديق. سنطلب من املستخدم في الحلقة الرئيسية للبرنامج إدخال حساب تويتر أو كتابة كلمة quitللخروج من البرنامج ،فإن أدخل حساب تويتر سنستخرج قائمة أصدقائه ونخزنها في قاعدة البيانات في حال ً ً مسبقا فنزيد بمقدار 1خانة friendsفي السطر مسبقا ،وإن كان اسم الصديق موجود عدم وجودها املخصص في قاعدة البيانات ،وفي حال ضغط املستخدم مفتاح - enterبدون كتابة أي ش يء -نبدأ ً مسبقا -لنضيفهم إلى قاعدة باستخراج قائمة أصدقاء الحساب التالي -من القائمة التي استخرجناها البيانات أو نحدث بياناتهم ونزيد عداد أصدقائهم (أي الخانة ،)friendsوبمجرد االنتهاء من عملية االستخراج نمر على كامل عناصر القاموس usersفي شيفرة JSONاملعادة لنستخرج اسم الحساب الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 262 (املخزن في املتغير )screen_nameلكل مستخدم ،ثم نستخدم تعليمة SELECTلنتحقق فيما إذا كان ً االسم ً مخزنا في قاعدة البيانات وإن كان ٌمسجال نستعيد عداد األصدقاء ونحدث قيمته. countnew = 0 countold = 0 for u in js['users'] : ]'friend = u['screen_name )print(friend cur.execute('SELECT friends FROM Twitter WHERE name = ? LIMIT 1', ) ) (friend, try: ]count = cur.fetchone()[0 cur.execute('UPDATE Twitter SET friends = ? WHERE name = ? ', ) )(count+1,friend countold = countold + 1 except: cur.execute('INSERT INTO Twitter (name, retrieved, friends) VALUES ( ?, ) ) 0, 1 ) ', ( friend, countnew = countnew + 1 )print('New accounts'=,countnew, 'revisited=',countold )(conn.commit ويجب أن نستعيد السطور بمجرد تنفيذ تعليمة SELECTباستخدام حلقة forولكن من األفضل كوننا سنستعيد سطر واحد ( )LIMIT 1استخدام التابع )( fetchoneلجلب السطر األول والوحيد الناتج عن األمر ،SELECTوبما أن هذا التابع يعيد السطر كصف (بالرغم من وجود خانة واحدة) نأخذ أول قيمة من الصف ] [0لنحصل على قيمة عداد األصدقاء الحالي ونضعها في املتغير ،count وفي حال نجاح هذه العملية نستعمل األمر Updateمع عبارة WHEREلزيادة 1إلى قيمة عامود عداد األصدقاء friendsفي السطر املوافق لحساب الصديق املطلوب ،مع مالحظة وجود عنصرين نائبين (عالمات االستفهام) في شيفرة SQLحيث املعامل الثاني للتابع )( executeهو صف ذو عنصرين الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 263 يحتوي القيم البديلة لعالمات االستفهام. ً فغالبا السبب هو عدم تطابق أي سجل مع العبارة WHERE إن حدث فشل في تنفيذ تعليمات try ?= nameضمن تعليمة SELECTلذلك نستخدم ضمن تعليمة exceptتعليمة INSERTإلضافة االسم الجديد screen_nameإلى الجدول مع وضع قيمة 0في خانة retrivedلتشير إلى عدم استدعاء االسم بعد ثم نسند قيمة 1إلى خانة عداد األصدقاء. كخالصة عند تشغيل البرنامج للمرة األولى ندخل اسم حساب تويتر ،فيعمل كاآلتي: Enter a Twitter account, or quit: drchuck Retrieving http://api.twitter.com/1.1/friends ... New accounts= 20 revisited= 0 Enter a Twitter account, or quit: quit وباعتبارها املرة األولى لتشغيل البرنامج تكون قاعدة البيانات فارغة وننشئها ضمن امللف spider.sqliteمع إضافة جدول باسم ،Twitterثم نستخرج بعض أسماء األصدقاء ونضيفهم إلى قاعدة البيانات ،ولربما ترغب بكتابة تعليمات تظهر لك مضمون امللف بعد تنفيذ ما سبق: import sqlite3 )'conn = sqlite3.connect('spider.sqlite )(cur = conn.cursor )'cur.execute('SELECT * FROM Twitter count = 0 for row in cur: )print(row count = count + 1 )' print(count, 'rows. )(cur.close # Code: http://www.py4e.com/code3/twdump.py الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 264 ببساطة يفتح هذا البرنامج قاعدة البيانات ويحدد جميع األعمدة لكل األسطر ضمن جدول ،Twitter ثم يمر على كل سطر ويعرضه ،ويكون خرجه عند تنفيذ أول عملية استكشاف كما يأتي: )('opencontent', 0, 1 )('lhawthorn', 0, 1 )('steve_coppin', 0, 1 )('davidkocher', 0, 1 )('hrheingold', 0, 1 ... 20 rows. لكل نالحظ وجود سطر واحد لكل اسم screen_nameلم نستخرج بياناته حيث يوجد صديق واحد ٍ منهم ضمن قاعدة البيانات ،حيث تعكس هذه القاعدة عملية استخراج أصدقاء حساب تويتر معين للمرة األولى ،كما باستطاعتنا إعادة تشغيل البرنامج لنستخرج أصدقاء الحساب التالي ،وذلك عن ً طريق الضغط على مفتاح enterبدال من إدخال اسم حساب جديد كما يأتي: Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends ... New accounts= 18 revisited= 2 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends ... New accounts= 17 revisited= 3 Enter a Twitter account, or quit: quit وتكون الشيفرة البرمجية املنفذة هي : if (len(acct) < 1) : cur.execute('SELECT name FROM Twitter WHERE )'retrieved = 0 LIMIT 1 try: ]acct = cur.fetchone()[0 الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 265 except: )'print('No unretrieved twitter accounts found continue ثم نستخدم األمر SELECTالستخراج اسم املستخدم األول ) (LIMT 1صاحب القيمة الصفرية في عامود ،retrivedكما نستخدم العبارة ] fetchone()[0ضمن كتلة try/exceptالستخراج االسم screen_nameمن البيانات املستعادة أو العودة للمرور على بقية املستخدمين ،وفي حال نجحنا باستدعاء االسم لحساب غير مكتشف فنستخرج بياناته كما يلي: )}'url=twurl.augment(TWITTER_URL,{ 'screen_name': acct, 'count': '20 )print('Retrieving', url )connection = urllib.urlopen(url )(data = connection.read )js = json.loads(data )) cur.execute('UPDATE Twitter SET retrieved=1 WHERE name = ? ',(acct, نستخدم تعليمة UPDATEبمجرد نجاح العملية السابقة ،وذلك لتغيير قيمة العمود retrievedإلى الواحد لإلشارة إلى انتهاء عملية استخراج قائمة أصدقاء املستخدم لعدم استخراج نفس البيانات مر ًارا وتكر ًارا والسماح لنا بالتقدم عبر شبكة األصدقاء في تويتر. عند تشغيل البرنامج والضغط على مفتاح enterمرتين الستخراج أصدقاء الصديق نحصل على الخرج اآلتي: )('opencontent', 1, 1 )('lhawthorn', 1, 1 )('steve_coppin', 0, 1 )('davidkocher', 0, 1 )('hrheingold', 0, 1 ... الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 266 )('cnxorg', 0, 2 )('knoop', 0, 1 )('kthanos', 0, 2 )('LectureTools', 0, 1 ... 55 rows. كما نرى فقد وثقنا زيارة الحسابين lhawthornو opencontentونالحظ وجود متابعين لكل من الحسابين cnxorgو ،kthanosوبما أننا استخرجنا قائمة أصدقاء ثالثة أشخاص حتى اآلن وهم سطر من األصدقاء drchuckو opencontentو lhawthornفإن جدولنا األن يحتوي على 55 ٍ الستخراج بياناتهم ،وفي كل مرة تشغيل سيختار البرنامج الحساب التالي غير املزار بعد ضغط enter (على سبيل املثال الحساب التالي الواجب معالجته هو )steve_coppinثم نستخرج قائمة األصدقاء لهذا الحساب ونضيفهم لنهاية قاعدة البيانات أو نحدث عداد أصدقائهم إن كانوا موجودين ضمن ً الجدول مسبقا ،وباعتبار أن بيانات البرنامج مخزنة على قرص في قاعدة بيانات فيمكن إيقاف عملية االكتشاف ً مؤقتا وإكمالها بعدد املرات الذي نحتاجه دون فقد البيانات. 7.15نمذجة البيانات تكمن قوة قاعدة البيانات العالئقية الحقيقية في إمكانية إنشاء عدة جداول وربطها ببعضها البعض، وتدعى عملية تقسيم البيانات إلى عدد من الجداول وإنشاء روابط بينها بنمذجة البيانات ( data ،)modelingويدعى املخطط الذي يظهر الجداول والعالقات بينها بنموذج البيانات. تتطلب عملية نمذجة البيانات مهارات وخبرة كبيرة ً نسبيا لذلك سنتطرق إلى أساسيات نمذجة قواعد البيانات العالئقية في هذا القسم من الفصل ،وللحصول على مزيد من املعلومات حول هذا املوضوع بإمكانك زيارة الرابط اآلتي. http://en.wikipedia.org/wiki/Relational_model : فلنفترض أننا أردنا إنشاء قائمة تبين جميع عالقات األصدقاء ببعضهم البعض في البرنامج السابق ً بدال من إحصاء أصدقاء كل شخص فحسب بهدف الحصول على قائمة جميع األشخاص املتابعين لحساب تويتر معين ،وبما أن كل حساب قد يكون ُمتابع من عدة حسابات أخرى فال نستطيع االكتفاء بإضافة عمود واحد إلى جدول ،Twitterلذا ننش ئ جدول جديد منفصل لنحدد طرفي الصداقة، الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 267 ونوضح في الشيفرة التالية طريقة التنفيذ: )CREATE TABLE Pals (from_friend TEXT, to_friend TEXT وفي كل مرة نضيف شخص ٌيتابعه drchuckنضيف سطر كالتالي: )'INSERT INTO Pals (from_friend,to_friend) VALUES ('drchuck', 'lhawthorn وبما أننا سنتعامل مع 20صديق من أصدقاء حساب تويتر الخاص بـ " " drchuckأي سنضيف 20 مرة اسم " " drchuckباعتباره املعامل األول مما يعني إعادة ذكر اسم الحساب عدة مرات في قاعدة البيانات ،ينتهك هذا التكرار أهم معايير قواعد البيانات والذي ينص على أال نكرر سلسلة نصية نفسها أكثر من مرة ،فإن احتجنا تلك السلسلة أكثر من مرة استبدلناها برقم ،حيث ً عمليا تشغل ً حجما أكبر من األرقام على قرص التخزين وفي ذاكرة الحاسوب وتتطلب زمن السالسل النصية معالجة أكبر في عمليات املقارنة والترتيب ،لكن قد يكون زمن املعالجة ومساحة التخزين غير مهمين في حال وجود بضعة مئات فقط من املدخالت في قاعدة البيانات ،أما إذا كان لدينا مليون شخص في قاعدة البيانات مع احتمال وجود رابط مع 100مليون صديق فتكون لسرعة عملية البحث في البيانات أهمية كبرى. ً سنخزن حسابات تويتر املستخرجة في جدول اسمه Peopleبدال من Twitterاملستخدم في املثال السابق ،ويحتوي هذا الجدول على عمود إضافي لتخزين املفتاح الرقمي املرتبط بالسطر الخاص ً تلقائيا ألي بحساب تويتر محدد ،مع األخذ بعين االعتبار أن SQLiteتملك ميزة إضافة قيمة املفتاح سطر ندخله للجدول باستخدام عمود ذي نوع بيانات مخصص (.)INTEGER PRIMARY KEY ننش ئ جدول Peopleمع عمود إضافي يسمى idكما يأتي: CREATE TABLE People )(id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER ونالحظ أننا لم نعد نحتفظ بعداد األصدقاء في كل سطر ضمن جدول ،Peopleوعند تحديد نوع العمود idكـ ( )INTEGER PRIMARY KEYفهذا يعني أننا نرغب في أن تسند SQLiteرقم فريد لكل ً تلقائيا ،كما أضفنا الكلمة املفتاحية UNIQUEلإلشارة إلى عدم سماحنا بإدخال سطر ندخله ً سطرين بنفس القيمة للخانة ،nameوبدال من إنشاء جدول Palsكما فعلنا أعاله سننش ئ جدول يدعى Followsذي عمودين كالهما من نوع عدد صحيح وسندعوهما from_idو to_idونركز على كون كل زوج من هاتين الخانتين فريد في الجدول (أي ال نستطيع تكرار السطر) في قاعدة البيانات. الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 268 CREATE TABLE Follows ) )(from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id نحدد عند إضافة عبارة UNIQUEللجداول مجموعة قواعد نطلب من قاعدة البيانات تنفيذها أثناء إدخالنا السجالت ،وغرضنا من وضع هذه القواعد هو جعل برنامجنا أسهل ومريح أكثر كما سنرى ً الحقا فهذه القواعد تمنعنا من ارتكاب األخطاء وتسهل كتابة جزء من برنامجنا ،وباختصار ً ً شخصا آخر نموذجا للعالقة بين األشخاص عندما يتابع أحدهم فإن إنشاء جدول Followsيمثل وذلك من خالل زوج من األرقام التي تشير إلى وجود عالقة بين هؤالء األشخاص واتجاه هذه العالقة. 8.15برمجة قاعدة البيانات ذات الجداول املتعددة سنعدل على برنامج اكتشاف تويتر بحيث يحوي جدولين للمفاتيح األساسية وعالقات املفاتيح كما وضحنا أعاله ،ويكون البرنامج كما يأتي: الشكل : 25العالقات بين الجداول import urllib.request, urllib.parse, urllib.error import twurl import json SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 269 import sqlite3 import ssl TWITTER_URL = 'https://api.twitter.com/1.1/friends/list.json' conn = sqlite3.connect('friends.sqlite') cur = conn.cursor() cur.execute('''CREATE TABLE IF NOT EXISTS People (id INTEGER PRIMARY KEY, name TEXT UNIQUE, retrieved INTEGER)''') cur.execute('''CREATE TABLE IF NOT EXISTS Follows (from_id INTEGER, to_id INTEGER, UNIQUE(from_id, to_id))''') # Ignore SSL certificate errors ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE while True: acct = input('Enter a Twitter account, or quit: ') if (acct == 'quit'): break if (len(acct) < 1): cur.execute('SELECT id, name FROM People WHERE retrieved=0 LIMIT 1') try: (id, acct) = cur.fetchone() except: SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 270 print('No unretrieved Twitter accounts found') continue else: cur.execute('SELECT id FROM People WHERE name = ? LIMIT 1', (acct, )) try: id = cur.fetchone()[0] except: cur.execute('''INSERT OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', (acct, )) conn.commit() if cur.rowcount != 1: print('Error inserting account:', acct) continue id = cur.lastrowid url = twurl.augment(TWITTER_URL, {'screen_name': acct, 'count': '100'}) print('Retrieving account', acct) try: connection = urllib.request.urlopen(url, context=ctx) except Exception as err: print('Failed to Retrieve', err) break data = connection.read().decode() headers = dict(connection.getheaders()) SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 271 print('Remaining', headers['x-rate-limit-remaining']) try: js = json.loads(data) except: print('Unable to parse json') print(data) break # Debugging # print(json.dumps(js, indent=4)) if 'users' not in js: print('Incorrect JSON received') print(json.dumps(js, indent=4)) continue cur.execute('UPDATE People SET retrieved=1 WHERE name = ?', (acct, )) countnew = 0 countold = 0 for u in js['users']: friend = u['screen_name'] print(friend) SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 272 cur.execute('SELECT id FROM People WHERE name = ? LIMIT 1', (friend, )) try: friend_id = cur.fetchone()[0] countold = countold + 1 except: cur.execute('''INSERT OR IGNORE INTO People (name, retrieved) VALUES (?, 0)''', (friend, )) conn.commit() if cur.rowcount != 1: print('Error inserting account:', friend) continue friend_id = cur.lastrowid countnew = countnew + 1 cur.execute('''INSERT OR IGNORE INTO Follows (from_id, to_id) VALUES (?, ?)''', (id, friend_id)) print('New accounts=', countnew, ' revisited=', countold) print('Remaining', headers['x-rate-limit-remaining']) conn.commit() cur.close() # Code: http://www.py4e.com/code3/twfriends.py يبدو البرنامج وكأنه معقد بعض الش يء إال أنه يوضح األنماط البرمجية التي نحتاج الستخدامها عند :االعتماد على مفاتيح رقمية لربط الجداول حيث تكون تلك األنماط كما يأتي الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 273 . ١إنشاء جداول ذات مفاتيح أساسية ( )primary keysوقيود. ً . ٢عند وجود مفتاح منطقي ( )logical keyلشخص ما (مثال اسم الحساب) واحتجنا ملعرفة قيمة idالخاصة به ،مع األخذ بعين االعتبار وجود الشخص في جدول peopleمن عدمه فسنحتاج إما للبحث عن الشخص في جدول peopleالستخراج قيمة idالخاصة به أو إضافته إلى الجدول والحصول على idالسطر املضاف الجديد. . ٣إدخال السطر الذي يحدد عالقة الصداقة .follows وسنغطي كل من هذه النقاط على حدة في الفقرات التالية. 1.8.15القيود في قواعد البيانات يمكننا في مرحلة تصميم الجداول تطبيق مجموعة قواعد على قاعدة البيانات ،لتجنب ارتكاب األخطاء أو إدخال بيانات غير صحيحة ،ويتم هذا باآللية التالية: cur.execute('''CREATE TABLE IF NOT EXISTS People (id INTEGER PRIMARY )''')KEY, name TEXT UNIQUE, retrieved INTEGER cur.execute('''CREATE TABLE IF NOT EXISTS Follows (from_id INTEGER, )'''))to_id INTEGER, UNIQUE(from_id, to_id نشترط أن كل من عمود االسم nameفي جدول peopleوزوج الرقمين ) (from_id, to_idفي كل سطر من جدول followsفريد (غير مكرر) حيث تمنعنا هذه القيود أو القواعد من ارتكاب األخطاء كإضافة نفس عالقة الصداقة في مثالنا السابق عدة مرات ،ونستطيع االستفادة منها من خالل التعليمات اآلتية: ( cur.execute('''INSERT OR IGNORE INTO People (name, retrieved) VALUES ( ?, 0)''', ) ) friend, أضفنا عبارة OR IGNOREإلى تعليمة INSERTليتم تجاهل التعليمة INSERTإن خالفت قاعدة استخدام اسم فريد غير مكرر ،أي أننا نستخدم تلك القواعد كشبكة أمان لنتأكد من عدم ارتكاب أخطاء بدون قصد ،وبشكل مشابه نستخدم التعليمات التالية للتأكد من عدم إضافة نفس العالقة لجدول : follows cur.execute('''INSERT OR IGNORE INTO Follows (from_id, to_id) VALUES (?, ?)''', ) )(id, friend_id الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 274 أي ببساطة طلبنا من قاعدة البيانات تجاهل تعليمة اإلدخال إن كانت تنتهك قاعدة عدم التكرار في أسطر الجدول .Follows 2.8.15استعادة أو إضافة سجل في قاعدة البيانات عندما نطلب من املستخدم إدخال اسم حساب تويتر معين ونجده ضمن قاعدة البيانات علينا البحث عن قيمة معرفه ،idبينما إن لم يكن موجود في جدول peopleفعلينا إضافة السجل والحصول على قيمة املعرف في السطر املضاف ،وهذا أسلوب شائع ً جدا ٌونفذ مرتين في البرنامج السابق أعاله ،حيث يظهر البرنامج كيفية البحث عن معرف حساب صديق ما بعد استخراج االسم screen_nameمن عقدة userفي ملف JSONاملستعاد ،وباعتبار وجود احتمالية لوجود الحساب ً ً ً مسبقا في جدول peopleعن طريق تعليمة مسبقا لذا علينا أوال تفقد وجوده في قاعدة البيانات ،SELECTفإن لم نواجه أي أخطاء في بنية ) (try/exceptنستخرج السجل باستخدام )( fetchone ثم نستخرج أول عنصر (وهو العنصر الوحيد) من الصف املستعاد ونخزنه في املتحول ،friend_id فإن فشلت تعليمة SELECTستفشل تعليمات ] fetchone () [0وسينتقل التنفيذ إلى قسم except ]'friend = u['screen_name 'cur.execute('SELECT id FROM People WHERE name = ? LIMIT 1 ) ) (friend, try: ]friend_id = cur.fetchone()[0 countold = countold + 1 except: )cur.execute('''INSERT OR IGNORE INTO People (name, retrieved ) ) VALUES ( ?, 0)''', ( friend, )(conn.commit if cur.rowcount != 1 : )print('Error inserting account:',friend continue friend_id = cur.lastrowid الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 275 countnew = countnew + 1 ُ وإن نفذت تعليمات قسم exceptفهذا يعني أننا لم نعثر على السطر لذلك سيتوجب علينا إضافة السطر ،أي نستخدم INSERT OR IGNOREلتجنب األخطاء ثم نستدعي )( commitإلجبار قاعدة البيانات إلجراء عملية تحديث للبيانات ،وبعد انتهاء عملية الكتابة يصبح بإمكاننا تفقد قيمة cur.rowcountملعرفة عدد السطور املتأثرة وإن كان عدد الصفوف املتأثرة ال يساوي الواحد فهذا خطأ حيث أننا نعمل على إدخال صف واحد فقط ،وإن نجحت عملية INSERTنستطيع تفقد قيمة ُ َ cur.lastrowidملعرفة القيمة التي أسندتها قاعدة البيانات لعمود idفي السطر الجديد املنشأ. 3.8.15تخزين عالقة الصداقة بين مستخدمي تويتر لكل من مستخدم تويتر وصديقه في ملفات JSONتصبح عملية إدخال بمجرد معرفة قيمة املفتاح ٍ القيم إلى جدول Followعملية بسيطة وذلك عن طريق التعليمة اآلتية: cur.execute('INSERT OR IGNORE INTO Follows (from_id, to_id) VALUES ) )(?, ?)', (id, friend_id كما يجب مالحظة أن قاعدة البيانات تمنعنا من إدخال نفس العالقة مرتين عبر إضافة القيود وإضافة OR IGNOREإلى تعليمة ،INSERTونعرض هنا نتيجة تنفيذ هذا البرنامج: Enter a Twitter account, or quit: No unretrieved Twitter accounts found Enter a Twitter account, or quit: drchuck Retrieving http://api.twitter.com/1.1/friends ... New accounts= 20 revisited= 0 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends ... New accounts= 17 revisited= 3 Enter a Twitter account, or quit: Retrieving http://api.twitter.com/1.1/friends ... New accounts= 17 revisited= 3 الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 276 Enter a Twitter account, or quit: quit كما نرى ،فقد بدأنا بمعالجة الحساب ( drchuckاسم حساب املؤلف في تويتر) ثم ندع البرنامج يختار ً تلقائيا ،ونعرض هنا بعض الحسابين التاليين الستخراج بياناتهما وإضافتها إلى قاعدة البيانات الصفوف األولى من جدولي peopleو followsالناتجة بعد اكتمال تشغيل البرنامج: People: )(1, 'drchuck', 1 )(2, 'opencontent', 1 )(3, 'lhawthorn', 1 )(4, 'steve_coppin', 0 )(5, 'davidkocher', 0 55 rows. Follows: )(1, 2 )(1, 3 )(1, 4 )(1, 5 )(1, 6 60 rows. نجد هنا من جدول peopleرقم املعرف idواالسم nameوالخانة األخيرة visitedتشير فيما إذا كان الحساب قد تم معالجته أم ال ،ونالحظ أنه تمت معالجة الحسابات الثالثة األولى ،أما في جدول followsفنجد أرقام توضح العالقة بين األصدقاء حيث تبين البيانات الظاهرة أن املستخدم األول drchuckصديق لجميع األشخاص الظاهرة أسماؤهم في الصفوف الخمسة األولى ،وهذا منطقي ً فقد استخرجنا أوال قائمة أصدقاء drchuckوخزناها وهكذا إن استطعت إظهار صفوف أكثر من جدول followsفسترى أصدقاء املستخدمين 2وً 3 أيضا. الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 277 9.15أنواع املفاتيح الثالثة بما أننا بدأنا ببناء نموذج بيانات من خالل إضافة بياناتنا إلى عدد من الجداول املرتبطة ببعضها البعض ،حيث ربطنا السطور باستخدام املفاتيح فالبد من التعرف على بعض املصطلحات املتعلقة بهذا املوضوع ،حيث يوجد بشكل عام ثالثة أنواع من املفاتيح املستخدمة في نمذجة البيانات: • املفتاح املنطقي ) :(logical keyهو مفتاح يستخدم ً علميا للبحث عن سطر معين ،وهو في ً اعتمادا عليه لنحصل على بيانات مثالنا خانة nameالذي يمثل اسم املستخدم وقد بحثنا ً سابقا أنه من املفيد فرض قيود على املفتاح سطر خاصة بأحد املستخدمين ،الحظنا املنطقي بحيث يكون غير مكرر UNIQUEولكن بما أنه -أي املفتاح -يعبر عن كيفية بحثنا ً أحيانا السماح لعدة سطور عن سطر معين من وجهة نظر العالم الخارجي فمن املنطقي ضمن الجدول بالحصول على نفس القيمة. ً تلقائيا ،يستخدم لربط • املفتاح الرئيس ي ) :(primary keyهو رقم تولده قاعدة البيانات عدة سطور من جداول مختلفة فال فائدة لوجوده خارج البرنامج ،وتكون الطريقة األسرع إليجاد سطر ما ضمن أحد الجداول بالبحث عنه عن طريق املفتاح الرئيس ي باعتباره رقم صحيح حيث ال يشغل مساحة تخزين كبيرة ويمكن مقارنته وترتيبه بسرعة ،وكمثال عنه في نموذجنا الخانة . id • املفتاح الخارجي ( :)foreign keyوهو رقم يشير إلى املفتاح الرئيس ي لسطر بجدول أخر، وكمثال عليه في نموذجنا املفتاح .from_id مع األخذ بعين االعتبار أننا استخدمنا نظام تسميات معين حيث أشرنا إلى املفتاح الرئيس ي بـ idبينما أشرنا إلى املفتاح الخارجي باسم ينتهي بالالحقة . _id 10.15استخدام عبارة JOINالستعادة البيانات ً اآلن وقد قطعنا شوطا اتبعنا فيه معايير تصميم قواعد البيانات وفصلنا البيانات ضمن جدولين وربطنا بينهما باستخدام املفاتيح الرئيسية والخارجية أصبح باإلمكان أن نستخدم تعليمة SELECT لجمع البيانات من الجدولين .تستخدم لغة SQLعبارة JOINلربط تلك الجداول ببعضها حيث تسمح لنا بتحديد الخانات الالزمة لربط السطور بين الجداول املختلفة ،كما في املثال اآلتي: SELECT * FROM Follows JOIN People الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 278 ON Follows.from_id = People.id WHERE People.id = 1 وتشير JOINإلى أننا نسترجع الخانات املتقاطعة بين الجدولين Followsو Peopleوتشير عبارة ON إلى شرط تحقيق هذا التقاطع ،نفسر التعليمة السابقة كما يلي :نستعيد السطور من جدول Followsونضيف إليه السطر من جدول Peopleحيث تتطابق قيمة from_idفي جدول follows مع قيمة idفي جدول . People الشكل : 26ربط الجداول باستخدام JOIN باختصار إن مهمة JOINهي إنشاء سطور معدلة طويلة تحتوي على خانات من جدول People والخانات املوافقة لها في جدول Followsحيث يوجد أكثر من حالة توافق ما بين حقل idمن جدول لكل من أزواج Peopleوحقل from_idمن جدول ،Followsأي تنش ئ عبارة JOINسطر معدل ٍ ً الصفوف املتوافقة مكررة البيانات بالقدر الذي نحتاجه. ويوضح البرنامج التالي البيانات التي ستخزن في قاعدة البيانات بعد تشغيل برنامج استكشاف تويتر عدة مرات: import sqlite3 )'conn = sqlite3.connect('friends.sqlite SQL استخدام قواعد البيانات ولغة:الفصل الخامس عشر 279 cur = conn.cursor() cur.execute('SELECT * FROM People') count = 0 print('People:') for row in cur: if count < 5: print(row) count = count + 1 print(count, 'rows.') cur.execute('SELECT * FROM Follows') count = 0 print('Follows:') for row in cur: if count < 5: print(row) count = count + 1 print(count, 'rows.') cur.execute('''SELECT * FROM Follows JOIN People ON Follows.to_id = People.id WHERE Follows.from_id = 2''') count = 0 print('Connections for id=2:') for row in cur: if count < 5: print(row) count = count + 1 print(count, 'rows.') cur.close() # Code: http://www.py4e.com/code3/twjoin.py الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 280 عرضنا بيانات الجدولين في بداية البرنامج ثم عرضنا مجموعة جزئية من البيانات املتقاطعة بين الجداول املترابطة ببعضها ويكون خرج البرنامج كما يلي: python twjoin.py People: )(1, 'drchuck', 1 )(2, 'opencontent', 1 )(3, 'lhawthorn', 1 )(4, 'steve_coppin', 0 )(5, 'davidkocher', 0 55 rows. Follows: )(1, 2 )(1, 3 )(1, 4 )(1, 5 )(1, 6 60 rows. Connections for id=2: )(2, 1, 1, 'drchuck', 1 )(2, 28, 28, 'cnxorg', 0 )(2, 30, 30, 'kthanos', 0 )(2, 102, 102, 'SomethingGirl', 0 )(2, 103, 103, 'ja_Pac', 0 20 rows. الحظ أننا نجد في الخرج أعمدة الجدولين Peopleو Followsومجموعة األسطر الظاهرة في النهاية هي نتيجة استخدام تعليمة SELECTمع عبارة JOINحيث نفحص في عملية SELECTاألخيرة حسابات الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 281 أصدقاء” – “opencontentاسم أحد الحسابات -حيث ( ،(People.id=2ففي كل سطر معدل من ً متبوعا باألعمدة ً بدءا من العمود الثالث حتى تلك العملية يظهر أول عمودين من جدول Follows الخامس من جدول ،Peopleوتجد ً أيضا أن العمود الثاني ) (Follows.to_idيطابق العمود الثالث كل من السطور املعدلة املضافة. )(People.idفي ٍ 11.15امللخص تناول هذا الفصل أساسيات استخدام قواعد البيانات في لغة بايثون ،مع مالحظة أن كتابة برنامج ً تعقيدا من استخدام قواميس بايثون أو ملفات عادية الستخدام قاعدة بيانات لتخزين البيانات أكثر ً قليال ً نسبيا إال عند الحاجة الحقيقية لها ولإلمكانيات التي مما يجعل امليل نحو قواعد البيانات توفرها ،ونلخص هنا الحاالت التي تكون فيها قواعد البيانات مفيدة ً جدا: 1إن كان برنامجك يحتاج إلى إجراء العديد من التحديثات العشوائية الصغيرة ضمن مجموعة بيانات هائلة الحجم. 2في حال كانت البيانات ضخمة ً جدا بحيث ال َ تسع ضمن قاموس ولديك حاجة للبحث عن معلومات معينة بشكل متكرر. 3عند وجود عملية معالجة تستهلك وقت طويل وتحتاج خاللها إلى وقف وإعادة تشغيل البرنامج وحفظ البيانات من عملية تشغيل إلى أخرى. باختصار ،تستطيع إنشاء قاعدة بيانات بسيطة تحتوي جدول بسيط لتناسب احتياجات تطبيقات مختلفة ،إال أن معظم القضايا ستتطلب عدة جداول وعالقات بين السطور في مختلف الجداول، ومن املهم التمعن بشكل جيد بالتصميم واتباع معايير قواعد البيانات عند البدء بإنشاء الروابط بين الجداول لالستفادة أقص ى ما يمكن من اإلمكانيات التي توفرها قاعدة البيانات ،وبما أن الهدف الرئيس ي الستخدام قواعد البيانات هو التعامل مع كمية كبيرة من البيانات فمن املهم نمذجة البيانات بطريقة فعالة ليتمكن البرنامج من العمل أسرع ما يمكن. 12.15التنقيح ً شيوعا عند تطوير برامج بلغة بايثون لالتصال بقاعدة بيانات SQLiteهو أحد أكثر اإلجراءات تشغيل برنامج وتفحص النتائج باستخدام متصفح قواعد بيانات الخاص بـ ،SQLiteحيث يسمح لك املتصفح بتفقد عمل البرنامج ،كما يجب أن تكون ً حذرا ألن SQLiteتمنع برنامجين مختلفين من الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 282 تعديل نفس البيانات في نفس الوقت .على سبيل املثال ،إن فتحت قاعدة بيانات معينة في متصفح قواعد بيانات وأجريت تعديل ما عليها بدون الضغط على زر "حفظ" فسيحجب املتصفح ملف قاعدة البيانات وسيمنع أي برنامج آخر من الوصول إلى امللف ،أي لن يكون برنامج بايثون ً قادرا على الوصول امللف في هذه الحالة ،وكحل لتلك املشكلة نتأكد من إغالق متفصح قاعدة البيانات أو استخدام قائمة ملف إلغالق قاعدة البيانات في املتصفح قبل محاولة الوصول إلى قاعدة البيانات باستخدام بايثون ،وبهذا نتجنب مشكلة فشل برنامج بايثون بسبب حجب قاعدة البيانات. 13.15فهرس املصطلحات • السمة ( :)attributeإحدى قيم صفوف بايثون ُيعرف باسم عمود أو خانة. • قاعدة أو قيد ( :)constraintعندما نطلب من قاعدة البيانات تطبيق قاعدة ما على أحد ً الحقول أو السطور في جدول ما ،وأشهرها عدم تكرار القيم في حقل معين (مثال :يجب أن تكون جميع القيم فريدة). • املؤشر ( :)cursorيسمح لك بتنفيذ أوامر SQLفي قاعدة بيانات معينة واستخراج البيانات منها ،كما ُيشابه مأخذ الشبكة ( )socketأو معرف امللفات ( )file handleالخاصين باتصاالت الشبكة وامللفات. • متصفح قواعد البيانات ( :)database browserبرنامج يسمح لك باالتصال بشكل مباشر مع قواعد البيانات والتعديل عليها دون الحاجة إلى كتابة برنامج. • املفتاح الخارجي ( :)foreign keyمفتاح رقمي يشير إلى املفتاح الرئيس ي الخاص بسطر ما في جدول آخر ،وتنش ئ هذه املفاتيح الروابط بين السطور املخزنة في جداول مختلفة. • الفهرس ( :)indexبيانات إضافية يحتويها برنامج قاعدة البيانات كالسطور واإلدخاالت إلى جدول ما بهدف إجراء عمليات البحث بسرعة. • املفتاح املنطقي ( :)logical keyمفتاح نستخدمه للبحث عن سطر معين ،على سبيل املثال قد يشكل عنوان البريد اإللكتروني لشخص ما في جدول حسابات املستخدمين قيمة مناسبة ليكون املفتاح املنطقي الخاص ببيانات املستخدم. • املعايرة ( :)normalizationتصميم نموذج بيانات يمنع تكرارها حيث نخزن كل عنصر من الفصل الخامس عشر :استخدام قواعد البيانات ولغة SQL 283 البيانات في مكان واحد ضمن قاعدة البيانات ونربطه بمكان آخر عن طريق املفتاح الخارجي. • املفتاح الرئيس ي ( :)primary keyمفتاح رقمي خاص بكل سطر ويستخدم لإلشارة إلى ً سطر ما في جدول مختلف ،وعادة ما تكون قاعدة البيانات مضبوطة بحيث تسند قيم هذه املفاتيح بشكل تلقائي أثناء إدخال السطور. • العالقة ( :)relationجزء من قاعدة البيانات تحتوي على صفوف ( )tuplesوسمات ُ ( )attributesوتعرف باسم "جدول". • الصف ( :)tupleمدخل وحيد ضمن قاعدة بيانات معينة يتألف من مجموعة من السمات، ُويعرف باسم "سطر". الفصل السادس عشر العرض املرئي للبيانات الفصل السادس عشر :العرض املرئي للبيانات 285 ّ املرئي للبيانات 16العرض تعلمنا إلى حد اآلن أساسيات لغة بايثون ،وكيفية استخدامها مع الشبكات ،وقواعد البيانات، وطرائق التعامل مع البيانات. سندرس في هذا الفصل ثالث تطبيقات تشمل جميع تلك املفاهيم ً معا؛ بهدف إدارة وعرض البيانات نماذج ُت ُ َ ًّ عين َك عندما تبدأ بحل مسائل حقيقية. مرئيا .ويمكنك اعتبار هذه التطبيقات كملف مضغوط بصيغة " ،"ZIPيمكنك تحميله وفك ضغطه على حاسوبك تتوفر هذه التطبيقات ٍ الشخص ي لتشغيله. 1.16عرض خريطة باستخدام بيانات جغر ّ افية من غوغل سنستخدم في هذا املشروع واجهة غوغل البرمجية للترميز الجغرافي ()Google geocoding API؛ للبحث عن مواقع جغرافية لبعض أسماء جامعات ٌمدخلة من املستخدم ،ثم إدراج هذه املواقع على خريطة غوغل. حمل التطبيق من هناhttp://www.py4e.com/code3/geodata.zip : أولى القضايا الواجب حلها هي أن النسخة املجانية من واجهة غوغل البرمجية للترميز الجغرافي محدودة من ناحية عدد الطلبات في اليوم ،فإن كان لديك الكثير من البياناتَّ ، ترتب عليك إيقاف عملية البحث وإعادتها عدة مرات ،لذلك سنحل هذه املشكلة على مرحلتين. في املرحلة األولى ،نقرأ بيانات أسماء الجامعات املوجودة في ملف where.dataكل سطر على حدة، ثم نسترجع املعلومات َّ املرمزة جغر ًّ افيا من غوغل لكل سطر ،ونخزنها في قاعدة البيانات .geodata.sqliteلكن ،قبل استخدام الواجهة البرمجية مع كل موقع ُمدخل من قبل املستخدم، ً مسبقا؛ للتأكد من عدم تكرار الطلب لذات البيانات علينا التحقق من عدم توفر تلك البيانات لدينا من غوغل ،حيث تعمل قاعدة البيانات بمثابة ذاكرة تخزين مؤقت ( )cacheمحلية لبيانات الترميز الجغرافي. يمكنك إعادة تنفيذ العملية في أي وقت بحذف امللف .geodata.sqlite سيقرأ برنامج geoload.pyاملدخالت من امللف ،where.dataويتحقق فيما إذا كان كل سطر متوف ًرا ً مسبقا في قاعدة البيانات ،أم ال .في حال عدم توفر بيانات املوقع ،سنستدعي الواجهة البرمجية العرض املرئي للبيانات:الفصل السادس عشر 286 . وتخزينها ضمن قاعدة البيانات،للترميز الجغرافي السترجاع البيانات خريطة غوغل: 27 الشكل : وذلك بوجود بعض البيانات في قاعدة البيانات،نبين فيما يلي الخرج بعد التشغيل Found in database Northeastern University Found in database University of Hong Kong, ... Found in database Viswakarma Institute, Pune, India Found in database UMD Found in database Tufts University Resolving Monash University Retrieving http://maps.googleapis.com/maps/api/ geocode/json?address=Monash+University Retrieved 2063 characters { "results" : [ {'status': 'OK', 'results': ... } الفصل السادس عشر :العرض املرئي للبيانات 287 Resolving Kokshetau Institute of Economics and Management Retrieving http://maps.googleapis.com/maps/api/ geocode/json?address=Kokshetau+Inst ... [ Retrieved 1749 characters { "results" : } {'status': 'OK', 'results': ... ... ً مسبقا في قاعدة البيانات ،لذلك تم تخطيها .يستمر البرنامج حتى يجد املواقع الخمسة األولى موجودة مواقع جديدة ،ثم يبدأ في استرجاعها. يمكن إيقاف برنامج groload.pyفي أي وقت تريد ،باإلضافة إلى وجود عداد يمكن استخدامه للحد من استدعاءات الواجهة البرمجية للترميز الجغرافي في كل مرة تشغيل؛ ألنه ال يجب الوصول إلى املعدل األقص ى للبيانات اليومية ،ألن where.dataال يحتوي إال على بضع مئات من عناصر البيانات ،فلن يكون هناك مشكلة .لكن ،في حال وجود املزيد من البيانات ،سيتطلب ذلك التشغيل عدة مرات على مدار أيام عدة حتى تحصل قاعدة البيانات على جميع البيانات الجغرافية املرمزة للمواقع املطلوبة. بمجرد توفر البيانات في ،geodata.pyيمكنك عرضها باستخدام برنامج ،geodump.pyحيث يقرأ هذا البرنامج محتوى قاعدة البيانات ،وينش ئ امللف ""where.js؛ ليعرض املوقع وخطوط الطول والعرض على شكل ملف Javascriptتنفيذي. ويكون ناتج تنفيذ برنامج geodump.pyكالتالي: Northeastern University, ... Boston, MA 02115, USA 42.3396998 -71.08975 Bradley University, 1501 ... Peoria, IL 61625, USA 40.6963857 -89.6160811 ... Monash University Clayton ... VIC 3800, Australia -37.9152113 145.134682 Kokshetau, Kazakhstan 53.2833333 69.3833333 ... الفصل السادس عشر :العرض املرئي للبيانات 288 12 records written to where.js Open where.html to view the data in a browser يتألف امللف " "where.htmlمن شيفرة ،HTMLو JavaScriptملعاينة وعرض خريطة غوغل. يقرأ أحدث البيانات في " "where.jsلعرضها .ويكون محتوى هذا امللف على الشكل التالي: [ = myData [42.3396998,-71.08975, 'Northeastern Uni ... Boston, MA 02115'], [40.6963857,-89.6160811, 'Bradley University, ... Peoria, IL 61625, USA'], ... ;] يحتوي هذا املتغير املكتوب بلغة JavaScriptعلى قائمة من القوائم .ومن املفترض أن تكون هذه الصيغة مألوفة بالنسبة لك ،حيث إن الصيغة البرمجية لكتابة القوائم بلغة JavaScriptتشبه إلى َ املستخدمة في بايثون ألجل هذا الغرض. حد كبير الصيغة البرمجية ٍ افتح " "where.htmlعلى املتصفح ملعاينة املواقع .يمكنك التحرك بين املواقع على الخريطة ملعرفة املوقع الذي أوجدته واجهة الترميز الجغرافي .وفي حال عدم وجود أية بيانات عند فتح ملف " ،"where.htmlيجب التحقق من ،JavaScriptأو وحدة املطورين ( )developer consoleعلى املتصفح. 2.16العرض ّ املرئي للشبكات واالرتباطات سننفذ في هذا التطبيق إحدى وظائف محركات البحث .سنكتشف ً ً صغيرا من شبكة اإلنترنت، جزءا ونشغل نسخة ُمبسطة من خوارزمية غوغل لترتيب الصفحات؛ بهدف التعرف على أكثر الصفحات ً ارتباطا ،ثم سنعرض ترتيب وارتباطات الصفحات التي اكتشفناها. سنستخدم مكتبة ( D3 JavaScript Visualizationمزيد من املعلومات في الرابط )http://d3js.org/ إلعداد عرض الخرج. يمكن تحميل وفك ضغط التطبيق عبر الرابطwww.py4e.com/code3/pagerank.zip : الفصل السادس عشر :العرض املرئي للبيانات 289 الشكل : 28رتبة الصفحات يكتشف البرنامج األول spider.pyأحد مواقع الشبكة ،ويستخرج منه عدة صفحات ليخزنها في قاعدة البيانات ً spider.sqlite وفقا للروابط بين هذه الصفحات. يمكنك إعادة تشغيل هذه العملية في أي وقت بحذف امللف ،spider.sqliteوإعادة تشغيل .spider.py Enter web url or enter: http://www.dr-chuck.com/ ]'['http://www.dr-chuck.com How many pages:2 1 http://www.dr-chuck.com/ 12 2 http://www.dr-chuck.com/csev-blog/ 57 How many pages: الفصل السادس عشر :العرض املرئي للبيانات 290 في املثال السابق ،بحث البرنامج في أحد املواقع ،وأرجع صفحتين منه .في حال أعدنا تشغيل البرنامج َ لتعقب املزيد من الصفحات ،فلن َّ يتتبع الصفحات التي ُحفظت مسب ًقا في قاعدة البيانات. َ صفحات جديدة لم ُتكت َشف بعد؛ ليبدأ من عندها .بالتالي ،يمكن القول حاملا تعيد تشغيله ،يتجه إلى ٍ إن مع كل عملية تشغيل ناجحة للبرنامج ،spider.pyتضاف صفحات جديدة. Enter web url or enter: http://www.dr-chuck.com/ ]'['http://www.dr-chuck.com How many pages:3 3 http://www.dr-chuck.com/csev-blog 57 4 http://www.dr-chuck.com/dr-chuck/resume/speaking.htm 1 5 http://www.dr-chuck.com/dr-chuck/resume/index.htm 13 How many pages: يمكنك الحصول على عدة نقاط مرجعية في قاعدة البيانات داخل البرنامج ،وتدعى " ."websيختار ُ عشوائيا ليكتشفها ً ًّ تاليا. البرنامج إحدى الصفحات التي لم تكتشف بعد إذا أردت عرض محتويات ملف ،spider.sqliteيمكنك تشغيل .spdump.py )'(5, None, 1.0, 3, 'http://www.dr-chuck.com/csev-blog )'(3, None, 1.0, 4, 'http://www.dr-chuck.com/dr-chuck/resume/speaking.htm )'(1, None, 1.0, 2, 'http://www.dr-chuck.com/csev-blog/ )'(1, None, 1.0, 5, 'http://www.dr-chuck.com/dr-chuck/resume/index.htm 4 rows. يعرض املثال السابق عدد الروابط الجديدة املضافة ،والترتيب القديم ،ثم الجديد للصفحة ،ورمز تعريف الصفحة ،ورابطها بالترتيب .يعرض برنامج spdump.pyفقط الصفحات التي تملك على األقل رابط يشير لها. بمجرد توفر عدة صفحات في قاعدة البيانات ،يمكنك تنفيذ عملية الترتيب لهذه الصفحات باستخدام برنامج ،sprank.pyحيث يمكنك إخبار البرنامج بعدد مرات تكرار خوارزمية ترتيب الصفحات. الفصل السادس عشر :العرض املرئي للبيانات 291 How many iterations:2 1 0.546848992536 2 0.226714939664 ])[(1, 0.559), (2, 0.659), (3, 0.985), (4, 2.135), (5, 0.659 يمكنك عرض محتوى قاعدة البيانات بتنفيذ pdump.pyلترى أن قيمة ترتيب الصفحة قد ُحدثت لجميع املواقع: )'(5, 1.0, 0.985, 3, 'http://www.dr-chuck.com/csev-blog )'(3, 1.0, 2.135, 4, 'http://www.dr-chuck.com/dr-chuck/resume/speaking.htm )'(1, 1.0, 0.659, 2, 'http://www.dr-chuck.com/csev-blog/ )'(1, 1.0, 0.659, 5, 'http://www.dr-chuck.com/dr-chuck/resume/index.htm 4 rows. يمكنك تشغيل البرنامج sprank.pyبقدر ما تشاء ،وسيظهر لك في كل مرة ترتيب الصفحات .أو يمكنك تشغيله بضع مرات ،ثم إضافة صفحات جديدة بتشغيل البرنامج ،spider.pyوثم تشغيل ،sprank.pyواالطالع على الترتيب الجديد. تقوم محركات البحث بهاتين العمليتين (تعقب صفحات جديدة وترتيبها) طوال الوقت. إذا أردت ترتيب الصفحات من جديد ،شغل برنامج ،spreset.pyثم أعد تشغيل .sprank.py How many iterations:50 1 0.546848992536 2 0.226714939664 3 0.0659516187242 4 0.0244199333 5 0.0102096489546 6 0.00610244329379 ... الفصل السادس عشر :العرض املرئي للبيانات 292 42 0.000109076928206 43 9.91987599002e-05 44 9.02151706798e-05 45 8.20451504471e-05 46 7.46150183837e-05 47 6.7857770908e-05 48 6.17124694224e-05 49 5.61236959327e-05 50 5.10410499467e-05 ])[(512, 0.0296), (1, 12.79), (2, 28.93), (3, 6.808), (4, 13.46 ُيعرض التغير الوسطي الحاصل في ترتيب الصفحات عند كل تكرار لخوارزمية ترتيب الصفحات .في البداية ،تكون الشبكة غير متوازنة ،لذا تتباين قيم ترتيب الصفحات مع تكرار الخوارزمية ،وعندما نصل إلى عدد معين من التكرارات للخوارزمية ،تصبح تلك القيم متقاربة أكثر ،لذا عليك تشغيل برنامج ً sprank.py عددا ً كافيا من املرات حتى تتقارب قيم ترتيب الصفحات. إذا أردت عرض ترتيب الصفحات الحالي للمواقع التي تعاملنا معها أعاله ،شغل البرنامج spjson.py ً لقراءة قاعدة البيانات وتخزين البيانات الخاصة بالصفحات األكثر ارتباطا وفق صيغة JSON؛ ُلتعرض في املتصفح. Creating JSON output on spider.json... How many nodes? 30 Open force.html in a browser to view the visualization بإمكانك عرض هذه البيانات بفتح ملف " "force.htmlفي املتصفح؛ لتشاهد الروابط والعقد مولدة تلقائيا ،حيث يمكنك السحب والنقر على أية عقدة ،كما يمكنك ً ً أيضا إيجاد الرابط الذي تمثله العقدة عبر النقر املزدوج عليها. إذا أعدت تشغيل البرامج املساعدة األخرى ،مثل برنامج ،spjson.pyوحدثت الصفحة في املتصفح، ستحصل على بيانات جديدة من ملف .spider.json الفصل السادس عشر :العرض املرئي للبيانات 293 ّ اإللكتروني 3.16تحليل وعرض البيانات الواردة في البريد ً بعد أن أصبح التعامل مع امللفين " "mbox-short.txtو" "mbox.txtمألوفا بالنسبة لنا ،حان الوقت لتحسين مهارتنا في تحليل البيانات الواردة في البريد اإللكتروني. ً أحيانا إلى سحب البيانات من الخوادم .قد تكون هذه البيانات في التطبيقات العملية ،قد تحتاج مليئة باألخطاء ،وغير متناسقة ،وتتطلب الكثير من التعديل والترتيب ،لذا قد تتطلب العملية ً وقتا ً طويال. سنتطرق في هذا القسم إلى أعقد تطبيق تعاملنا معه إلى حد اآلن ،حيث سوف نسحب 1جيجابايت من البيانات لتحليلها واستعراضها. يمكنك تحميل التطبيق من خالل الرابط التاليhttps://www.py4e.com/code3/gmane.zip : سوف نستخدم خدمة مجانية ألرشفة قوائم البريد اإللكتروني للحصول على البيانات ،تدعى ،http://www.gmane.org.حيث تعد هذه الخدمة شائعة االستخدام في التطبيقات مفتوحة املصدر؛ إذ تؤمن أرشيف يمكنك البحث فيه عن نشاط بريدهم اإللكترونيً . علما أنه ال يوجد حدود ً للتحميل ،إذ يمكنك تحميل قدر ما تشاء من البيانات ،لكن يفضل أال تسرف وتسبب ضغطا على الشكل :29مجموعة كلمات موزعة على شكل غيمة مولدة من قائمة شركة Sakai الفصل السادس عشر :العرض املرئي للبيانات 294 خوادمهم .يمكنك االطالع على شروط االستخدام من خالل زيارة الصفحة التالية: http://www.gmane.org/export.php من املهم استخدام هذه الخدمة بمسؤولية ،وذلك من خالل إضافة تأخير زمني لطلبات الوصول للخوادم ،وتوزيع املهام التي تحتاج إلى وقت معالجة طويل على أطول فترة ممكنة .لذلك ،احرص على عدم إساءة استخدام هذه الخدمة. ُ لدى ُّ تعقب بيانات البريد اإللكتروني لشركة Sakaiباستخدام هذا البرنامج ،أنتج قرابة 1غيغابايت من البيانات ،واستغرق ذلك عمليات عديدة على مدار عدة أيام. يحتوي امللف README.txtفي املجلد املضغوط أعاله على إرشادات حول كيفية تحميل نسخة من ملف content.sqliteمجموعة من رسائل البريد اإللكتروني لـ Sakaiالجاهزة ،حيث ال تضطر بذلك إلى التعقب ملدة خمسة أيام متواصلة من أجل تشغيل البرامج .لكن ،حتى وإن حملت املحتوى الجاهز ً مسبقا ،فال يزال عليك إجراء عملية تعقب ملتابعة أحدث الرسائل. تتجلى الخطوة األولى في تعقب أرشيف ،gmaneحيث إن عنوان URLاألساس ي مضاف بشكل مباشر في شيفرة ،gmane.pyوفي قائمة مطوري .Sakaiيمكنك تعقب أرشيف آخر عن طريق تغيير عنوان URLاألساس ي .تأكد من حذف ملف content.sqliteعند تبديل عنوان URLاألساس ي. يعمل ملف gmane.pyبطريقة مسؤولة ،حيث يعمل ببطء ،ويسترد رسالة بريد إلكتروني واحدة في َ الثانية ،وذلك كي ال يعلق في أرشيف .gmaneكما يخزن جميع بياناته في قاعدة بيانات تتيح املقاطعة وإعادة التشغيل كلما دعت الحاجة .قد يستغرق تحميل جميع البيانات عدة ساعات ،لذلك قد تحتاج إلى إعادة التشغيل عدة مرات. فيما يأتي ناتج عملية تشغيل ملف ،gmane.pyحيث يسترد الرسائل الخمسة األخيرة من قائمة مطوري :Sakai How many messages:10 http://download.gmane.org/gmane.comp.cms.sakai.devel/51410/51411 9460 nealcaidin@sakaifoundation.org 2013-04-05 re: [building ... http://download.gmane.org/gmane.comp.cms.sakai.devel/51411/51412 3379 samuelgutierrezjimenez@gmail.com 2013-04-06 re: [building ... الفصل السادس عشر :العرض املرئي للبيانات 295 http://download.gmane.org/gmane.comp.cms.sakai.devel/51412/51413 9903 da1@vt.edu 2013-04-05 [building sakai] melete 2.9 oracle ... http://download.gmane.org/gmane.comp.cms.sakai.devel/51413/51414 349265 m.shedid@elraed-it.com 2013-04-07 [building sakai] ... http://download.gmane.org/gmane.comp.cms.sakai.devel/51414/51415 3481 samuelgutierrezjimenez@gmail.com 2013-04-07 re: ... http://download.gmane.org/gmane.comp.cms.sakai.devel/51415/51416 0 Does not start with From يتصفح البرنامج قاعدة البيانات content.sqliteمن البداية حتى رقم الرسالة األولى التي لم يتم ً مسبقا ،ويبدأ بعد ذلك في تعقب تلك الرسالة ،إذ يستمر في التعقب حتى يصل إلى العدد تعقبها املطلوب من الرسائل ،أو يصل إلى صفحة ال تبدو أنها رسالة منسقة بشكل صحيح. ً ُ أحيانا تفقد رسالة في ،gmane.orgويعود السبب في ذلك إلى إمكانية حذفها من قبل املسؤولين ،أو احتمالية ضياع إحدى الرسائل .إذا توقف املتعقب بشكل يوحي أنه وصل إلى رسالة مفقودة ،عندها انتقل إلى ،SQLite Managerوأضف ًّ صفا مع كتابة رقم املعرف املفقود ،مع إبقاء الحقول األخرى فارغة ،ثم أعد تشغيل .gmane.pyسيؤدي هذا إلى تحرير ملف التعقب؛ مما يتيح له استمرارية التعقب دون أن يعلق عند الرسالة املفقودة .أما الرسائل الفارغة ،فسيجري تجاهلها في املرحلة التالية من العملية. يمكنك تشغيل gmane.pyمرة أخرى للحصول على رسائل جديدة عند إرسالها إلى القائمة ،وذلك بمجرد أن تتعقب جميع الرسائل وتضعها في ،content.sqliteحيث تعد هذه الخاصية من الخصائص املفيدة. تعد بيانات content.sqliteبيانات أولية ،حيث يعد نموذج بياناتها غير فعال ،كما أنها غير مضغوطة. هذا متعمد ،ألنه يسمح لك باالطالع على content.sqliteفي SQLite Managerلتصحيح مشاكل عملية التعقب .من غير املحبذ إجراء طلبات على قاعدة البيانات هذه ،ألن العملية ستكون بطيئة للغاية. الفصل السادس عشر :العرض املرئي للبيانات 296 أما الخطوة الثانية ،فهي تشغيل برنامج ،gmodel.pyإذ يقرأ هذا البرنامج البيانات األولية من ،content.sqliteوينتج نسخة منظمة ومنسقة من البيانات في ملف .index.sqliteسيكون هذا امللف ًّ أصغر بكثير ً (غالبا ما يكون أصغر بعشر مرات) من content.sqlite؛ ألنه يضغط كال من الترويسة والنص األساس ي. في كل مرة تشغيل لـ ـ ،gmodel.pyيحذف index.sqliteويعيد تكوينه ،مما يتيح إمكانية ضبط معامالته ،وتحرير جداول الربط في content.sqliteلتعديل عملية تنظيم البيانات. َ فيما يلي ناتج تشغيل برنامج ،gmodel.pyحيث يعرض سطر في كل مرة تعالج 250رسالة بريد، لتتمكن من مالحظة التغيير .وبعد فترة من عمل البرنامج ،يكون قد عالج قرابة 1جيجابايت من بيانات البريد. Loaded allsenders 1588 and mapping 28 dns mapping 1 1 2005-12-08T23:34:30-06:00 ggolden22@mac.com 251 2005-12-22T10:03:20-08:00 tpamsler@ucdavis.edu 501 2006-01-12T11:17:34-05:00 lance@indiana.edu 751 2006-01-24T11:13:28-08:00 vrajgopalan@ucmerced.edu ... يتحمل برنامج gmodel.pyعبء معالجة عدد من مهمات تنظيم البيانات .على سبيل املثال :اقتطاع أسماء النطاقات إلى مستويين أو إلى ثالثة مستويات .على سبيل املثال ،يصبح si.umich.eduبالشكل حول عناوين البريد اإللكتروني ً ،umich.eduويصبح caret.am.ac.ukبالشكل ُ ،cam.ac.ukوت َّ أيضا إلى حالة األحرف الصغيرة ،كما ُت َّ حول بعض العناوين التي تنتهي بـ ،@gmane.orgمثل العناوين اآلتية،arwhyte-63aXycvo3TyHXe+LvDLADg@public.gmane.org : إلى العنوان الحقيقي كلما عث َر على عنوان بريد إلكتروني حقيقي مطابق في مكان آخر ضمن الرسالة. يوجد في قاعدة البيانات mapping.sqliteجدوالن يسمحان لك بربط أسماء النطاقات وعناوين البريد اإللكتروني الفردية التي تتغير خالل مدة توفر قائمة البريد اإللكتروني .على سبيل املثال، استخدم ستيف غيثينس Steve Githensعناوين البريد اإللكتروني أدناه مع تغير عمله: s-githens@northwestern.edu الفصل السادس عشر :العرض املرئي للبيانات 297 sgithens@cam.ac.uk swgithen@mtu.edu يمكننا إضافة اثنين من املدخالت إلى جدول الربط في mapping.sqliteحتى يربط gmodel.py اإليميالت الثالثة بعنوان واحد: s-githens@northwestern.edu -> swgithen@mtu.edu sgithens@cam.ac.uk -> swgithen@mtu.edu يمكنك ً أيضا إضافة مدخالت مماثلة في جدول DNSMappingإذا كان هناك العديد من أسماء DNS ُ التي تريد ربطها إلى DNSواحد .على سبيل املثال ،أضيف الربط التالي إلى بيانات :Sakai iupui.edu -> indiana.edu وبذلك ،تكون جميع الحسابات من جميع أنحاء حرم جامعة إنديانا قد تم تعقبها. ً تنظيما يمكنك إعادة تشغيل gmodel.pyمر ًارا وتكر ًارا ،وإضافة عمليات ربط لجعل البيانات أكثر ودقة .وعند االنتهاء ،ستكون لديك نسخة منظمة من البريد اإللكتروني في .index.sqlite يؤمن هذا امللف آلية سريعة لتحليل البيانات. إن أول وأبسط تحليل للبيانات هو تحديد "من الذي أرسل أكبر عدد من الرسائل؟" ،و"ما هي املنظمة التي أرسلت أكبر عدد من رسائل البريد؟" .يتم ذلك باستخدام :gbasic.py How many to dump? 5 Loaded messages= 51330 subjects= 25033 senders= 1584 Top 5 Email list participants steve.swinsburg@gmail.com 2657 azeckoski@unicon.net 1742 ieb@tfd.co.uk 1591 csev@umich.edu 1304 david.horwitz@uct.ac.za 1184 الفصل السادس عشر :العرض املرئي للبيانات 298 Top 5 Email list organizations gmail.com 7339 umich.edu 6243 uct.ac.za 2451 indiana.edu 2258 unicon.net 2055 ً ً الحظ مدى سرعة تشغيل gbasic.pyمقارنة بـ gmane.pyأو حتى .gmodel.pyيعملون جميعا على البيانات ذاتها ،لكن gbasic.pyهو األسرع ،ألنه يستخدم البيانات املضغوطة واملنظمة في .index.sqliteإذا كان لديك الكثير من البيانات إلدارتها ،فقد تتطلب العملية املوجودة في هذا التطبيق ً وقتا أطول للتطويرً ، نظرا إلى أنها عملية متعددة الخطوات ،ولكنها ستوفر لك الكثير من الوقت عندما تبدأ ًّ فعليا في عملية استكشاف وعرض البيانات. يمكنك إجراء تمثيل بسيط للبيانات الخاصة بتكرار الكلمات في سطور املوضوع بتشغيل امللف :gword.py Range of counts: 33229 129 Output written to gword.js ينتج عن هذا التمثيل امللف gword.jsالذي يمكنك عرضه باستخدام gword.htmإلنتاج مجموعة كلمات (ذات أشكال وأحجام مختلفة) مشابهة لتلك املوجودة في بداية هذا القسم. ينتج التمثيل الثاني عند تشغيل gline.py؛ إذ يحسب عدد اإليميالت ً تبعا للمنظمة: Loaded messages= 51330 subjects= 25033 senders= 1584 Top 10 Oranizations ['gmail.com', 'umich.edu', 'uct.ac.za', 'indiana.edu', 'unicon.net', 'tfd.co.uk', 'berkeley.edu', 'longsight.com', ]''stanford.edu', 'ox.ac.uk Output written to gline.js الفصل السادس عشر :العرض املرئي للبيانات 299 تكتب مخرجاته في gline.jsالتي تعرض باستخدام .gline.htm يعد هذا التطبيق من التطبيقات َّ املعقدة ،واملتطورة ًّ نسبيا ،وله ميزات إلنجاز بعض عمليات استرداد البيانات الحقيقية ،وتنظيمها ،وتمثيلها. الشكل : 30توزع اإليميالت بالنسبة للمنظمة امللحق آ املساهمون "Python for Everybody - املساهمون في كتاب "بايثون للجميع.1 Elliott Hauser, Stephen Catto, Sue Blumenberg, Tamara Brunnock, Mihaela Mack, Chris Kolosiwsky, Dustin Farley, Jens Leerssen, Naveen KT, Mirza Ibrahimovic, Naveen (@togarnk), Zhou Fangyi, Alistair Walsh, Erica Brody, Jih-Sheng Huang, Louis Luangkesorn, and Michael Fudge https://github.com/csev/py4e/graphs/contributors :ملزيد من التفاصيل "Python for Informatics - املساهمون في كتاب "بايثون للمعلوماتية.2 Bruce Shields, Sarah Hegge, Steven Cherry, Sarah Kathleen Barbarow, Andrea Parker, Radaphat Chongthammakun, Megan Hixon, Kirby Urner, Sarah Kathleen Barbrow, Katie Kujala, Noah Botimer, Emily Alinder, Mark Thompson-Kular, James Perry, Eric Hofer, Eytan Adar, Peter Robinson, Deborah J. Nelson, Jonathan C. Anthony, Eden Rassette, Jeannette Schroeder, Justin Feezell, Chuanqi Li, Gerald Gordinier, Gavin Thomas Strassel, Ryan Clement, Alissa Talley, Caitlin Holman, Yong-Mi Kim, Karen Stover, Cherie Edmonds, Maria Seiferle, Romer Kristi D. Aranas (RK), Grant Boyer, Hedemarrie Dussan. "Think Python – مقدمة إلى كتاب "فكربطريقة بايثون.3 ملحة تاريخية عن الكتاب ُ ،)مقرر (مدخل إلى لغة جافا ُ 1999 يناير عام/في كانون الثاني َّ َّ أتحضر لتدريس وكنت قد كنت َ َّ درست هذا حتى،املقرر ثالث مرات سابق ٍة وبدأت أشعر بالضيق بسبب معدل الرسوب املرتفع َ ُ .ات تذكر ٍ الناجحين لم يحققوا إنجاز ُ َ َ تفاصيل بسبب ضخامتها واحتوائها على،الكتب هي إحدى أسباب انخفاض املعدالت اكتشفت أن ليست َ ذات أهمية ،وافتقارها إلى التوجيه حو َل كيفية كتابة البرامج ،لقد َ ُ جميعهم في وقع الطالب فخ االستسالم ،حيث يبدؤون القراءة ُبيسر ٍويتدرجون باملحتوى حتى الفصل الخامس وبعدها َ ينسحبون؛ ألن عليهم دراسة محتو ًى جديد بسرعة كبيرة ،لذلك وقبل أسبوعين من بداية الفصل الدراس ي قررت أن أقوم بتأليف كتابي لعدة أهداف منها: ً ً أن يكونصفحات أفضل من أن أعطيهم 50صفحة لن مختصرا (أن يقرأ الطالب 10 ٍ يلمسها أحد). ً َ تقليل املصطلحات التقنية مع ذكر تعريف لكل منها عند أن يكون بسيطا (فقد حاولتورودها ألول مرة). يسهل ُ ُ فهمها). أن يكون متدر ًجا (وزعت املحاور الصعبة إلى خطوات بسيطة التركيز على البرمجة ال على لغة البرمجة (ضمنت أهم قواعد لغة جافا وتركت الباقي).ُ عنونت الكتاب "كيف تفكر كعالم حاسوب" ،الطبعة األولى كانت صعبة لكن الطالب قرؤوها كبيرا منها ،مما مكنني من شرح املواضيع الصعبة في املحاضرات ومنحهم ً وفهموا ً جزءا ً وقتا أكثر للتدرب. أطلقت الكتاب تحت رخصة GNUالتي تمنح صالحية النسخ والتعديل والنشر. ً تبنى جيف إيلكنير ( )Jeff Elknerالكتاب وعدله ليكون مناسبا لتعليم لغة بايثون ،ثم أرسل إلي نسخة من كتابه حيث استمتعت ً جدا بقراءته ،ثم راجعنا الكتاب ً معا وأضفنا دراسة حالة أعدها كريس مايرز ( ،)Chris Meyersوفي عام 2001أطلقنا الكتاب تحت عنوان "كيف تفكر كعالم حاسوب :تعلم لغة بايثون" وفق رخصة ،GNUوبعد نشره بعنا ً عددا من النسخ الورقية عبر موقع أمازون ومكتبات الجامعة. في عام ،2003بدأت العمل كمدرس في جامعة أولين ( )Olinوكان علي أن أدرس لغة بايثون للمرة األولى ،وعلى خالف تعلم لغة جافا لم يعان الطالب ً كثيرا بل تعلموا الكثير وعملوا على مشاريع مهمة وممتعة. ُ ُ حسنت ً تابعت تطوير وتصحيح الكتاب في السنوات الخمس التالية؛ إذ َّ وأضفت بعضا من األمثلة بعض املحتوى وخاصة التمارين. شاملة للكتاب ،وفي الوقت نفسه تواصلت معي دار نشر اجعة ٍ في عام 2008شرعت بإجراء مر ٍ جامعة كمبريدج وكانت مهتمة بنشر نسخة جديدة ،وكم كانت مصادفة مذهلة! أرجو أن تستمتع بالتعلم من هذا الكتاب ،وأن يساعدك في تعلم البرمجة ،وأن تكتسب بعض مهارات التفكير كالتي يتميز بها علماء الحاسوب. كلمة شكر أ َّ توجه بالشكر الكبير لـ جيف إيلكنير الذي عدل كتابي من تعليم جافا إلى تعليم بايثون ،فقد كان املحفز لهذا املشروعَ ، وعرفني إلى اللغة التي أصبحت فيما بعد لغتي البرمجية املفضلة. َ كذلك أشكر مؤسسة كما أود أن أشكر كريس مايرز الذي ساهم بعدة فصول من الكتاب، البرمجيات الحرة ( )Free Software Foundationإلطالق رخصة GNUوالتي سمحت للمؤلفين الثالثة بالتعاون لتحقيق هذا اإلنجاز .وال يسعني إال أن أشكر محرري الكتاب والطالب الذين قرؤوا النسخ األولى منه وأرسلوا لي اقتراحاتهم ومالحظاتهم ،وأشكر زوجتي ليزا لدورها في إنجاز الكتاب ودار نشر غرين تي ( )Green Tea Pressوكل من ساهم في هذا العمل. آالن دويني أستاذ في قسم علوم الحاسوب بكلية فرانكلين أولين للهندسة .4املساهمون في كتاب " فكربطريقة بايثون – " Think Python َ أرسل ما يزيد عن مئة قارئ مالحظاتهم واقتراحاتهم لتحسين الكتاب على مدى سنوات ،وقد كانت مساهمتهم وحماسهم ذوي آثر كبير . لتتعرف على تفاصيل مساهمة كل فرد منهم راجع كتاب "فكر بطريقة بايثون". األسماء: Lloyd Hugh Allen, Yvon Boulianne, Fred Bremmer, Jonah Cohen, Michael Conlon, Benoit Girard, Courtney Gleason and Katherine Smith, Lee Harr, James Kaylin, David Kershaw, Eddie Lam, Man-Yong Lee, David Mayo, Chris McAloon, Matthew J. Moelter, Simon Dicon Montford, John Ouzts, Kevin Parks, David Pool, Michael Schmitt, Robin Shaw, Paul Sleigh, Craig T. Snydal, Ian Thomas, Keith Verheyden, Peter Winstanley, Chris Wrobel, Moshe Zadka, Christoph Zwerschke, James Mayer, Hayden McAfee, Angel Arnal, Tauhidul Hoque and Lex Berezhny, Dr. Michele Alzetta, Andy Mitchell, Kalin Harvey, Christopher P. Smith, David Hutchins, Gregor Lingl, Julie Peters, Florin Oprina, D. J. Webre, Ken, Ivo Wever, Curtis Yanko, Ben Logan, Jason Armstrong, Louis Cordier, Brian Cain, Rob Black, Jean-Philippe Rey at Ecole Centrale Paris, Jason Mader at George Washington University made a number Jan Gundtofte-Bruun, Abel David and Alexis Dinno, Charles Thayer, Roger Sperberg, Sam Bull, Andrew Cheung, C. Corey Capel, Alessandra, Wim Champagne, Douglas Wright, Jared Spindor, Lin Peiheng, Ray Hagtvedt, Torsten Hübsch, Inga Petuhhov, Arne Babenhauserheide, Mark E. Casida, Scott Tyler, Gordon Shephard, Andrew Turner, Adam Hobart, Daryl Hammond and Sarah Zimmerman, George Sass, Brian Bingham, Leah Engelbert-Fenton, Joe Funke, Chao-chao Chen, Jeff Paine, Lubos Pintes, Gregg Lind and Abigail Heithoff, Max Hailperin, Chotipat Pornavalai, Stanislaw Antol, Eric Pashman, Miguel Azevedo, Jianhua Liu, Nick King, Martin Zuther, Adam Zimmerman, Ratnakar Tiwari, Anurag Goel, Kelli Kratzer, Mark Griffiths, Roydan Ongie, Patryk Wolowiec, Mark Chonofsky, Russell Coleman, Wei Huang, Karen Barber, Nam Nguyen, Stéphane Morin, Fernando Tardio, and Paul Stoop. امللحق ب حقوق النشر العمل مرخص وفق رخصة املشاع اإلبداعي من النمط )استخدام غير تجاري -إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي( اإلصدار الثالث. ملعلومات حول الرخصة. http://creativecommons.org/licenses/by-nc-sa/3.0/ : ً ً مشاعا من رخصة املشاع اإلبداعي ذات النمط مرخصا برخصة أكثر لكم وددت أن يكون هذا العمل (عزو العمل األصلي إلى املؤلف -إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي) نسخ الكترونية غير أو CC-BY-SAلكن مع األسف قد تستغل بعض الجهات ذلك لتعيد نشر وبيع ٍ معدلة من الكتاب ضمن مواقع خدمة الطباعة عند الطلب مثل موقع LuLuوموقع .KDPاألخير ً مشكورا سياسة ٌتعنى باالهتمام بمتطلبات صاحب الحقوق األصلي أكثر من الذين يحاولون أضاف إعادة نشر الكتب بدون حصولهم على أية حقوق ولكن قلة من مزودي هذه الخدمة اتبعوا نهج موقع .KDP أضفت بكل حزن ميزة استخدام غير تجاري إلى رخصة الكتاب ألتفادى هؤالء الذين سيستنسخون الكتاب ويبيعونه بهدف الربح املادي .هذه امليزة تقيد من حرية استخدام محتوى الكتاب وددت لو منحتها بشكل كامل .لذا سأشرح في هذا القسم الحاالت التي سأسمح فيها باستخدام محتوى الكتاب بشكل تجاري ً إذا أردت طباعة عدد محدود من نسخ الكتاب كامال أو أجزاء منه بهدف االستخدام بمقررتعليمي فأمنحك رخصة املشاع اإلبداعي من النمط (عزو العمل األصلي إلى املؤلف) أو CC- BY إن كنت ًً جامعيا وترجمت الكتاب إلى لغة غير اإلنكليزية واستخدمت النسخة املترجمة مدرسا للتدريس ،فتواصل معي ألمنحك رخصة املشاع اإلبداعي من النمط )استخدام غير تجاري - إصدار العمل الجديد بموجب ترخيص مطابق للترخيص األصلي( أو CC-BY-SAبما يتوافق مع نسختك املترجمة حيث سأسمح لك باالستخدام التجاري للنسخة املترجمة. إن كنت تبغي ترجمة الكتاب فأنصحك بالتواصل معي حتى أقدم لك كل ما تحتاج من محتوى ليكون ً متاحا لك لترجمته. وفي حال لديك حالة تختلف عما ذكر أعاله فال تتردد بالتواصل معي فأنا منفتح على منح الرخصة في حال هناك قيمة مضافة في طريقة إعادة استخدامك ملحتوى الكتاب. تشارلز سيفيرنس www.dr.chuck.com مدينة أن أربور في والية ميشيغان في الواليات املتحدة األميركية 9أيلول /سبتمبر 2013