67% found this document useful (3 votes)
2K views

Bramijnet Python Course

المستند يتناول مقدمة عن لغة البايثون وخطة الدورة التدريبية حولها. يتضمن مبادئ اللغة والمتغيرات وإسناد القيم لها.

Uploaded by

yahia2009
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
67% found this document useful (3 votes)
2K views

Bramijnet Python Course

المستند يتناول مقدمة عن لغة البايثون وخطة الدورة التدريبية حولها. يتضمن مبادئ اللغة والمتغيرات وإسناد القيم لها.

Uploaded by

yahia2009
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 184

‫الول ‪:‬‬ ‫الدرس‬

‫بسم ال الرحمن الرحيم و الصلة و السلم على أشرف المرسلين سيدنا محمد و صحبه أجمعين و من تبعهم‬
‫بإحسان إلى يوم الدين‬
‫أما بعد‬
‫سنبدأ بحول ال دورة في لغة البايثون نتعرف فيها على هذه اللغة الرائعة ذات المكانيات العالية التي جمعت‬
‫بين القوة و السهولة و لقد عرفنا سابقا المشاريع الضخمة التي أنجزت بهذه اللغة وتعتبر لغة البايثون أحسن‬
‫إختيار للبدء بالبرمجة حسب رأي أغلب خبراء البرمجة لنها لغة كاملة تحتوي على جميع مبادئ البرمجة لنها‬
‫كانت سابقا عبارة عن نواة نظام تشغيل كما أن البرمجة بهذه اللغة سيزيد من إنتاجية المبرمج لنها تتيح له‬
‫الكثير من الدوال التي تسهل عليه إنشاء المشاريع الكبيرة كما أن المبرمج بلغة السي يتوجب عليه تعلم هذه اللغة‬
‫لستعمالها مع لغة السي حفظا للوقت ‪.‬‬
‫لغة البايثون لغة محمولة تستطيع البرمجة بواسطتها على كل النظمة و لكنها تعتبر مركز قوة لمستعمل نظام‬
‫لينيكس خصوصا لمنها متوافقة مع هذا النظام مما يسمح للمبرمج بالتحكم في موارد النظام بسهولة ‪.‬‬

‫خطة الدورة ‪:‬‬


‫ستكون الدورة مقسمة على ثلثة أقسام‬
‫‪ -‬القسم الول من الدورة يحتوي على مبادئ هذه اللغة و سنمر عليه بسرعة مع مراعات ذكر كل المبادئ‪.‬‬
‫‪-‬القسم الثاني من الدورة سيكون متقدما نوعا ما بحيث سندرس فيه البرمجة الجرائية و البرمجة الكائنية‬
‫بواسطة هذه للغة و سنتطرق أيضا للواجهات الرسومية في هذا القسم من الدورة‬
‫‪ -‬القسم الثالث سيخصص لبرمجة الشبكات و التطبيقات الموزعة‬
‫‪ -‬القسم الرابع سيكون مختبر الدورة بحيث سنقوم بدراسة عدة مشاريع متكاملة و ندرس كيفية تطويرها وفي‬
‫كل مرة نختار مشروع و ندرسه بصورة مركزة‪.‬‬
‫متطلبات الدورة‬
‫سنحتاج أول إلى المفسر الرسمي للغة البايثون و تستطيع تحميله من الموقع الرسمي للغة البايثون “طبعا‬
‫مستخدمي لينكس سيجدونه مثبت تلقائيا في توزيعاتهم ”‬
‫يمكنك استعمل اي محرر نصوص للعمل او اختر ‪ IDE‬مناسب‬
‫أول خطوة مع البايثون‬

‫أدات النسخ ‪print‬‬


‫طريقة إستعمال المفسر سهلة جدا و هذا راجع لسهولة اللغة بحيث ل تفرض علينا تعريفات قبل الستعمال ‪ .‬و‬
‫لطباعة الكتابة على الشاشة نستعمل المر ‪ print‬ثم نتبعه بالرسالة التي نريد طباعتها و لتشغيل البرنامج )‬
‫‪ (run‬نقوم بالضغط على ‪F9‬‬
‫ويظهر النتاتج الكود أسفل البرنامج‬

‫و نستطيع أيضا إسناد جمل لـ المتغيرات و طباعتها على الشاشة كما هو موضح في المثال التالي‬

‫– المتغيرات‬

‫كما يدل إسمها المتغيرات عبارة عن قيم قابلة ل التغير طول مدة تنفيد البرنامج فهي ل تأخذ قيمة ثابتة‬
‫بل نستطيع تغيرها متى نشاء ‪.‬‬
‫نضرب مثال‬
‫نفرض مثل أنك كتبت برنامج يقوم بحفظ أعمار وأسماء العمال في شركة معينة فيقوم العامل بإدخال‬
‫إسمه ثم عمره و يإتي عامل آخر فيقوم بنفس الشيئ وهكذا ‪.‬‬
‫تعتبر أسماء و أعمار العمال قيم نطلق علها إسم القيم ولكي نستطيع حفظ هذه القيم في ذاكرة الجهاز‬
‫يجب أن نسندها إلى متغير فيقوم المتغير بالتحاور مع الجهاز و حفظ القيم المحجوزة بداخله أو المسندة‬
‫إليه لن الجهاز يحفظ القيم بواسطة إسم المتغير و المثال التالي يوضح المر أكثر‬
‫كما نلحظ في المثال ‪ x‬تعتبر المتغير أو إسم المتغير و ‪ 10‬أو ‪ 22‬تعتبر قيمة المتغير و قلنا أن إسمه متغير‬
‫لننا نستطيع تغير قيمته متى نشاء‬
‫و لكي نستطيع حجز قيم ومعلومات في ذاكرة الجهاز لبد لنا من إسنادها إلى متغيرات لكي يستطيع الجهاز‬
‫حجزها فالجهاز يتعامل مع المعلومات أو القيم حسب أسمائها فمثل يحجز الجهاز القيمة ‪ 10‬ويطلق علها إسم ‪x‬‬
‫فإذا استدعينا ‪ x‬بالمر ‪ print‬يقوم الجهاز بالبحث عن ‪ x‬في الذاكرة ثم يقوم بتحميل قيمتها ‪.‬‬

‫تترك الغة في إختيار السماء ل المتغيرات و بكل الحرف )‪ (A>Z‬و العداد)‪ (9>0‬لكن يشترط أن يكون‬
‫أول السم عبارة عن حرف ل عدد ‪.‬‬
‫و لتستطيع إستخدام الحرف الخاصة لتسمية المتغيرات مثل ‪ $/ @ #‬و أيضا ل يمكنك تسمية المتغيرات‬
‫بالسماء المحجوزة من الطرف اللغة و المبينة في القائمة التالية‬
‫‪and‬‬ ‫‪assert‬‬ ‫‪break‬‬ ‫‪class‬‬ ‫‪continue‬‬ ‫‪def‬‬
‫‪del‬‬ ‫‪elif‬‬ ‫‪else‬‬ ‫‪except‬‬ ‫‪exec‬‬ ‫‪finally‬‬
‫‪for‬‬ ‫‪from‬‬ ‫‪global‬‬ ‫‪if‬‬ ‫‪import‬‬ ‫‪in‬‬
‫‪is‬‬ ‫‪lambda‬‬ ‫‪not‬‬ ‫‪or‬‬ ‫‪pass‬‬ ‫‪print‬‬
‫‪raise‬‬ ‫‪return‬‬ ‫‪try‬‬ ‫‪while‬‬ ‫‪yield‬‬

‫ما عدا هذا يمكنك إختيار السم الذي تشاء و لكي تسهل على نفسك المر حاول دائما إختيار إسم يكون معبر‬
‫عن عمل المتغير مثل إذا احتجت لمتغير تحجز فيه السماء سمه ‪ name‬حتى تستطيع معرفته بسهولة لنك‬
‫في المستقبل إن شاء ال ستستعمل الكثير من المتغيرات في مشروعك فإذا كان السم مناسب لن تتعب كثيرا في‬
‫البحث عن المتغير و يكون عملك منظما اكثر‪.‬‬
‫إسناد قيم ـ المتغيرات‬
‫كما قلنا سابقا يتكون المتغير من قسمين إسم وقيمة و إسناد قيمة لمتغير معين أمر سهل جدا بحيث نقوم بكتابة‬
‫إسم المتغير ثم وضع علمة = ثم قيمة المتغير‪.‬‬
‫من اروع مميزات لغة البايثون أنها تقوم بتعريف المتغير تلقائيا ففي لغة السي مثل يجب أن نعرف نوع المتغير‬

‫قبل أن نسند له قيمة‬


‫لغة البايثون تكتشف نوع المتغير تلقائيا ليس هذا فقط بل إنها تقوم بتسير موارد الذاكرة تلقائيا و هذه الميزة‬
‫الخيرة ل يعرف قيمتها إل من جرب البرمجة بلغة السي و السي ‪. ++‬‬
‫في المثلة الثلثة الذكورة في العلى يقوم الحهاز بعمل أربعة أمور‬
‫‪-‬إنشاء المتغير ثم حفظه و حفظ المعلومات الخاصة به) السم القيمة(‪.‬‬
‫‪-‬يحدد نوعه‪.‬‬
‫‪-‬يحوله إلى صيغته الخاص الصيغةأو المستعملة من طرف الجهاز المشابهة ل الصيغة التالية ‪a3 b9 fx‬‬
‫‪-‬إنشاء رابط )مؤشر( بين السم و مكان الحفظ و هذه ميزة أخرى رائعة بحيث أن اللغة تقوم يتسير المؤشرات‬
‫تلقائيا ‪.‬‬

‫نستطيع إعطاء قيمة لكثر من متغير في سطر واحد أو حتى إعطاء قيم مختلفة لمتغيرات متعددة كما يوضح‬
‫المثال التالي‬

‫وهذا مثال يقوم بحساب المساحة‬

‫كما نستطيع التعامل مع المتغيرات بكل المعاملت الرياضية) *‪ ( … + /‬كما يوجد معامل مهم هو معامل باقي‬
‫القسمة ‪%‬‬

‫تذكرو هذا المعامل جيدا لنكم ستحتاجونه كثيرا في المستقبل و خاصتا مع السلسل الحرفية‪.‬‬

‫كانت هذه مقدمة سريعة على لغة البايثون و التعامل بالمتغيرات سنحاول الختصار في المراحل الولى من‬
‫الدورة دون ظلم المبتدئين و سنتطرق لهذه المور بالتفصيل في الدروس المتقدمة ‪.‬‬
‫سندخل مباشرتا في الدرس القادم إلى الجمل الشرطية ‪.‬‬

‫تم بحمد ال‬


‫الدرس الثاني‪:‬‬
‫جمل التحكم بالمتغيرات )جمل الشرطية(‬

‫كنت أود أن ندرس السلسل الحرفية أول و لكن لكي نستفيد أكثر قررت أن ندرس الجمل الشرطية لنها سهلة‬
‫ثم نطبقها أكثر مع السلسل الحرفية و القوائم ‪.‬‬

‫أول يجب عليك أن تعلم أن عماد البرمجة بأي لغة هي الجمل الشرطية و الحلقات و السلسل الحرفية بمختلف‬
‫أنواعها و المؤشرات)في اللغات المنخفضة المستوى( و إن احتراف البرمجة ل يؤتى إل بإتقان هذه المور و‬
‫فهمها جيدا لن كل شيئ يأتي بعد هذه المور سيعتمد عليها سواء في البرمجة الكينوية ِ)‪(Class ,Method‬‬
‫أو في الواجهات الرسومية لدى إحذر أخي القارئ فطريق الحتلراف يبدئ من هنا و ل تستصغر أي شيئ لنك‬
‫ستحتاجه فيما بعد ‪.‬‬

‫نحن نعلم أن اللغة العربية تحتوي على جمل الشرط و أن هذه الجمل تتكون من قسمين جملة الشرط وجملة‬
‫جواب الشرط ‪ ,‬كذلك الحال مع لغات البرمجة بحيث أننا نقوم بكتابة الشرط ثم يليه جواب الشرط أو بالحرى‬
‫الوامر التي سينفدها البرنامج عند تحقق الشرط‬

‫الشرط >‪if< condition‬‬


‫>'‪< bloc d'instruction‬‬
‫جواب الشرط‬

‫في لغة البايثون تكون جملة الشرط على النحو التالي‬


‫‪a=10‬‬
‫‪if(a>10):‬‬
‫‪..........‬‬

‫فجملة الشرط تبتدأ دائما بعبارة ‪) IF‬إذا( ومابين القوسين يعبر عن الشرط ثم النقطتين ‪ :‬لـ الدللة على أن ما‬
‫يتبع النقطتين عبارة عن جواب الشرط أو لكي نبين للمفسر أن كل ما يأتي بعد النقتطين ينفد إذا تحقق الشرط‪.‬‬

‫‪a=1200‬‬
‫‪if(a<2000):‬‬
‫"‪print"a <2000‬‬
‫عند تحقق الشرط قام المفسر بتنفيد جواب الشرط و هو طباعة الرسالة‪.‬‬

‫ملحظة هامة ‪ :‬يجب مراعات المسافة التي يتيحها لك البرنامج بعد جملة ‪ If‬ل تعد لول السطر بل أكتب‬
‫الوامر في هذه المسافة فكل ما سيكب في هذه المسافة يعتبره المفسر تابع لجملة ‪. if‬‬

‫الن لو كان لدينا حالتين لشرط واحد يتوجب علينا إستعمال عبارة ثمسث التي تعتبر أخت جملة ‪if‬‬

‫بهذا سنكون قادرين على التعامل مع أكثر من حالة مع نفس الشرط ‪ ,‬ل يشترط كما تلحظون وضع القواس‬
‫في جملة ‪ if‬ولكن من الحسن وضعهما لكي تزيد في وضوح الكود‪.‬‬
‫وهذه بعض المعاملت التي سنحتاج إليها ل التعامل مع المتغيرات بواسطة الجمل الشرطية‬
‫‪x==y‬‬ ‫المساوات‬
‫‪x!=y‬‬ ‫عدم المساوات‬
‫‪x>y‬‬
‫‪x<y‬‬
‫‪x>=y‬‬
‫أكبر أو يساوي‬
‫‪x<=y‬‬
‫أقل أو يساوي‬

‫مثال‬
‫إكتشاف العدد زوجي أو فردي‬
‫‪a=7‬‬
‫‪if(a%2==0):‬‬
‫"‪print" a est pair‬‬ ‫‪#‬‬ ‫‪#‬عدد زوجي‬
‫‪else :‬‬
‫"‪print " a est impair‬‬
‫‪#‬عدد فرد‪#‬‬

‫أخذ المعلومات من المستعمل ‪:‬‬


‫حتى الن لم نعرف كيف نطلب من المستعمل إدخال معلومات أو أعداد وهذا ما سنعرفه الن‬
‫يوجد عبارتين أساسيتين في لغة البايثون لدخال المعلومات هما ‪ ()Input‬و ‪ ()raw_input‬و كلهما له نفس‬
‫العمل تقريبا ولكن يوجد إختلف طفيف بينهما سنعرفه في الدروس المتقدمة إن شاء ال ‪.‬‬
‫و لكي نستطيع إستعمالهما بصورة ديناميكية يجب علينا إستعمال الفسر ‪ Py******er‬و من الن فصاعدا‬
‫سنستعمل هذا المفسر لنه أحسن من المفسر الرسمي ‪.‬‬
‫بما أننا أصبحنا الن نعرف كيف نتعامل مع المستخدم سنواصل الجمل الشرطية ونطبق بعض المثلة عليها‬
‫سنقوم في المثال التالي بـ الطلب من المستخد إدخال عددين ثم ندرس حالت العددين‬
‫‪a=input('number 1‬‬ ‫)'‪:‬‬
‫‪b=input(' number 2‬‬ ‫)'‪:‬‬
‫‪if a>b:‬‬
‫‪print a," > ",b‬‬
‫‪elif a<b:‬‬
‫‪print a," < ",b‬‬
‫‪else:‬‬
‫‪print a," = ",b‬‬

‫و في التالي سنقوم بالطلب من المستخدم بإدخال عدد ثم يكتشف البرنامج إن كان العدد زوجي أو فردي‬
‫‪a=raw_input( 'Introdiusez un nombre‬‬ ‫)'‪:‬‬
‫‪if (int(a) % 2==0 ):‬‬
‫" ‪print a," est paire‬‬
‫‪else:‬‬
‫" ‪print a," est impaire‬‬

‫قمنا بالكتابة التالية‬


‫)‪int(a‬‬

‫حتى يحول المفسر قيمة ‪ a‬إلى عدد صحيح ‪ integer‬بدون فاصلة ‪.‬‬
‫ثم قسمنا هذ العدد على إثنين فإذا كان الناتج صفر فالعدد ‪ a‬زوجي و إذا كان الناتج مختلف عن الصفر فالعدد‬
‫فردي‪ .‬الن نريد أن يكون العدد المدخل من طرف المستعمل أقل من مئة فإذا كان أكبر من مئة نطبع للمستخدم‬
‫رسالة خطأ‬
‫‪a=raw_input( 'Introdiusez un nombre <100‬‬ ‫)'‪:‬‬
‫‪if (int(a) % 2==0 and int(a)<100 ):‬‬
‫" ‪print a," est paire‬‬
‫‪elif a>100:‬‬
‫‪print a," Error‬‬ ‫"‬
‫‪else:‬‬
‫"‪print a,"est impaire‬‬

‫المعامل ‪ and‬يعني "و" و المعامل ‪ or‬يعني "أو" و المعامل ‪ not‬يعني "ليس" المعامل ‪ in‬يعني "في"‬
‫أمثلة‬
‫في المثال التالي سيقوم البرنامج بالطلب من المستخدم إدخال رقم بين ‪ 0‬و ‪ 100‬فإذا أدخل المستخدم رقم أكبر‬
‫من ‪ 100‬أو أقل من ‪ 0‬سيقوم البرنامج بطباعة رسالة خطأ‬

‫))' ‪a=int(raw_input('enter any number !!(0) or >100‬‬


‫‪if( a<0 or a>100):‬‬
‫"‪print "pleas enter a nember between 1 and 99‬‬
‫‪elif (a>0 and a<100):‬‬
‫"‪print "good‬‬
‫‪else:‬‬
‫"‪print"Error‬‬
‫في المثال التالي يقوم البرنامج بالبحث عن حرف ‪ s‬في إسم المستخدم‬
‫)' ‪name =raw_input('your name pleas :‬‬
‫‪if 's' in name :‬‬
‫") ‪print " your name contain (s) char‬‬
‫‪else:‬‬
‫‪print" can't find char s in your name‬‬ ‫"‬

‫كما اننا نستطيع إستعمال ‪ in‬في الرقام كما هو موضح في المثال التالي‬
‫)' ‪number =raw_input('enter a number :‬‬
‫‪if '0' in number:‬‬
‫") ‪print " the number contain 0‬‬
‫‪else:‬‬
‫‪print" the number dos't contain 0‬‬ ‫"‬

‫و في التالي مثال يقوم بالطلب من المستخدم إدخال مبلغ مالي ثم يقوم البرنامج بحساب القيم المضافة ‪TVA‬‬
‫لهذا المبلغ علما أنه إذا كان المبلغ أقل من ‪ 1000‬فليس عليه قيمة مضافة و إذا كان المبلغ أكبر من ‪1000‬‬
‫سيطلب البرنامج من المستخدم إدخال قيمة الرسم ‪ TVA‬ثم يحسب القيمة‬
‫‪Sum =int(raw_input('Sum‬‬ ‫))' ‪:‬‬
‫‪if Sum<1000:‬‬
‫" ‪print "No TVA‬‬

‫‪else:‬‬
‫‪p =float(raw_input('TVA‬‬ ‫)) ' ‪:‬‬
‫‪TVA=(Sum*p)/100‬‬
‫‪print "TVA : ",TVA‬‬

‫علمنا بأن قيمة الرسم تكون بالفاصلة في أغلب الحيان فقمنا بتحويل العدد المدخل من طرف المستخدم إلى نوع‬
‫‪ float‬حتى يتمكن البرنامج من التعامل مع العدد المدخل‬
‫‪p =float(raw_input('TVA‬‬ ‫)) ' ‪:‬‬

‫إنتهينا الن من الجمل الشرطية و أظن أن الكثرية فهمتها لنها سهلة جدا و لكنها مازالت تتبعنا في مشوارنا‬
‫الطويل إن شاء ال و سنطبق أمثلة عليها في الدروس المقبلة‬

‫سننتقل الن إلى الحلقات التكرارية و هي الخرى سهلة جدا و لن تأخذ منا الكثير من الوقت و سنطبق الجمل‬
‫الشرطية عليها حتى تعم الفائدة ‪.‬‬

‫تم بحمد ال‬


‫الدرس الثالث‪:‬‬
‫السلم عليكم و رحمة ال و بركاته‬

‫كما يدل إسمها تستعمل الحلقات لتكرار عمل معين عدة مرات فإذا كان لدينا عمل يتوجب فعله أكثر من مرة‬
‫فبدل من أن نكتب الومر عدة مرات نقوم بإستعمال حلقة تكرارية تكرر هذا العمل ‪.‬‬
‫تحتوي لغة البايثون على نوعين من الحلقات ‪ :‬حلقة ‪ while‬و حلقة ‪ for‬نظريا كل الحلقتين تؤديان إلى نفس‬
‫النتيجة و لكن عمليا المر يختلف فكل حلقة تحتوي على خصائص معينة و هذا ما ستكتشفه في المستقبل ‪.‬‬

‫‪while( expretion) :‬‬


‫>‪<bloc d'instruction‬‬

‫تشبه الحلقات الجمل الشرطية كثيرا بل في بعض الحيان تعمل نفس عملها ‪ while‬تعني "إذا كان" و هنا نضع‬
‫شرط الحلقة إن صح التعبير مثل‬
‫‪while(i<10):‬‬

‫أو‬
‫‪while(name !=' '):‬‬

‫إستعمالتها كثيرة جدا و يبقى الستعمال الهم ل الحلقات التكرارية مع السلسل الحرفية و القواميس ‪ dico‬و‬
‫هذا ما سنراه مستقبل ‪.‬‬
‫كما قلت حالت إستعمال الحلقات كثيرة جدا و لكن نستطيع تلخيصها في حالتين أساسيتين ‪:‬‬
‫الحالة الولى تتمثل في تكرار عمل معين‬
‫‪i=0‬‬
‫‪while(i<10):‬‬
‫‪print i‬‬
‫‪i=i+1‬‬

‫سيطبع هذا البرنامج العداد من صفر إلى عشرة ‪ .‬شرط الحلقة أن يكون ‪ i‬أقل من عشرة و قلب الحلقة أو عمل‬
‫الحلقة هو طباعة المتغير ‪ i‬أما الكتابة‬
‫‪i=i+1‬‬

‫فتسمى عداد الحلقة ونستطيع إختصارها بالعبارة التالية ‪ i+=1‬وتؤدي نفس عمل العبارة السابقة ‪.‬‬
‫في قلب الحلقة‬
‫لو أردنا تحليل عمل هذه الحلقة بالتفصيل الممل نقول ‪:‬‬
‫أول سيئ يفعله المفسر هو لتحقق من شرط الحلقة ‪ i<10‬فإن وجد الشرط محقق يتجه لتنفيد عمل الحلقة و هو‬
‫‪ print i‬ثم ينزل إلى تحت فيجد العبارة ‪ i=i+1‬فيقوم بإضافة ‪ 1‬إلى ‪ i‬أي أن ‪ i‬أصبح يساوي ‪ 1‬ثم يتحقق من‬
‫الشرط ثانيتا فيجده محقق لن ‪ 10>1‬فينفد أمر الحلقة و يطبع عدد ‪ 1‬ثم ينزل إلى تحت فيجد العداد فيقوم‬
‫بإضاقة ‪ 1‬إلى ‪ i‬ثم يتحقق من شرط الحلقة مجددا ‪ .....‬وهكذا حتى يصبح ‪ i‬يساوي ‪ 9‬يقوم بطباعته على‬
‫الشاشة ثم يضيف له ‪ 1‬و عندما يتحقق من الشرط يجده غير محقق لن العبارة ‪ 10>10‬عبارة خاطئة فيقوم‬
‫المفسر بالخروج من الحلقة تماما ‪.‬‬
‫هكذا تعمل الحلقات ‪.‬‬

‫مثل لو أردنا بطبعات نفس العداد ولكن بصورة عكسية سيصبح الكود كالتالي‬
‫‪i=10‬‬
‫‪while(i>0):‬‬
‫‪print i‬‬
‫‪i=i-1‬‬

‫عكس الحلقة الولى تماما و نستطيع أيضا إستبدال العبارة ‪ i=i-1‬بـ العبارة ‪i-=1‬‬
‫كما أننا نستطيع إضافة عبارات عند نسخ رقم العداد‬
‫‪count= 0‬‬
‫‪while(count<10):‬‬
‫‪print" the index is‬‬ ‫‪:",count‬‬
‫‪count+=1‬‬

‫نستطيع إستعمال الحلقات للتأكد من شرط أي أننا نستخدمها بالطريقة التي نستخدم بها الجمل الشرطية‬
‫''=‪name‬‬
‫‪while not name :‬‬
‫‪name=raw_input(' your name pleas‬‬ ‫)'‪:‬‬

‫‪print "Welcom ",name‬‬

‫ستقوم هذه الحلقة بتكرار طلب إسم المستخدم حتى يدخل إسمه‬

‫مثال آخر‬
‫يقوم هذا المثال بجمع العداد التي يدخلها المستخدم حتى يدخل الرقم ‪ 0‬فإذا أدخل الرقم ‪ 0‬يقوم البرنامج‬
‫بإظهار الناتج‬
‫‪a,b=0,0‬‬
‫))') ‪a=int(raw_input('enter a number (0 to exit‬‬
‫‪while a>0:‬‬
‫‪b=b+a‬‬
‫))') ‪a=int(raw_input('enter a number (0 to exit‬‬

‫‪print " THE some is‬‬ ‫‪:",b‬‬

‫و المثال التالي نفس المثال الذي رأيناه سابقا )إكتشاف العدد الزوجي و الفردي( ولكن مع شرط إدخال عدد‬
‫موجب فلو أدخل المستخدم عدد سالب تقوم الحلقة بإعادة طلب الدخال حتى يدخل المستخدم عدد موجب‬

‫))' ‪a=int(raw_input('entrer uu nombre svp‬‬


‫‪while a<0:‬‬
‫" ‪print" entrer un nombre positif >0‬‬
‫))' ‪a=int(raw_input('entrer uu nombre svp‬‬
‫‪if a%2==0:‬‬
‫" ‪print a,"est paire‬‬
‫‪else :‬‬
‫" ‪print a,"est impaire‬‬

‫لم نتحدث عن جملة ‪ for‬حتى الن لن الستعمال الساسي لهذ الجملة يكون مع السلسل الحرفية كل ماعليك‬
‫الن أخي القارئ هو فهم كيفية عمل الحلقات و الجمل الشرطية و سنطبق عليهما الكثير من المثلة مع السلسل‬
‫الحرفية و القوائم ‪.‬‬

‫سيكون درسنا القادم بإذن ال مجموعة من المثلة حول الجمل الشرطية و الحلقات قبل النطلق في السلسل‬
‫الحرفية‬

‫تم بحمد ال‬


‫تمارين‪:‬‬
‫الـسـلم عليكم ورحمة ال وبركات‬
‫هذه مجموعة من التمارين حول الجمل الشرطية و الجمل التكرارية‬

‫المثال الول الة حاسبة بسيطة‬


‫"***************** ‪print" ************ Python calculator‬‬
‫))'‪a=float(raw_input('first num :‬‬
‫))' ‪b=float(raw_input('second num :‬‬
‫)'‪op=raw_input(' operator :‬‬
‫‪if op=='+':‬‬
‫)‪print "%d + %d = %d" % (a,b,a+b‬‬
‫‪elif op=='-':‬‬
‫)‪print "%d - %d = %d" % (a,b,a-b‬‬
‫‪elif op=='*':‬‬
‫)‪print "%d * %d = %d" % (a,b,a*b‬‬
‫‪elif op=='/':‬‬
‫)‪print "%d / %d = %f" %(a,b,a/b‬‬

‫أول قمنا بالطلب من المستخدم بإدخال رقمين و لقد حجزنا هذين الرقمين على صيغة ‪ float‬حتى يتمكن‬
‫البرنامج من حساب العداد بالفواصل دون مشاكل‬
‫ثم يدخل المستخدم المعامل الخاص بالعملية هنا يبدئ البرنامج بدراسة الحتمالت حسب المعامل المدخل فإذا‬
‫كان عبارة عن علمة '‪ '+‬يقوم البرنامج بجمع العددين و إظهار النتيجة و هكذا مع كل الحتمالت الخرى‬

‫المثال الثاني برنامج بسيط للتسجيل في المعهد‬

‫يقوم هذا البرنامج بالطلب من الطالب إدخال إسمه و عمره و نفرض مثل أن المعهد ل يقبل العضاء الذين‬
‫يفوق عمرهم فإذا كان عمر الطالب ‪ 23‬تحت ‪ 23‬يطلب منه البرنامج إختايار الختصاص الذي يريد التسجيل‬
‫فيه ثم يطلب منه المعدل فإذا كان المعدل مقبول و هذا حسب الختصاص‬
‫"******************* ‪print "*************** Bienvenu‬‬
‫"**************)*****(‪print "************** institut‬‬
‫)'‪name=raw_input(' Nom :‬‬
‫))' ‪age=int(raw_input(' Age :‬‬
‫‪if ( age < 18 or age > 23) or (name=='') :‬‬
‫" ‪print " Erreur invalide information‬‬
‫‪else:‬‬
‫‪print"choisissez une branche svp ! \n 1 :Reseau‬‬ ‫" ‪\n 2 : Web \n 3 : Maintenance‬‬
‫)' ‪ch=raw_input('Choix :‬‬
‫‪if ch=='1':‬‬
‫))"‪moy=float(raw_input("entrer votre moyenne :‬‬
‫‪if moy >=13 :‬‬
‫)‪print" Felicitations %s votre chois est accepte par l'admisitration" %(name‬‬
‫‪else :‬‬
print" Desole ! vous ne peuvez pas s'inscrire dans cette branche"
elif ch=='2':
moy=float(raw_input("entrer votre moyenne :"))
if moy >=12.5 & moy<13 :
print" Felicitations %s votre chois est accepté par l'admisitration" %
(name)
else :
print" Desole ! vous peuvez pas s'inscrire dans cette branche"
elif ch=='3':
moy=float(raw_input("entrer votre moyenne :"))
if moy >=11 & moy<12.5 :
print" Felicitations %s votre chois est accepte par l'admisitration" %
(name)
else :
print" Desole ! vous peuvez pas s'inscrire dans cette branche"

‫البرنامج بسيط أول نأخذ من المستخدم المعلومات‬


name=raw_input(' Nom :')
age=int(raw_input(' Age : '))

‫ثم نقوم بفحص العمر و السم‬


if ( age < 18 or age > 23) or (name==' ') :

(Choice) ‫ثم نقوم بدراسة الحالت حسب إختيار الطالب‬

‫المثال الثالث إكتشاف العدد الكبر من ثلثة ارقام‬


a=int(raw_input('A :'))
b=int(raw_input('B : '))
c=int(raw_input('C : '))

if(a == b == c):
print"A = B = C"

if (a>b & b>c) :


print" MAX : A"

if a<b & b>c:


print " MAX : B"

elif b<c:
print "MAX : C"

‫المثال الرابع ترتيب ثلث أعداد حسب قيمها‬

‫لو طلب منا الن أن نرتب العدا ترتيبا تصاعديا أي يقوم الستخدم بإدخال ثلثة أعداد فيقوم البرنامج بترتيبها‬
3 6 9 ‫ فيقوم البرنامج بترتيبها على النحو التالي‬9 3 6 ‫تصاعديا ثم يظهرها للمستخدم مثل يدخل المستخدم‬
‫أول شيئ يجب أن نعرف كم متغير نحتاجه لعمل هدا البرنامج بالتأكيد سيحتاج إلى ثلثة متغيرات يقوم بتخزين‬
‫العداد الثلثة فيها‬
‫ثانيا و هو الهم كيف سيعمل البرنامج ؟‬
‫فالنبدأ بدراسة البرنامج خطوة خطوة‬
‫لكي يرتب البرنامج العداد يجب أن يقوم بتبديل مواضعها أي تبديل أماكنها مثل فلو كان لدينا ‪ a,b,c‬وكان‬
‫‪ b>a‬سيصبح الترتيب كالتالي ‪b,a,c‬‬
‫ولكن المشكل يكمن في كيفية تبديل الماكن فلو كتبنا مثل ‪ if(a<b) a=b‬سيقوم البرنامج بإسناد قيمة ‪ b‬إلى ‪a‬‬
‫أي أن القيمة الحقيقية ل ‪ a‬قد حدفت وحلت مكانها قيمة ‪ b‬فيصبح عندنا ‪b,b,c‬‬
‫لكي نقوم بحل هدا المشكل يجب أن نضيف متغير رابع نسميه المتغير المؤقت ‪ temp‬لمادا مؤقت لننا سنحجز‬
‫فيه قيمة المتغيرات المراد تبديلها مؤقتا‬
‫فبدل ما نكتب ‪ if(a<b) a=b‬وهنا كما قلنا قد حدفنا قيمة ‪a‬تماما‬
‫نكتب‬
‫‪if(a<b):‬‬
‫‪temp=a‬‬
‫‪a=b‬‬
‫‪b=temp‬‬

‫بهذا نكون قد تمكنا من التي هي أصل قيمة ‪ a‬في ‪ b‬و هدا ما نريد ثم وضعنا قيمة المتغير ‪ temp‬و لحظو‬
‫جيدا أول وضعنا قيمة ‪ a‬فى المتغير المؤقت ‪ temp‬ثم أسندنا قيمة ‪ b‬ل ‪ a‬دون حدفهما أي منهما تبديل قيم ‪a‬‬
‫و‪b‬‬
‫و يكون كود البرنامج كالتالي‬
‫))'‪a=int(raw_input('A :‬‬
‫))' ‪b=int(raw_input('B :‬‬
‫))' ‪c=int(raw_input('C :‬‬
‫‪if a<b :‬‬
‫‪temp=a‬‬
‫‪a=b‬‬
‫‪b=temp‬‬

‫‪if a<c:‬‬
‫‪temp=a‬‬
‫‪a=c‬‬
‫‪c=temp‬‬

‫‪if b<c:‬‬
‫‪temp=c‬‬
‫‪c=b‬‬
‫‪b=temp‬‬

‫‪print " Tri‬‬ ‫‪: ",a,b,c‬‬


‫المثال الخامس إكتشاف إشارة حاصل ضرب عددين‬

‫كود بسيط يمكننا من إكتشاف إشارة حاصل ضرب عددين دون إستعمال الدوال‬
‫))'‪a=int(raw_input('A :‬‬
‫))' ‪b=int(raw_input('B :‬‬

‫‪if(a==0 or b==0):‬‬
‫)‪print "Le produit %d * %d est zero " %(a,b‬‬

‫‪elif (a >0 and b >0) or (a< 0 and b< 0) :‬‬


‫)‪print " Le signe du produit %d * %d est positif" % (a,b‬‬

‫‪else:‬‬
‫)‪print "Le signe du produit %d * %d est negatif " % (a,b‬‬

‫المثال السادس برنامج رفع قوة عدد‬


‫يقوم هذا البرنامج برفع قوة عدد حسب الس الذي يدخله المستخدم‬
‫))'‪a=int(raw_input('A :‬‬
‫))' ‪n=int(raw_input(' n‬‬
‫‪i, res =0, 1‬‬
‫‪while i<n:‬‬
‫‪res*=a‬‬
‫‪i+=1‬‬
‫‪print res‬‬
‫‪ a‬يعتبر العدد و ‪ n‬يعتبر الس بعد ذلك تقوم حلقة بضرب العدد ‪ a‬بنفسه و تخزين الناتج في المتغير ‪res‬‬

‫المثال السابع رسم مثلث‬

‫يقوم هذا البرنامج برسم مثلث و يعتبر كود البرنامج بسيط جدا لكنه يفيدك في أمور عدة‬
‫مثل الطريقة البسيطة لرسم مثلث هي عمل حلقة تقوم برسم الرمز * مثل ولكن هذا المثلث سيكون مثلث قائم‬
‫لحظو الكود‬
‫‪i=0‬‬
‫‪while i<10:‬‬
‫‪print"*"*i‬‬
‫‪i+=1‬‬
‫و سيكون المثلث على الشكل التالي‬
‫*‬
‫**‬
‫***‬
‫****‬
‫*****‬
‫******‬
‫*******‬
‫********‬
‫*********‬

‫لكننا نريد رسم مثلث متساوي الساقين كهذا‬

‫تبدئ الفكرة من الفراغات التي قبل * من جهة اليسار فلو لحظتم جيدا سترون أنها ترسم مثلث قائم مقلوب‬

‫إنطلقا من هذه الملحظة سنكتب كود يرس مثلث قائم فارغ و في نفس الوقت يرسم مثلث بواسطة الرمز*‬
‫'* '=‪et‬‬
‫' '=‪es‬‬
‫‪i=0‬‬
‫‪y=10‬‬
‫‪while i<10:‬‬
‫)‪print"%s %s" %(es*y, et*i‬‬
‫‪i+=1‬‬
‫‪y-=1‬‬

‫كما تلحظون يحتوي الكود على حلقة دات عدادين ‪ i‬و ‪ y‬يقوم العاداد ‪ i‬التصاعدي برسم علمات * و في نفس‬
‫الوقت يقوم العداد ‪ y‬التنازلي برسم فراغات قبل الرمز *‬
‫المثال الثامن رسم مستطيل‬

‫يقوم هذا البرنامج برسم مستطيل يقوم المستخدم بتحديد طوله و عرضه‬
‫'‪a='-‬‬
‫'|'=‪b‬‬
‫‪l=0‬‬
‫))'‪i=int(raw_input('larg :‬‬
‫))' ‪y=int(raw_input('long :‬‬
‫'‪print '+'+ a*i + '+‬‬
‫‪while l< y :‬‬
‫‪print b+ ' '*i+b‬‬
‫‪l+=1‬‬
‫'‪print '+'+a*i+'+‬‬

‫أول نطلب من المستخدم إدخال الطول و العرض‬


‫))'‪i=int(raw_input('larg :‬‬
‫))' ‪y=int(raw_input('long :‬‬

‫ثم يقوم البرنامج برسم الشق الول من المستطيل بواسطة الكتابة التالية‬
‫'‪print '+'+ a*i + '+‬‬

‫و ستنتج لنا الرسم التالي‬


‫‪+-------------------------------------+‬‬
‫ثم يقوم البرنامج برسم الرمز | ويليه فراغات بحسب عرض المستطيل و هذا ما تعملة الكتابة التالية‬
‫‪while l< y :‬‬
‫‪print b+ ' '*i+b‬‬

‫إذ أن الفراغات تساوي عرض المستطيل‬


‫و في الخير يرسم البرنامج الشق الخير للمستطيل المطابق للشق الول‬

‫تم بحمد ال‬


‫الدرس الرابع‪:‬‬
‫السلسل الحرفية ) الجزء الول (‬

‫تعتبر هذه الخطوة أول خطوة نحو التعمق في لغة البايثون لن السلسل الحرفية تعتبر الكثر إستعمال في‬
‫البرمجة و من يتقن السلسل الحرفية و القوائم و التعامل بها لن يجد صعوبة في تطوير برامجه وإدخال تقنيات‬
‫جديدة عليها و هي واسعة الستعمال و لن تجد كود ل يحتوي على سلسل حرفية و تستعمل خاصتا مع بنوك‬
‫المعلومات )قواعد البيانات( و التواصل عن بعد )التطبيقات الموزعة( و التحكم في الجهزة عن بعد)برمجة‬
‫الشبكات ( و التعامل مع الملفات و أمو كثيرة جدا ل يسعنا الوقت لذكرها الن ‪.‬‬
‫على كل حال ل تخف بأي طريقة من الطرق التي سندرسها في هذا الجزء من الدورة ودون كل شيئ جديد في‬
‫ورقة لن هذا مهم جدا لك ‪.‬‬

‫أول خطوة مع السلسل ‪:‬‬


‫كما يدل إسمها تعتبر السلسل الحرفية مجموعة أو سلسلة من الحروف أو الرقام المترابطة ببعضها البعض‬
‫فهي مجموعة من المتغيرات المترابطة ببعضها و المحجوزة بمتغير واحد في مكان واحد ‪.‬‬
‫"‪name="chouaib‬‬
‫"‪age="21 years old‬‬
‫‪print name‬‬
‫‪print age‬‬
‫يسمى المتغير ‪ name‬سلسلة أو ‪ string‬ونفس الشيئ ل ‪ age‬و كما موضح في المثال نقوم بكتابة إسم‬
‫المتغير ثم نسند له المحتوى‬
‫و نستطيع تجزئة السلسلة إلى أجزاء صغيرة‬
‫"‪name="chouaib‬‬
‫"‪age="21 years old‬‬
‫‪print name‬‬
‫‪print age‬‬
‫]‪print name[2‬‬
‫]‪print age[5‬‬
‫و لكن يعتبر العدد ‪ 0‬عنصر أول عنصر في السلسلة فلو كتبنا‬
‫]‪print name[0‬‬
‫سيكون الناتج ‪C‬‬
‫و نستطيع طباعة الحرف بالعد العكسي أي بدأ العد من آخر السلسة‬
‫]‪print name[2-‬‬
‫سيكون الناتج ‪i‬‬
‫و نستطيع التعامل مع السلسل بواسطة المعاملت الرياضية ‪ * +‬كما هو موضح في المثال التالي‬
‫"‪name="chouaib‬‬
‫"‪age="21 years old‬‬
‫‪nameandage=name+age‬‬
‫‪print name‬‬
‫‪print age‬‬
‫‪print nameandage‬‬
‫أو بواسطة الكتابة التالية‬
‫"‪name="chouaib‬‬
‫‪print name +" age‬‬ ‫" ‪: 21‬‬

‫نستطيع أيضا إستعمال عملية الضرب لطبع حرف عدة مرات‬


‫'‪a='a‬‬
‫'‪b='b‬‬
‫‪print a*10‬‬
‫‪print b*25‬‬
‫‪print a*10+b*25‬‬

‫و نستطيع تحديد عدد الحرف التي نريد طباعنها من سلسة معينة‬


‫"‪forum="institue moad http://moad.alestidafa.com/vb/index.php‬‬
‫]‪print forum[0:8‬‬
‫]‪print forum[9:14‬‬
‫]‪print forum[14:40‬‬

‫بهذه الطريقة نتمكن من إنشاء مجال معين لطباعة جزء معين من السلسلة‬
‫وبنفس الطريقة نستطيع التعامل مع أجزاء السلسلة بواسطة المعاملت الرياضية‬

‫"‪forum="institue moad http://moad.alestidafa.com/vb/index.php‬‬


‫]‪print forum[0:8]+forum[9:14‬‬

‫و لعمل مساحة بين العبارتين نضيف إليها " "‬


‫"‪forum="institue moad http://moad.alestidafa.com/vb/index.php‬‬
‫]‪print forum[0:8]+ " " + forum[9:14‬‬

‫و لو كانت لدينا جملة كبيرة أو عبارة كاملة نريد حجزها في سلسلة نقوم بكتابة """ قبل العبارة وننهي العبارة‬
‫بنفس الكتابة‬
‫"""=‪forum‬‬
‫"‪institue moad http://moad.alestidafa.com/vb/index.php‬‬
‫‪cours of python perl php java and more ..........‬‬
‫"""‬
‫‪print forum‬‬

‫و لكن لو كانت لدينا مجموعة من السماء مثل مختلفة و نريد حجزها في متغير واحد دون الدمج بينهما هل‬
‫نستطيع فعل ذلك ؟‬
‫أنظر المثال التالي‬
‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫‪print "name : %s %s %s %s %s " %name‬‬

‫لقد جمعنا عدة أسماء و قمنا بحجزهم في متغير واحد و العبارة ‪ %s‬تعني طباعة متغير في هذا المكان و ‪s‬‬
‫تعني ‪ string‬و عند النتهاء نقوم بتعريف المتغير الذي يحتوي على مجموعة السماء ‪name%‬‬
‫و لو قمنا بطباعة السلسلة ككل دون إستعمال المعامل ‪ %‬سيقوم البرنامج بطباعة المحتوى كامل على هذا‬
‫الشكل‬
‫)'‪('chouaib', 'moad', 'jarod', 'somebody', 'man2008‬‬

‫و لو أردنا طباعة السم الول أو الجزء الول من السلسلة فقط نقوم بكتابة‬
‫]‪print name[0‬‬

‫فيكون الناتج ‪chouaib‬‬


‫و نستطيع أيضا طباعة المحتوى الذي نريد‬
‫]‪print name[0]+ " " + name[1‬‬

‫فيكون الناتج ‪chouaib moad‬‬

‫أو إضافة عبارات أخرى بين مستقلة عن السلسلة الم‬


‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫)]‪c=len(name[1‬‬
‫‪print c‬‬
‫يكون الناتج ‪4‬‬
‫و هذه الدالة بالدات سنتخدمها كثيرا في المستقبل خاصتا مع الحلقات و هذا مثال يبين لنا إستعمال هذه الدالة مع‬
‫الحلقات‬
‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫]‪print name[i‬‬
‫‪i+=1‬‬
‫تقوم هذه الحلقة بطباعة كل محتوى السلسة و ذلك بواسطة العبارة‬
‫]‪print name[i‬‬

‫و ‪ i‬هو عداد الحلقة أي أنه سيطبع كل محتوى الحلقة بشرط أن يكون أقل من محتواها‬
‫‪while i<c:‬‬
‫و الن سنقوم بكتابة نفس البرنامج و لكنه يطبع رسالة يخبرنا بها أن العضو ‪ somebody‬غير معروف‬
‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫]‪print name[i‬‬

‫‪if name[i]=="somebody":‬‬
‫"‪print"unknown user‬‬

‫‪i+=1‬‬

‫و لو أردنا التعديل ثانيتا على الكود بحيث أنه يتوقف هذه المرة عند الوصول إلى السم الغير معروف سنقوم‬
‫بإدخال العبارة ‪break‬‬

‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫]‪print name[i‬‬

‫‪if name[i]=="somebody":‬‬
‫"‪print"unknown user‬‬
‫;‪break‬‬

‫‪i+=1‬‬
‫عبارة ‪ break‬تجبر الحلقة على الخروج عند تحقق الشرط ‪ .‬إذا سيقوم هذا الكود بطباعة الرسالة ثم الخروج‬
‫من البرنامج‬
‫سنطور الن في الكود قليل حتى يتمكن المستخدم من إدخال إسم يريد البحث عنه فيخبره البرنامج بوجود السم‬
‫إن وجده‬
‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫)'‪search=raw_input('enter the name :‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫‪if name[i]==search:‬‬
‫" ‪print search," exist in the string‬‬
‫;‪break‬‬
‫‪i=i+1‬‬

‫و لكن هذا الكود ليطبع شيئ في حالة عدم وجود السم ‪.‬‬

‫الن فكرو معي في طريقة تجعل البرنامج يخبرنا بعدم وجود السم إن كان هذا السم ليس محتوى في‬
‫المجموعة ‪.‬‬
‫قد يقول البعض منكم أن المر بسيط بإستعمال عبارة ‪ else‬وهم على حق و لكن كيف ؟‬
‫مثل لو جربنا الطريقة التالية‬

‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫)'‪search=raw_input('enter the name :‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫‪if name[i]==search:‬‬
‫" ‪print search," exist in the string‬‬
‫;‪break‬‬
‫‪else:‬‬
‫‪print "can't find this name ",search‬‬

‫‪i=i+1‬‬

‫جربوا هذا الكود و ستكتشفون الخطأ بأنفسكم مع أن الكود صحيح مئة بالمائة و لكنه ليؤدي العمل الذي نريد‬
‫بحيث أنه يقوم بطابعة الرسالة عدة مرات عندما ل يجد السم ‪.‬‬

‫لماذا ؟ لن جملة ‪ else‬مكتوبة داخل الحلقة فيقوم البرنامج بالتحقق من الشرط الول‬
‫‪if name[i]==search:‬‬

‫فإن تحقق سيقوم بتنفيد المر التالي‬


‫" ‪print search," exist in the string‬‬
‫;‪break‬‬

‫هنا كلو تمام و لكن المشكل يبدأ عندما ل يتحقق الشرط الول فيقوم البرنامج بالتوجه نحو جملة ‪ else‬ليطبع‬
‫العبارة‬
‫‪print "can't find this name ",search‬‬
‫هو يقوم بطباعتها فعل و لكن المشكل أنه يطبعها بعدد المرات التي لم يجد السم في السلسلة)عدم تحقق الشرط‬
‫الول(‬
‫من يبحث عن السم الول )‪ (chouaib‬في السلسلة لن يكتشف هذا الخطأ و لكن من يبحث عن السم الثاني و‬
‫السماء التي تليه سيكتشف الخطا فمثل لو قمنا بالبحث عن إسم )‪(jarod‬‬
‫سيكون الناتج كالتالي‬

‫‪can't find this name jarod‬‬


‫‪can't find this name jarod‬‬
‫‪jarod exist in the string‬‬

‫فالبرنامج يبقى يطبع في رسالة ‪ can't find this name‬في كل مرة لم يتحقق فيها الشرط ‪.‬‬
‫إذا المشكل يكمن في العداد سنقوم بالتغير في الكود قليل و نجبر البرنامج أن ل يطبع رسالة ‪can't find this‬‬
‫‪ name‬حتى يكون العداد في آخر السلسلة )أي أن البحث إنتهى فعل(‬

‫)"‪name=("chouaib","moad","jarod","somebody","man2008‬‬
‫)'‪search=raw_input('enter the name :‬‬
‫‪i=0‬‬
‫)‪c=len(name‬‬
‫‪while i<c:‬‬
‫‪if name[i]==search:‬‬
‫" ‪print search," exist in the string‬‬
‫;‪break‬‬
‫‪else:‬‬
‫‪if i==c-1:‬‬
‫‪print "can't find this name ",search‬‬

‫‪i=i+1‬‬

‫لقدد حللنا المشكل بواسطة هذا الكود‬


‫‪else:‬‬
‫‪if i==c-1:‬‬
‫‪print "can't find this name ",search‬‬

‫‪i=i+1‬‬

‫أي أن رسالة ‪ can't find this name‬لن تظهر حتى يكون العداد أقل من طول السلسلة بدرجة )أي أنه في‬
‫نهايتها(‬
‫جربو الكود الجديد بنفسكم و حاولو إضافت بعض الشياء الجديدة علي‬

‫سيكون الدرس القادم بعنوان التعامل مع السلسل الحرفية سندرس فيه بعض الدوال التي تتيح لنا التعامل مع‬
‫السلسل بصورة أفضل ‪.‬‬

‫تمت بحمد ال‬


‫تمارين‪:‬‬
‫السلم عليكم و رحمة ال و بركاته‬
‫و هذه مجموعة من المثلة المتعلقة بالسلسل الحرفية و التعامل معها تضعنا في المكان الصحيح قبل البدأ في‬
‫القوئم‬

‫قبل أن ننطلق يتوجب علينا تعريف الدوال لننا تكلمنا عليها كثيرا دون تعريفها‬
‫انشأت الدوال في مطلع البرمجة الجرائية و لقد أحدثت طفرة كبيرة في مجال البرمجة و لها الفضل الكبير في‬
‫تطوير لغات البرمجة حتى اصبحت كما هي عليه اليوم‬
‫و الدالة تقوم بجمع عدة أوامر و أعمال معينة )إجراءات( لتقديم نتيجة معينة فمثل لو أردنا جمع عددين نكتب‬
‫‪a=int(raw_input(' a:‬‬ ‫))'‬
‫‪b=int(raw_input(' b:‬‬ ‫))'‬
‫) ‪print " %d + %d = %d " %(a, b, a+b‬‬

‫فلو أردنا أن ننشئ دالة تقوم بجمع عددين يتوجب علينا كتابة هذا الكود داخل تعريق الدالة ثم نقوم بإستدعائها‬
‫فقط لتعطينا النتيجة‬
‫و لكي ننشئ دالة نقوم بكتابة العبارة ‪ def‬ثم تليها اسم الدالة ثم قوسين )( ثم النقطتين ‪ :‬للدللة على أن كل‬
‫مايلي النقطتين تابع للدالة‬
‫و يصبح البرنامج كالتالي‬
‫‪:()def add‬‬
‫'((‬ ‫‪:a=int(raw_input(' a‬‬
‫'((‬ ‫‪:b=int(raw_input(' b‬‬
‫‪( print " %d + %d = %d " %(a, b, a+b‬‬

‫‪()add‬‬

‫لحظو جيدا قمنا بكتابة ‪ def‬حتى يعلم المفسر أننا نريد تعريف دالة ثم قمنا بكتابة إسم الدالة ‪ add‬و السم‬
‫بالطبع إختياري تستطيع تغيره و كل ما يأتي بعد النقطتين يعتبر تابع للدالة أو بعبارة أخرى يعتبر جسم الدالة و‬
‫الوامر التي ستقوم بتنفيدها هذه الدالة‬
‫في الخير قمنا بإستدعاء الدالة بكتابة إسمها فقط ‪.‬‬
‫هذا تعريف بسيط عن الدوال و سنعود لها بعد النتهاء من دراسة القوائم بإذن ال‬

‫المثال الول‬
‫مثال بسيط جدا سنقوم بعكس محتوى سلسلة حرفية‬

‫'‪name='chouaib‬‬

‫(‪c=len(name‬‬
‫‪i=c-1‬‬

‫‪while i>=0:‬‬

‫]‪print name[i‬‬

‫‪i=i-1‬‬

‫يقوم عداد الحلقة بالتمركز على آخر حرف في السلسة ‪ c-1‬و لو كتبنا س سيحدث خطأ و لن يعمل البرنامج‬
‫لن آخر حرف في أي سلسلة يتمركز في الموضع ‪ c-1‬فالمفسر يترك الموضع الخير لعلمة ‪ /‬و التي تعني‬
‫نهاية محتوى السلسلة فالجهاز يرى هذه السلسة عبارة عن ‪. / chouaib‬‬

‫و شرط الحلقة أن يكون العداد ل يقل عن الصفر أي عندما يصل العداد إلى موضع الصفر تتوقف الحلقة ‪.‬‬

‫بعدها يبدأ البرنامج في النسخ من آخر السلسلة إلى أولها حتى ينتفي الشرط ‪.‬‬

‫المثال الثاني‬
‫سيقوم هذا بإخذ إسم من المستخدم ثم يقوم بنسخ علمة * بين كل حرف من إسم المستخدم‪.‬‬

‫)' ‪name=raw_input('enter your name :‬‬

‫)‪c=len(name‬‬

‫‪i=0‬‬

‫‪while i<c:‬‬

‫‪print name[i]+'*',‬‬

‫‪i=i+1‬‬

‫يقوم هذا الكود بنسخ حرف من إسم المستخدم ثم يضيف له العلمة * و لقد إستعملنا الفاصلة لطباعة السم في‬
‫سطر واحد‪.‬‬

‫المثال الثالث‬
‫في المثال التالي يقوم المستخدم بإدخال إسم ثم يحدد ل البرنامج الحرف الذي يريد معرفة عدد تكراره في السم‬
‫فيقوم البرنامج بحساب عدد تكرار هذا الحرف‬
‫)'‪name=raw_input('enter a name :‬‬

‫)' ‪char=raw_input('enter a character :‬‬

‫)‪c=len(name‬‬

‫‪i, y=0, 0‬‬

‫‪while i<c:‬‬

‫‪if name[i]==char:‬‬

‫‪y=y+1‬‬

‫‪i=i+1‬‬

‫‪print name," contain ",y," :",char‬‬

‫يحتوي هذا الكود كما تلحظون على حلقة واحدة وعدادين الول إي يمكن الحلقة من معاينة كل محتوى‬
‫السلسلة و العداد الثاني يقوم بحساب عدد الحرف و هذا بإضاقة ‪ 1‬في كل مرة تجد فيها الحلقة الحرف المحدد‬
‫من طرف المستعمل‪ .‬و في النهاية يقوم البرنامج بنسخ النتائج للمستعمل‪.‬‬

‫المثال الرابع ‪:‬‬

‫يقوم المثال التالي بنسخ محتوى سلسلة في سلسلة أخرى فارغة‬

‫"‪name="my name‬‬

‫""=‪name2‬‬

‫)‪c=len(name‬‬

‫‪i=0‬‬

‫‪while i <c :‬‬

‫]‪name2+= name[i‬‬

‫‪i=i+1‬‬

‫‪print name2‬‬

‫دائما نستعمل الحلقات لكي نتمكن من المرور على كل أجزاء السلسلة ثم نضيف كل حرف من السلسلة الولى‬
‫إلى السلسلة الثانية)الفارغة(‬

‫كما نستطيع عكس السم الول و حفظه في السم الثاني و ذلك بتغير شرط الحلقة على الشكل التالي‬
‫‪i=c-1‬‬

‫‪while i>=0:‬‬

‫]‪name2+= name[i‬‬

‫‪i=i-1‬‬

‫المثال الخامس‪:‬‬
‫من المثال السابق نستطيع عمل برنامج يطلب من المستخدم إدخال إسم ثم يخبره البرنامج إن كان السم‬
‫‪ Palindorm‬او ل و السم ‪Palindorme‬هو الذي ل يتغير عندما نعكسه‬

‫‪RADAR‬‬ ‫‪OBO‬‬ ‫‪SOS‬‬


‫)' ‪name=raw_input('entrer a name‬‬

‫""=‪name2‬‬

‫)‪c=len(name‬‬

‫‪i=c-1‬‬

‫‪while i>=0:‬‬

‫]‪name2=name2+name[i‬‬

‫‪i=i-1‬‬

‫‪if name==name2:‬‬

‫"‪print"palindorme‬‬

‫‪else:‬‬

‫"‪print "non palindorme‬‬

‫سيقوم البرنامج بعكس السم و حفظه في سلسلة ثانية ثم يقارن محتواهما فإن تطابقا فالسم من نوع‬
‫‪ Palindorme‬و ان لم يتطابقا فالسم ليس من نوع ‪. Palindorme‬‬
‫المثال السادس‪:‬‬
‫في هذا المثال سنستعمل سلسلتين الولى تقوم بحفظ إسم المستخدم و الثانية تقوم بحفظ كلمة المرور الخاصة‬
‫بالمستعمل‬

‫ثم يقوم البرنامج بنسخ المحتوى بكتابة اسم المستخدم و كلمة المرور الخاصة به‬

‫)' ‪name=('chouaib','moad','jarod',' somebody‬‬

‫)'‪pas=('123125','85478','99857','88475‬‬

‫)‪c=len(name‬‬

‫)‪b=len(pas‬‬

‫‪i, y=0, 0‬‬

‫‪while i<c and i<b:‬‬

‫"‪print "user :",name[i],‬‬ ‫]‪pass", pas[i‬‬

‫‪i=i+1‬‬

‫قمنا بإنشاء حلقة ذات عدادين العداد الول إي يقوم بتفحص أجزاء سلسلة السماء و نسخها و في نفس الوقت‬
‫يقوم العدادا الثاني بفحص كلمات المرور و نسخها بحيث إذا طبع العداد الول السم الول يطبع العداد الثاني‬
‫كلمة المرور الثانية و هكذا حتى تنتهي السلسلة‬

‫المثال السابع‬
‫إنطلقا من المثال السابق سنطورفي الكود قليل بحيث يقوم البرنامج بالطلب من المستخدم إدخال السم ثم كلمة‬
‫المرور ثم يتحقق البرنامج من صحة المعلومات المدخلة و يطبع رسالة للمستخدم بنجاح الدخول إذا كانت‬
‫المعلومات صحيحة أو رسالة خطأ إذا كان السم أو كلمة المرور خاطئة‬

‫)"‪user=("chouaib","lemdaoui","amir‬‬

‫)"‪pas=("5555","3333","2222‬‬

‫)‪c=len(user‬‬

‫‪i=0‬‬

‫)'‪name=raw_input('entrer votre nom :‬‬

‫)'‪psw=raw_input('entrer notre pass :‬‬


‫‪while i<c:‬‬

‫‪if user[i]==name and pas[i]==psw :‬‬

‫" ‪print "registration ok‬‬

‫‪break‬‬

‫‪else :‬‬

‫‪if i==c:‬‬

‫" ‪print "registration failed‬‬

‫‪i+=1‬‬

‫المثال الثامن‬
‫سنقوم في هذا المثال بإستدعاء مكتبة ‪ string‬حتى نتمكن من الستفادة من خصائصها‬

‫سيقوم هذا المثال بالطلب من المستخدم إدخال إسمه ثم يحول البرنامج الحرف الول من إسم المستخدم إلى‬
‫حرف كبير و يطبع له الناتج‬

‫‪import string‬‬

‫)'‪name=raw_input('entrer your name pls :‬‬

‫)‪i=len(name‬‬

‫]‪name1=string.upper(name[0])+name[1:i‬‬

‫‪print "hellow "+ name1‬‬

‫في السطر الول قمنا بإستدعاء المكتبة و هي مكتبة تضم الكثير من الدوال التي تساعدنا على التعامل مع‬
‫السلسل و قمنا بحجز إسم المستخدم في المتغير ‪ name‬و في السطر الرابع قمنا بإستعمال دالة ‪ upper‬التي‬
‫تقوم بتحويل الحروف من ‪ Min‬إلى ‪ Maj‬و لقد قمنا بتحويل الحرف الول فقط ‪ [name[0‬ثم أضفنا إليه باقي‬
‫الحروف دون تغيير‪.‬‬
‫بعض الدوال الخاصة بالتعامل مع السلسل و ستساعدنا كثيرا في المستقبل لدى أرجوا من الجميع فهمها و‬
‫سنتطرق لها بالتمارين إن شاء ال ‪.‬‬

‫** للبحث عن مكان كلمة معينة داخل سلسة نقوم بإستعمال الدالة ‪find‬‬

‫" ‪name="my name is Chouaib‬‬

‫)'‪print name.find('is‬‬

‫تقوم هذه الدالة بنسخ موضع تواجد الكلمة المحددة‪.‬‬


‫** للفصل بين عناصر السلسلة بعنصر محدد نقوم بإستعمال دالة ‪join‬‬
‫'‪Dir='Mes ********s','Python ******er‬‬
‫)‪print 'C :' + '\\'.join(Dir‬‬

‫سيكون الناتج‬
‫‪C :Mes ********sPython ******er‬‬

‫و نستطيع إستعمال الطريقة التالية‬

‫'‪name='Mohamed','Amine','Samy‬‬

‫' ‪sep= ' or‬‬

‫)‪print sep.join(name‬‬

‫و عكس هذه الدالة هي دالة ‪ split‬بحيث أن دالة ‪ split‬تقوم بتقسيم سلسلة حسب العنصر الذي نحدده لها ثم‬
‫تقوم بتحويل هذه السلسلة إلى قائمة‬

‫ل حظوا المثال التالي‬

‫'‪ame='Mohamed or Amine or Samy‬‬

‫)'‪print name.split('or‬‬

‫الناتج]"‪[size="4‬‬ ‫]‪[/size‬سيكون‬

‫]'‪['Mohamed ', ' Amine ', ' Samy‬‬


‫كما أننا نستطيع إستعمال هذه الدالة لتحويل سلسلة إلى قائمة‬
‫' ‪user='user1 user2 user3 user4‬‬

‫)(‪print user.split‬‬

‫سيكون الناتج‬
‫]'‪['user1', 'user2', 'user3', 'user4‬‬

‫** و لستبدال كلمة داخل سلسلة بكلمة أخرى نستعمل الدالة ‪replace‬‬
‫"‪name="Mohamed Amine Samy‬‬

‫)'‪print name.replace('Samy','Amar‬‬

‫هذه بعض المثلة عن التعامل مع السلسل الحرفية على كل حال سنخصص لها بعض المشاريع البسيطة حتى‬
‫نفهمها جيدا و لكن بعد دراسة القوائم ‪list‬و القواميس‬
‫سيكون درسنا القادم بإذن ال القواميس و التعامل معها‬

‫تم بحمد ال‬


‫الدرس الخامس‪]:‬القوائم والقواميس[‬

‫السلسل التي رأيناها في الموضوع السابق تمثل نوعا من أنواع المتغيرات الخاصة و المتنوعة و التي تستعمل‬
‫لتنظيم المعلومات و تسيرها و سنرى الن نوعا آخر من هذه المتغيرات و هي القوائم‪.‬‬

‫القوائم ) كما يدل إسمها( هي عبارة عن متغير يحمل بداخله قائمة من أسماء أو أعداد أو الثنين معا و مجالت‬
‫إستعمالها واسعة جدا و أكثر ما يميزها في لغة البايثون هو كثرة المكاتب و الدوال المخصصة لها و التي تسهل‬
‫التعامل معها و احذر أخي القارئ يجب عليك فهم التعامل بالقوائم جيدا لن كل ما سيأتي مرتبط بها‬

‫في لغة البايثون نستطيع تعريف قائمة كأي متغير آخر ثم نقوم بإدراج محتوى القائمة و الفصل بين المحتويات‬
‫بفاصلة كما يوضح المثال التالي‬

‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY‬‬

‫المتغير ‪ day‬يمثل إسم القائمة أما أيام السبوع فتمثل عناصر القائمة‪ .‬و نستطيع إدراج أعداد أيضا في محتوى‬
‫القائمة‬
‫‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','20‬‬
‫]'‪08‬‬

‫أو عمل قائمة تضم متغيرات عددية و حرفية‬


‫]‪day=['SATURDAY','SUNDAY','MONDAY',20,55,1895,12.65‬‬

‫و نستطيع التعامل مع محتوى القوائم بنفس الطريقة التي رأيناها في السلسل‬


‫]‪day=['SATURDAY','SUNDAY','MONDAY',20,55,1895,12.65‬‬
‫]‪print day[0‬‬
‫]‪print day[2‬‬
‫]‪print day[1:6‬‬

‫و كما قلنا سابقا أن لغة البايثون تقوم بتعريف المتغيرات تلقائيا نستطيع التعامل مع المتغيرات العددية داخل‬
‫القائمة بحرية كبيرة‬
‫]‪day=['SATURDAY','SUNDAY','MONDAY',20,55,1895,12.65‬‬
‫‪day[3]=day[3]+90‬‬
‫‪print day‬‬
‫و نستطيع أيضا إستبدال عنصر من القائمة بعنصر جديد‬
‫]‪day=['SATURDAY','SUNDAY','MONDAY',20,55,1895,12.65‬‬
‫'‪day[2]='Lundi‬‬
‫‪print day‬‬

‫و نستطيع عمل مثال ل التحقق من العضوية بواسطة القوائم لنرى الفرق بين القوائم و السلسل‬
‫[=‪database‬‬
‫‪['Lem_Chouaib','1234'],‬‬
‫‪['user01','5678'],‬‬
‫]'‪['user02','91011‬‬
‫]‬
‫)'‪username=raw_input('User name :‬‬
‫)'‪pas=raw_input('Password :‬‬
‫‪if[username, pas] in database :‬‬
‫'‪print 'Access granted‬‬

‫لحظو الفرق الكبير بين هذا البرنامج و البرنامج الذي رأيناه سابقا فهذا أكثر تنظيم و أمان ‪.‬‬

‫بحيث أننا قسمنا القائمة إلى عدة عناصر يحتوي كل عنصر على إسم المستخدم و رقمه السري وعند التحقق‬
‫من مدخلت المستخدم نقوم بالبحث داخل المجموعات فقط ‪.‬‬

‫**إضافة عنصر لقائمة ‪ :‬لضافة عنصر جديد إلى القائمة نقوم بإستعمال الدالة أبند على الشكل التالي‬
‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY‬‬
‫)'‪day.append('FRIDAY‬‬
‫‪print day‬‬
‫أو إذا كانت لدينا قائمة تحتوي على مجموعة أعداد نستطيع إضافة عدد جديد بنفس الطري‬
‫قة‬
‫]‪num=[1,2,3,4,5,6,7,8,9‬‬
‫)‪num.append(10‬‬
‫‪print num‬‬

‫** و لزالة عنصر من القائمة نقوم بإستعمال الدالة ‪ del‬على الشكل التالي‬
‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY‬‬
‫)]‪del(day[2‬‬
‫‪print day‬‬

‫** و لمعرفة عدد تكرار عنصر داخل القائمة نقوم بإستعمال الدالة ‪count‬‬
‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY‬‬
‫)'‪a=day.count('SATURDAY‬‬
‫‪print a‬‬
‫]‪num=[1,2,3,1,5,1,5,19,2,6‬‬
‫)‪a=num.count(1‬‬
‫‪print a‬‬
‫** و لضافة محتوى قائمة في قائمة ثانية نقوم بإستعمال الدالة ‪extend‬‬
‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY‬‬
‫]‪num=[1,2,3,4,5,6,7‬‬
‫)‪day.extend(num‬‬
‫‪print day‬‬

‫وكنا نستطيع جمع محتوى قائمتين بواسطة المعامل الرياضي ‪ +‬على النحو التالي‬
‫]'‪day=['SATURDAY','SUNDAY','MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY‬‬
‫]‪num=[1,2,3,4,5,6,7‬‬
‫‪day=day+num‬‬
‫‪print day‬‬

‫و سنقوم الن بعمل مثال بسيط لفهم القوائم جيدا ‪.‬‬

‫سيقوم هذا المثال بطلب من المستخدم بإدخال عشرة نقاط ثم يقوم البرنامج بعرض النقاط و مخطط بياني لهذه‬
‫النقاط ‪.‬‬
‫][=‪value‬‬
‫‪print "value‬‬ ‫"‪:‬‬
‫‪for i in range(10):‬‬
‫)))‪newvalue=int(raw_input('value %d :'% (i+1‬‬
‫]‪value+=[newvalue‬‬
‫‪print "\n Diagram‬‬ ‫"‪:‬‬
‫)"‪print "%s %10s %10s " % ("Element","Value", "Diagram‬‬
‫‪for i in range (10):‬‬
‫)]‪print "%7d %9d %s" % (i, value[i], "*" *value[i‬‬

‫أول شيئ قمنا بإنشاء قائمة فارغة حتى نحجز بداخلها النقاط التي يدخلها المستخدم ‪ ,‬ثم قمنا بإنشاء المتغير‬
‫‪ newvalue‬الذي يأخذ قيمة العدد الذي سيدخله المستخدم مع العلم أن هذا الشق من الكود سيكرر ‪ 10‬مراة‬
‫لنه مكتوب داخل حلقة ‪. for‬‬

‫بعد إدخال عشرة أعداد قمنا بإنجاز حلقة ثانية تقوم بنسخ الناتج الذي أدخله المستخدم و معنى الرقام التالية‬
‫"‪print "%7d %9d %s‬‬

‫تبين المسافة التباعد بين النتائج التي ستعرض على الشاشة حتى ل تكون النتائج ملتسقة ببعضها البعض ‪.‬‬

‫ثم قمنا بعرض رتبت العدد أول و التي تمثلها ‪ i‬ثم العدد نفسه ثم عرض نجوم بقدر العدد‪.‬‬
‫** مثل لو أردنا معرفة مكان توجد عنصر معين داخل قائمة نقوم بإستعمال الدالة ‪ index‬فتقوم هذه الخيرة‬
‫بالبحث داخل القائمة حتى تجد العنصر المطابق ‪.‬‬
‫]'‪name=['user1','user2','user3','user4‬‬
‫)'‪i=name.index('user3‬‬
‫‪print i‬‬
‫و إحذر أخي القارئ أن تخلط بين عمل هذه الدالة و دالة ‪ count‬لن دالة ‪ index‬تعطينا مكان تواجد العنصر‬
‫و دالة ‪ count‬تعطينا عدد تكراره‪.‬‬
‫راينا سابقا كيفية إضافة عنصر جديد إلى قائمة و لكن كما رأينا سيضاف هذا العنصر في آخر القائمة ‪ ,‬و لهذا‬
‫توجد دالة أخرى تعطينا الخيار لضافة عنصر جديد و في المكان الذي نريد و هي دالة ‪. insert‬‬
‫]'‪name=['user1','user2','user3','user4‬‬
‫)'‪name.insert(0,'user0‬‬
‫)'‪name.insert(5,'user5‬‬
‫‪print name‬‬

‫نقوم بتحديد مكان وضع العنصر الجديد ثم نحدد للداة العنصر الجديد ‪ .‬و نفس الشيئ لزالة عنصر نحن رأينا‬
‫سابقا الداة ‪ del‬التي يتعين علينا تحديد مكان العنصر حتى تحذف و لكن إفرض لو كنا ل نعرف مكان تواجد‬
‫العنصر و نعرف إسمه فقط ‪.‬في هذه الحالة يجب علينا إستعمال الدالة ‪remove‬‬
‫]'‪name=['user1','user2','user3','user4‬‬
‫)'‪name.remove('user4‬‬
‫‪print name‬‬

‫** و لعكس محتوى قائمة نقوم بإستعمال الدالة ‪reverse‬‬


‫]‪name=[1,2,3,4,5,6,7‬‬
‫)(‪name.reverse‬‬
‫‪print name‬‬

‫و نستطيع عكس محتوى قائمة تحتوي على اسماء أيضا‬


‫]'‪name=['user1','user2','user3','user4‬‬
‫)(‪name.reverse‬‬
‫‪print name‬‬

‫** و لترتيب محتوى قائمة أعدادا تصاعديا نقوم بإستعمال الدالة ‪sort‬‬
‫]‪num=[6,8,2,4,9,1,5,7‬‬
‫)(‪num.sort‬‬
‫‪print num‬‬

‫** و توجد دالة أخرى تساعدنا على عمل قائمة لتخزين العناصر بصورة مؤقتة و هي دالة ‪ pop‬بحيث تقوم‬
‫هذه الدالة بإستخدام العنصر ثم إزالته من القائمة‬
‫]‪note=[23,25,28,16‬‬
‫)‪ahmed = note.pop(0‬‬
‫)‪chouaib= note.pop(0‬‬
‫)‪samir=note.pop(0‬‬
‫)‪moad=note.pop(0‬‬
‫‪print " ahmed %d chouaib%d‬‬ ‫‪samir %d‬‬ ‫)‪moad %d " % (ahmed,chouaib, samir, moad‬‬
‫تقوم دالة بإسناد قيمة العنصر من القائمة إلى المتغير ثم تقوم بحذفه من القائمة تماما وهذه الميزة ستساعدنا‬
‫كثيرا لو أردنا حجز معلومات بصورة مؤقتة‪.‬‬

‫**القواميس‬

‫رأينا السلسل الحرفية و القوائم و راينا أن كل واحدة منهما تختص بمميزاتها و سنرى الن نوعا آخر من‬
‫المتغيرات المتنوعة و التي ل تختلف كثيرا عن ما رأيناه سابقا و هي القواميس ‪.‬‬

‫تستعمل القواميس لربط عنصرين مع بعضهما البعض فالقواميس تتشكل من مجموعة ثنائيات مترابطة مع‬
‫بعضها البعض فمثل لو أردنا عمل قاموس يحتوي على السم المستخدم و يليه رقم الهاتف سيكون شكله كالتالي‬
‫}'‪PhoneBook={'user01': '1234','user02' : '3456','user04' : '78910‬‬

‫كما قلنا يتشكل القاموس من مجموعات ثنائية يجب علينا أول فتح القوس الخاص ب القاموس ثم ندرج العنصر‬
‫الول و تليه نقطتان حتى نحدد للمفسر أن مايلي النقطتين تابع للعنصر الول ‪.‬‬
‫و لمعرفة رقم هاتف المستعمل نقوم بتحديد إسمه فقط على الشكل التالي‬

‫]'‪print PhoneBook['user01‬‬

‫و لنشاء قاموس جديد نقوم بتحديد إسمه على الشكل التالي‬

‫‪{}=name‬‬
‫ثم نقوم بتعبئة هذا القاموس بالبيانات الزمة‬
‫}{=‪name‬‬
‫‪name['chouaib']=03122‬‬
‫‪name['samir']=36584‬‬
‫‪name['mohamed']=65498‬‬
‫و نستطيع إدراج أكثر من بيان لعنصر ما داخل القاموس‬
‫{ = ‪name‬‬
‫{ ‪'Chouaib':‬‬
‫‪'phone': '2341',‬‬
‫'‪'addr': 'Algeria‬‬
‫‪},‬‬
‫{ ‪'Moad':‬‬
‫‪'phone': '9102',‬‬
‫'‪'addr': 'Palastine‬‬
‫‪},‬‬
‫{ ‪'Mohamed':‬‬
‫‪'phone': '3158',‬‬
‫'‪'addr': 'Egypt‬‬
‫}‬
‫}‬
‫فالقاموس ‪ name‬يحتوي على عدة قواميس فرعية بداخله كل قاموس من هذه الخيرة يحتوي على رقم هاتف‬
‫المستخدم و عنوانه‪.‬و نستطيع التطوير في البرنامج قليل حتى يشمل خاصية البحث و ذلك بإضافة الكود التالي‬
‫)' ‪user = raw_input('Name:‬‬
‫)' ?)‪request = raw_input('Phone number (p) or address (a‬‬
‫‪if request == 'p':‬‬
‫]‪if user in name: print"%s Phone numbers is %s " % (user, name[user‬‬
‫)]'‪['phone‬‬
‫‪if request == 'a':‬‬
‫)]'‪if user in name: print"%s Address is %s " % (user,name[user]['addr‬‬

‫كما تلحظون تسهل القواميس العمل علينا كثيرا خاصتا في التعامل مع المعلومات و قواعد البيانات ‪.‬‬

‫** لتفريغ محتوى القاموس تماما نقوم بإستعمال الدالة ‪clrear‬‬


‫{ = ‪name‬‬
‫{ ‪'Chouaib':‬‬
‫‪'phone': '2341',‬‬
‫'‪'addr': 'Algeria‬‬
‫‪},‬‬
‫{ ‪'Moad':‬‬
‫‪'phone': '9102',‬‬
‫'‪'addr': 'Palastine‬‬
‫‪},‬‬
‫{ ‪'Mohamed':‬‬
‫‪'phone': '3158',‬‬
‫'‪'addr': 'Egypt‬‬
‫}‬
‫}‬
‫)(‪name.clear‬‬
‫‪print name‬‬

‫كما أننا نستطيع أن نسند أكثر من قيمة لعنصر معين حسب الحاجة‬
‫‪Mail={'user01': '[email protected]','user02':‬‬
‫}]'‪['[email protected]','[email protected]','[email protected]‬‬

‫** و نستطيع نسخ قاموس داخل قاموس آخر بواسطة الدالة ‪copy‬‬
‫‪Mail={'user01': '[email protected]','user02':‬‬
‫}]'‪['[email protected]','[email protected]','[email protected]‬‬
‫)(‪mail01=Mail.copy‬‬

‫بواسطة هذه الكتابة سيقوم المفسر بإسناد كل قيم ‪ Mail‬إلى ‪mail01‬‬


‫** و نستطيع إضافة عنصر جديد لقاموس عن طريق الدالة ‪update‬‬
‫{=‪user‬‬
‫‪'name':'Mohamed',‬‬
‫‪'pass':'1234',‬‬
‫}‬
‫}'‪Phone={'Phone':'123456789‬‬
‫)‪user.update(Phone‬‬
‫‪print user‬‬

‫**و لمعرفة محتوى عنصر معين داخل قاموس نقوم بإستعماللدالة ‪get‬‬
‫{=‪user‬‬
‫{‪'Mohamed':‬‬
‫‪'name':'Mohamed',‬‬
‫'‪'pass':'1234‬‬
‫‪},‬‬
‫‪'Moad':{'name':'Moad',‬‬
‫'‪'pass':'9876‬‬
‫}‬
‫}‬
‫)‪print user.get(Mohamed‬‬

‫**و نستطيع عمل قاموس لحجز المعلومات بصفة مؤقتة كما رأينا في السلسل بواسطة الدالة ‪pop‬‬
‫{=‪user‬‬
‫{‪'Mohamed':‬‬
‫‪'name':'Mohamed',‬‬
‫'‪'pass':'1234‬‬
‫‪},‬‬
‫‪'Moad':{'name':'Moad',‬‬
‫'‪'pass':'9876‬‬
‫}‬
‫}‬
‫)'‪print user.pop('Mohamed‬‬
‫‪print user‬‬

‫سيقوم البرنامج بطباعة محتويات العنصر محمد ثم يحذفه نهائيا من القاموس‬

‫هذه أكثر الدوال إستعمال في مجال القوائم و القواميس نكون هنا قد قطعنا شوطا معتبرا في تعلم مبادئ لغة‬
‫البايثون في الدرس القادم سنقوم بدراسة أمثلة خاصة بكل ما رايناه في السلسل الحرفية و القوائم ثم ننطلق في‬
‫الجزئ الثاني من هذه الدورة‬

‫تم بحمد ال‬


‫تمارين ‪:‬‬
‫لدينا اليوم ثلث تمارين شاملة بإذن ال تعطينا نظرة بسيطة عن التعامل مع كل ما درسناه سابقا و تمهدنا‬
‫لدراسة أمور أكثر تقدما في الدروس القادمة و أريد التنبيه على الكثار من المثلة و التعديل عليها و تجريب‬
‫كل مارايناه من دوال و تطبيقها لن البرمجة ل تتعلم إل بالتطبيق أما الحفظ فلن يفيدك في شيئ إذا أخي القارئ‬
‫نصيحة قم بإضافة أشياء جديدة على المثلة التي في الدورة و غير بعض الشياء عليها واكتب ملحظاتك عليها‬
‫لن هذا المر مهم جدا‬

‫التمرين الول‬
‫فكرة هذا الترين تتمثل في إنشاء قاعدة بينات لحفظ المعلومات و يمثل هذه القاعدة قاموس نقوم بإنشائه و‬
‫نفرض مثل أن هذه القاعدة تستعمل لحفظ معلومات خاصة بالطلب يستعملها الستاذ لحفظ إسم الطالب و‬
‫النقطة المتحصل عليها ‪.‬‬
‫سنقوم بإنشاء بعض الدوال التي تساعد الستاذ على عمله و يحتوي هذا الكود على أربع دوال‬
‫الدالة ‪ ()get_name‬تقوم بأخذ السم و النقطة و حفظها داخل القاموس )قاعدة البيانات(‬
‫الدالة ‪ ()del_name‬تقوم بحذف بيانات طالب معين يقوم بتحديده الستاذ‬
‫الدالة ‪ ()show_dico‬تقوم بإظهار كل المعلومات المحجوزرة داخل القاعدة‬
‫الدالة ‪ ()search_name‬تقوم بالبحث داخل القاعدة عن طالب معين و إظها البيانات الخاصة به‬
‫إذن فالكود مقسم إلى أربع دوال لكل دالة عمل معين تقوم به و عند النتهاء من برمجة هذه الدوال نقوم‬
‫بإستدعائها بإسمها فقط‬

‫الكود‬
‫أول نقوم بتعريف المتغيرات الساسية للبرنامج و التي ستستعملها كل الدوال‬

‫‪import string‬‬
‫}{=‪database‬‬
‫‪alpha=string.letters‬‬
‫‪digi=string.digits‬‬

‫إستدعينا مكتبة ‪ string‬لكي نستفيد من مزايها ثم قمنا بإنشاء قاموس جديد إسمه ‪ database‬يقوم بحجز‬
‫البيانات المدخلة من طرف الستاذ ثم قمنا بتعريف متغيرين ‪ alpha‬و ‪ digi‬بحيث أن ‪ alpha‬يحتوي على‬
‫كل الحروف الفرنسية فلقد استعملنا دالة ‪ letters‬التي تنتمي لمكتبة ‪ string‬و تقوم هذه الدالة بإسناد كل‬
‫الحروف البجدية للمتغير ‪ alpha‬نفس الشيئ بالنسبة ‪ digi‬بحيث أن الدالة ‪ digits‬تقوم بإسناد كل الرقام لهذا‬
‫المتغير و سنرى الفائدة المرجوة من هذا العمل‬
‫أول الدالة ‪()get_name‬‬
‫‪def get_name():‬‬
‫‪i=0‬‬
‫))"‪nb=int(raw_input("number of student :‬‬
‫‪while i<nb :‬‬
‫)"‪name=raw_input(" name :‬‬
‫)"‪note=raw_input(" note :‬‬
‫‪if (name[0] not in alpha) or (note[0] not‬‬ ‫‪in digi):‬‬
‫"‪print " erreur invalid name or note‬‬
‫‪continue‬‬
‫‪else:‬‬
‫}‪info={name : note‬‬
‫)‪database.update(info‬‬
‫‪i+=1‬‬

‫إسم الدالة غير مهم بحيث أنك تستطيع تغير كما تشاء ‪.‬‬
‫أول عرفنا العداد ‪ i‬و أسندنا له قيمة الصفر ثم طلبنا من المستخدم إدخال عدد الطلب ‪ nb‬أو عدد البيانات التي‬
‫يريد إدخالها لكي نقوم بعمل حلقة يتكرر عملها حسب عدد البيانات‬
‫و انظرو بعد ذلك يبدئ عمل الحلقة بحيث ان شرط الحلقة أن يبقى العداد أقل من عدد الطلب‬
‫بعد ذلك يطلب البرنامج من المستخدم إدخال إسم الطالب و النقطة المتحصل عليها و هنا تأتي فائدة المتغير‬
‫‪ alpha‬و ‪ digi‬أنظرو جيدا إلى الجملة الشرطية‬
‫‪if (name[0] not in alpha) and (note[0] not‬‬ ‫‪in digi):‬‬

‫قمنا بإختبار السم و النقطة بحيث لو أدخل المستخدم إسم الطالب وكان أول حروفه رقم سيطبع البرنامج رسالة‬
‫خطأ للمستخدم لنه من غير المعقول أن يكون إسم طالب يبدئ برقم و نفس الشيئ بالنسبة للنقطة بحيث لو‬
‫أدخل المستخدم بدل النقطة حرف سيقوم البرنامج بإرسال رسالة خطئ و هنا عند حدوث الخطأ لن يتوقف‬
‫البرنامج او بالحرى لن تتوقف الحلقة بل ستعيد الطلب من المستخدم وهذا بواسطة العبارة‬
‫‪continue‬‬

‫أي استمر بإعادة هذا القسم من الحلقة حتى تكون المدخلت صحيحة و لو أردنا مثل أن تتوقف الحلقة تماما و‬
‫يتوقف البرنامج عند حدوث خطأ في المدخلت نقوم بإستبدال عبارة ‪ continue‬ب عبارة ‪break‬‬
‫‪else:‬‬
‫}‪info={name : note‬‬
‫)‪database.update(info‬‬
‫‪i+=1‬‬

‫هنا إذا كانت المدخلت صحيحة يقوم المتغير ‪ info‬بحجز السم و النقطة و يكون السم و النقطة مترابطان مع‬
‫بعضهما البعض بعد ذلك نحجز هذه المعلومات داخل القاموس بواسطة الدالة ‪update‬‬
‫و هكذا ستستمر هذه الحلقة حتى يبلغ العداد إي رقم الطلب ‪.‬‬
‫ثانيا الدالة ‪()del_name‬‬
‫‪def del_name():‬‬
‫)"‪del_n=raw_input(" name of student :‬‬
‫‪if del_n in database :‬‬
‫"‪print " delte " + database.pop(del_n)+ "...............‬‬
‫‪else:‬‬
‫"‪print" unknowable student‬‬

‫كما قلنا سابقا تقوم هذه الدالة بحذف بيانات طالب معين يحيث أنها تطلب من المستخدم إدخال إسم الطالب‬
‫المراد حذفه ثم تقوم بالبحث داخل القاموس إن كان هذا السم موجود فعل داخل القاموس فإن وجد ستقوم بحذفه‬
‫بواسطة الدالة ‪ pop‬إن لم يوجد سيقوم البرنامج بتنبيه المستخدم أن بيانات الطالب غير متوفرة داخل القاعدة‬

‫ثالثا الدالة ‪()show_dico‬‬


‫‪def show_dico():‬‬
‫‪for a,b in database.items():‬‬
‫‪print "name " + a + " : " +‬‬ ‫‪"note " + b‬‬

‫قمنا بإستعمال حلقة ‪ for‬في هذه الدالة و لقد قمنا بتقسيم القاموس إلى ثنائيات )حولناه إلى قائمة( ثم تقوم الدالة‬
‫بطباعة السم و المتمثل بالمتغير ‪ a‬و العلمة المتمثلة بالمتغير ‪b‬‬

‫رابعا الدالة ‪()search_name‬‬

‫‪def search_name():‬‬
‫)" ‪name=raw_input("name of student :‬‬
‫‪if name in database:‬‬
‫)‪print "result :" + database.get(name‬‬
‫‪else:‬‬
‫"‪print"unknowable student‬‬

‫تقوم هذه الدالة بالبحث عن بيانات طالب معين و هذا بواسطة العبارة‬
‫‪if name in database:‬‬

‫فلو وجد هذا السم سيقوم البرنامج بطباعة إسم و نقطة الطالب للمستخدم و إن لم يوجد سيقوم البرنامج بتنبيه‬
‫المستخدم بأن السم غير معروف داخل القاعدة ‪.‬في هذه المرحلة أنهينا برمجة الدوال و ما بقي إل استدعائها‬
‫بواسطة اسمها فقط‬
‫فمثل نكتب‬
‫‪()get_name‬‬
‫سيقوم البرنامج باستدعاء هذه الدالة و ستقوم بتنفيد عملها و لو كتبنا بعدها الدالة الثانية‬
‫‪()del_name‬‬
‫ستقوم هي الخرى بتنفيد عملها بعد الدالة الولى حسب الترتيب‬
‫و تستطيع أخي القارئ بعمل برنامج رئيسي بعد هذه الدوال فإذا كان المستخدم يريد إدخال بينات تقوم باستدعاء‬
‫الدالة ‪ ()get_name‬وإذا أراد البحث عن البيانات تقوم باستدعاء الدالة ‪ ()search_name‬و هكذا‬
‫وتستطيع عمل لئحة للمستخدم تسهل عليه الختيار‬
‫"‪print " (1): add name \n (2): search \n (3): delte \n (4): show‬‬

‫‪choic=raw_input(' Choic‬‬ ‫)'‪:‬‬


‫‪if choic=='1':‬‬
‫)(‪get_name‬‬
‫‪elif choic=='2':‬‬
‫)(‪search_name‬‬
‫‪elif choic=='3':‬‬
‫)(‪del_name‬‬
‫‪elif choic=='4':‬‬
‫)(‪show_dico‬‬

‫يكتب هذا الكود بعد النتهاء من أكواد الدوال‬

‫نكون هنا قد انهينا المثال الول و في الحقيقة سنعود لهذا المثال بالذات عند دراسة الملفات لن عمل هذا المثال‬
‫مرتبط بالملفات ‪.‬‬

‫بقي لدينا تمرينين اثنين سنتعلم من خللهما كيفية عمل مكتبة و استدعاء الدوال من خللها و سنطبق مثال على‬
‫هذا الكود الذي درسناه ‪.‬‬
‫طريقة عمل مكتبة و استدعائها‬
‫قم بكتابة الكود الخاص بالدوال على المفسر ثم اعطه اسما مثل ‪ student‬و قم بحفظه في أي مكان بصيغة ‪.‬‬
‫‪ py‬أي أن الملف يصبح ‪ student.py‬و بعد ذلك قم بنسخ هذا الملف و الصقه داخل ملف ‪ Lib‬الذي تجده‬
‫داخل مجلد ‪ python25‬و يحتوي مجلد ‪ Lib‬على كل المكاتب التي يستعملها المفسر و كل ملف تضعه داخل‬
‫هذا المجلد سيعتبره المفسر مكتبة‬

‫بعد ذلك افتح المفسر ثانيتا و قم باستدعاء هذه المكتبة التي انشئتها بواسطة العبارة‬
‫‪Import student‬‬

‫ثم اعد كتابة الكود الذي رأيناه بالعلى الخاص بالبرنامج الرئيسي‬
import student
print " (1): add name \n (2): search \n (3): delte \n (4): show \(5):Quit"

choic=raw_input(' Choic :')


while choic!='5':
if choic=='1':
student.get_name()
elif choic=='2':
student.search_name()
elif choic=='3':
student.del_name()
elif choic=='4':
student.show_dico()
choic=raw_input(' Choic :')

‫و لقد بالتعديل عليه بحيث انه سيبقى ينتظر أوامر المستخدم حتى يطلب هذا الخير الخروج من البرنامج و ذلك‬
5 ‫بإدخال رقم‬

‫و أبشر يا أخي لنك صرت تعرف كيف تنشئ مكتبة و تزيد في لغة البايثون أشياء جديدة‬
‫التمرين الثاني‬
‫فكرة هذا التمرين تكمن في برمجة اربع أوامر ‪ ftp‬ثم التعامل مع هذه الوامر‬
‫فقوم بإنشاء قائمة تلعب دور السيرفر بحيث سيحجز البرنامج الملفات التي بعتها العميل لهذا السيرفر و تمثل‬
‫هذه الوامر أربع دوال و هي‬

‫‪def open_con():‬‬
‫)'‪add=raw_input('TO :‬‬
‫‪if add[0:2]in 'www' and add[-3] in 'com':‬‬
‫)‪print "Conneecter a %s" %(add‬‬
‫‪else:‬‬
‫"‪print "address invalide‬‬

‫تقوم هذه الدالة بفتح التصال مع السيرفر‬


‫نقوم أول بالطلب من المستخدم إدخال عنوان الجهاز أو الموقع الذي يريد التصال به و حجزنا هذا العنوان‬
‫داخل المتغير ‪ add‬ثم نقوم بإختبار هذا العنوان بواسطة جملة شرطية‬
‫‪if add[0:2]in 'www' and add[-3] in 'com':‬‬

‫فإذا كانت بداية العنوان هي ‪ www‬و نهايته هي ‪ com‬فهذا يعني أن العنوان صحيح فلو تلحظوا مع العبارة جي‬
‫دا سترون أننا قطعنا العنوان إلى قسمين القسم الول يحتوي على الثلث حروف الولى من العنوان‬
‫]‪add[0:2‬‬
‫و القسم الثاني يحتوي على الثلث حروف الخيرة من العنوان‬
‫]‪add[-3‬‬
‫و دائما أأكد على معالجة مدخلت المستخدم فيجب عليك أخي القارئ أن تعتاد على هذه الطرق لن البرنامج لو‬
‫تقبل كل ما يدخله المستخدم ستكون العواقب وخيمة لدى ضع في بالك دائما كل الحتمالت الممكنة الوقوع و‬
‫عالجها كلها حتى يكون برنامجك متكامل و منطقي‬
‫بعد التحقق من العنوان نقوم بطبع رسالة للمستخدم تعلمه أن التصال نجح و لو حدث خطأ في التصال كإدخال‬
‫عنوان خاطئ سيقوم البرنامج بطباعة رسالة خطئ للمستخدم‬
‫‪def mkdir(host):‬‬
‫)" ‪nf=raw_input("nom de fichier‬‬
‫‪if nf not in host:‬‬
‫)‪host.append(nf‬‬
‫‪else:‬‬
‫"‪print" le fichier est d?ja exist dans le repertoire local‬‬

‫المر ‪ mkdir‬تجده في لينيكس و ‪ ftp‬و هو عبارة عن أمر يقوم بإنشاء مجلد جديد و هذه هي وضيفته في‬
‫هذا البرنامج بحيث أن هذه الدالة تقوم بالطلب من المستخدم بإدخال إسم الملف الذي يريد إنشائه و حجزنا إسم‬
‫الملف في المتغير ‪ nf‬ثم نقوم بالتحقق من عدم وجود الملف داخل السيرفر‬
‫‪if nf not in host:‬‬

‫فإذا تحقق الشرط تقوم الدالة بإنشاء عنصر جديد داخل القائمة بواسطة الدالة ‪ uppend‬أما عن كان العنصر‬
‫متواجد أصل داخل القائمة سيقوم البرنامج بتنبيه المستخدم بأن الملف متواجد أصل داخل المجلد‬
‫و نلحظ أن الدالة تحتوي بين القوسين الخاصين بها على كلمة ‪ host‬و التي سنعوضها في الكود الرئيسي ب‬
‫إسم القائمة فتقوم الدالة بتعويض ‪ host‬ب إسم القائمة و في الحقيقة تعتبر ‪ host‬تعديل‬
‫‪parameter‬خاص بالدالة ‪ mkdir‬و سندرس هذه المور في المرحلة القادمة‬
‫‪def rmdir(host):‬‬
‫)" ‪nf=raw_input("nom de fichier‬‬
‫‪if nf in host:‬‬
‫)‪host.remove(nf‬‬
‫‪else:‬‬
‫‪print" le fichier n'exist pas‬‬ ‫"‪dans le repertoire local‬‬
‫عكس الدالة السابقة تماما تقوم هذه الدالة بحذف ملف من المجلد الرئيسي و لكن بعد التحقق من وجوده فلو وجد‬
‫هذا العنصر ستقوم الدالة بحذفه بواسطة الدالة ‪ remove‬و إن كان غير موجود داخل القائمة سينبه البرنامج‬
‫المستخدم ان الملف غير موجود داخل السيرفر‬
‫‪def dir_rep(host):‬‬
‫‪print host‬‬
‫عمل هذه الدالة بسيط جدا بحيث أنها تقوم بطبع محتوايات المجلد‬
‫البرنامج الرئيسي‬
‫قم بحفظ هذا الملف داخل المجلد ‪ Lib‬بإسم ‪ ftp‬ثم قم بفتح البرنامج و استدعي هذا الملف و كما قلنا سابقا‬
‫سيعتبر البرنامج هذا الملف على أنه مكتبة‬
‫‪import ftp‬‬
‫][=‪serveur‬‬

‫)'‪cmd=raw_input('Command :‬‬
‫‪while cmd !='bye':‬‬

‫‪if cmd=='open':‬‬
‫)(‪ftp.open_con‬‬

‫‪elif cmd=='mkdir':‬‬
‫)‪ftp.mkdir(serveur‬‬

‫‪elif cmd=='rmdir':‬‬
‫)‪ftp.rmdir(serveur‬‬

‫‪elif cmd=='dir':‬‬
‫)‪ftp.dir_rep(serveur‬‬

‫)'‪cmd=raw_input('Command :‬‬
‫قمنا بإنشاء قائمة جديدة ‪ serveur‬و التي ستلعب دور السيرفر ‪ serveur‬بعد ذلك سيطلب البرنامج من‬
‫المستخدم إدخال المر الذي يريده و سيبقى هكذا حتى يدخل البرنامج المر ‪ bye‬و الذي يعني ‪exit‬‬
‫و ل حظوا جيدا عند استدعا أي دالة نقوم بإدراج اسم القائمة ‪ serveur‬بين قوسين فتقوم الدالة بتعويض هذا‬
‫الخير في مكان ‪ host‬اي أن كل الوضائف التي اسندناها ل ‪ host‬ستحل مكانها القائمة ‪serveur‬‬
‫هذا كل شيئ بالنسبة لهذا المثال و سنعود له أيضا في الدروس المتقدمة بإذن ال و سيكون في تلك المرحلة‬
‫عبارة عن برنامج ‪ ftp‬حقيقي‬

‫بقي لنا مثال أخير قبل أن ننطلق في مرحلة جديدة فمن لديه سؤال أو استفسار حول كل مارأيناه سابقا ل يتردد‬
‫بطرحه‬

‫التمرين الثالث‬
‫هو تمرين بسيط ل يحتوي على شفرات طويلة و لكنه سيعلمنا كيفية التحكم في المدخلت و تحويلها من صيغة‬
‫إلى أخرى و توجيهها إلى لداء الخدمة التي نريدها‬
‫التمرين عبارة عن لعبة لغوية نقو بإدخال كلمة مثل ‪ Python‬ثم يطلب البرنامج من المستخدم ادخال حرف‬
‫فإذا كان الحرف ينتمي للكلمة سيظهر مكان الحرف و الباقي مخفي و هكذا يبقى المستخدم يخمن و يجرب‬
‫الحروف حتى تكتمل الكلمة‬
‫مثل‬
‫لو ادخل المستخدم حرف ‪ t‬سينسخ البرنامج الصيغة التالية‬
‫**‪***t‬‬
‫ثم يعيد الكرة فلو ادخل حرف ‪ p‬تصبح الصيغة‬
‫‪***P*t‬‬
‫كما قلت المثال بسيط و لكنه يفيدنا جدا في التعامل مع الكلمات و التلعب بها لنك أخي القارئ ستجد نفسك‬
‫امام مشاكل غريبة جدا في المستقبل تتطلب منك معرفة جيدة بتقنيات التعامل مع الدوال و تسيرها حسب طلبك‬

‫شرح البرنامج‬
‫سنحتاج أول لتعريف المتغير الذي يحجز الكلمة المدخلة من طرفنا و سنسميه ‪word‬‬
‫عندما يدخل المستخدم الكلمة ستكون عبارة عن سلسلة ‪ string‬أي ستكون بالصيغة التالية ‪python‬‬
‫سيتوجب علينا تقسيمها و تحويلها إلى قائمة ‪ list‬على الصيغى التالية ]‘‬
‫‪ [’p’,’y’,’t’,’h’,’o’,’n‬حتى نتمكن من التعامل معها و سنسمي المتغير الذي يحجز هذه‬
‫الصيغة ‪ word_split‬و سنعرفه على انه قائمة فارغة‬
‫‪[ ]=Word_split‬‬
‫سنحتاج ايضا لقائمة تحتوي على نجوم "*" بعدد حروف الكلمة و سنسميها ‪ etoile‬بحيث هي القائمة‬
‫المستكلفة بطباعة النتائج و كما قلت يجب أن يكون عدد النجوم بنفس عدد حروف الكلمة مثل‬
‫]‘‪ [’p’,’y’,’t’,’h’,’o’,’n‬سيقابلها ]‘*’‪[’*’,’*’,’*’,’*’,’*’,‬‬

‫الن نفرض أننا ادخلنا الكلمة لكي نقوم بتحويلها إلى قائمة يجب ان ندخل عليها بعض التعديلت لدى يتوجب‬
‫علينا تعريف متغير آخر يلعب دور الواسطة بينهما و سنسميه ‪ tampon‬أي المتغير المؤقت‬
‫مثل‬
‫سندخل كلمة ‪ python‬ستكون هذه الكلمة عبارة عن ‪ string‬أي » ‪« pytohn‬‬
‫يجب ان نحولها لقائمة و لتحويلها يجب ادخال عنصر وسيط بين احرف الكلمة ثم نقسمها بواسطته‬
‫كيف‬
‫سنعمل حلقة تضيف بين كل حرف من حروف هذه الكلمة علمة | فتصبح الكلمة على الشكل التالي‬
‫» ‘‪« ’p|y|t|h|o|n‬‬
‫ثم نقوم بتحويلها إلى قائمة و يكون التقسيم على أساس هذه العلمة و يكون التقسيم بواسطة دالة ‪ split‬التي‬
‫رأيناها سابقا‬
‫‪('|')word_split= tampon.split‬‬
‫كل هذا المر يعتبر تهيئة للبرنامج ثم يأتي القسم الرئيسي‬
‫إذا نلخص‬
‫ندخل كلمة يكون نوعها ‪string‬‬
‫نأخذ هذه الكلمة و نضيف علمة | بين حروفها‬
‫ننشئ قائمة تحتوي على علمات نجوم بعدد هذه القائمة‬
‫نحول الكلمة إلى قائمة‬
‫و نبدء في التعامل مع هذه القائمة‬
‫كود البرنامج‬
‫)' ‪word=raw_input(' word :‬‬
‫][ ‪word_split, etoile=[],‬‬
‫''=‪tampon‬‬
‫‪i, l, y=0, 0, 0‬‬

‫)‪c=len(word‬‬

‫‪while y<c:‬‬
‫)'*'(‪etoile.append‬‬
‫‪y+=1‬‬

‫‪while i<c:‬‬
‫"|"‪tampon+=word[i]+‬‬
‫‪i+=1‬‬

‫)'|'(‪word_split= tampon.split‬‬

‫‪while l<c+3:‬‬
‫)"‪car=raw_input(" char :‬‬
‫‪if car in word_split and car not in etoile :‬‬
‫)‪ind=word_split.index(car‬‬
‫)‪etoile.insert(ind,car‬‬
‫)]‪etoile.remove(etoile[c‬‬
‫‪print etoile‬‬
‫‪if etoile[0:c]==word_split[0:c]:‬‬
‫"*******‪print "***** YoU WiN‬‬
‫‪break‬‬

‫‪l+=1‬‬
‫شرح الكود‬

‫أول قمنا بطلب الكلمة ‪ word‬ثم قمنا بتعريف القوائم ‪ word_split‬التي ستحجز الكلمة بعد تقسيمها و‬
‫القائمة ‪ etoile‬التي سننشئ بداخلها علمات * بنفس عدد الكلمة‬
‫ثم عرفنا المتغير ‪ tampon‬و الذي قلنا انه متغير وسيط بين الكلمة ‪ word‬و ‪word_split‬‬
‫ثم عرفنا ثلثة عدادات التي سنعتمد عليها في الحلقات‬
‫أول نقوم بحساب عدد احرف الكلمة المدخلة بواسطة الدالة ‪len‬‬

‫)‪c=len(word‬‬

‫ثم نعمل حلقة تقوم بإضافة "*" في القائمة ‪ etoile‬يعدد حروف الكلمة ‪word‬‬
‫‪while y<c:‬‬
‫)'*'(‪etoile.append‬‬
‫‪y+=1‬‬

‫ثم نقوم بإضافة علمة | بين احرف الكلمة ‪ word‬كما بينا سابقا‬
‫‪while i<c:‬‬
‫"|"‪tampon+=word[i]+‬‬
‫‪i+=1‬‬

‫هنا في هذه المرحلة من الكود لدينا القائمة ‪ etoile‬تحتوي على ]‘*’‪ [’*’,’*’,’*’,‬بنفس حروف الكلمة و‬
‫المتغير ‪ tampon‬يحتوي على الكلمة ‪ word‬و لكن مقسمة بواسطة علمة | كما رأينا في المقدمة‬
‫» ‘‪« ’p|y|t|h|o|n‬‬
‫في هذه المرحلة نستطيع تحويل المتغير ‪ word‬إلى قائمة بواسطة الدالة ‪split‬‬
‫)'|'(‪word_split= tampon.split‬‬

‫الن انتهينا من تهيئة المتغيرات و جاء دور القسم الرئيسي‬


‫أول نعمل حلقة تكون نهايتها أكبر من عدد الحروف ب ‪ 3‬دورات حتى نعطي للمستخدم فرصة‬
‫‪while l<c+3:‬‬
‫ثم نطلب من المستخدم إدخال حرف‬
‫‪car=raw_input(" char‬‬ ‫)"‪:‬‬
‫ثم يأتي الشرط الساسي‬
‫‪if car in word_split and car not in etoile :‬‬
‫نقوم بدراسة الحرف المدخل فإذا كان ينتمي للكلمة و ل يوجد في القائمة ‪ etoile‬أي ان البرنامج لم يضعه في‬
‫‪ etoile‬من قبل سيقوم البرنامج بتنفيد أربع خطوات‬
‫الخطوة الولى تكمن في معرفة مكان تواجد هذا الحرف داخل القائمة ‪word_split‬‬

‫)‪ind=word_split.index(car‬‬

‫و هذا بواسطة بواسطة الدالة ‪ Index‬و نحجز الرقم الممثل لهذا المكان في المتغير ‪ind‬‬
‫الخطوة الثانية نقوم بإدخال هذا الحرف داخل القائمة ‪ etoile‬مع مراعات المكان‬
‫)‪etoile.insert(ind,car‬‬

‫لحظو جيدا قمنا بإدخال المتغير ‪ char‬داخل ‪ etoile‬و مكان إدخاله متوافق مع ‪ ind‬أي انه سيثبت في نفس‬
‫مكان الكلمة الصلية‬
‫لكن لو تذكرو حين راينا الدالة ‪ insert‬من قبل و لو تعاملتم بها سترون انها تضيف عنصر جديد للقائمة و ل‬
‫تستبدل هذا العنصر كالدالة ‪ replace‬أي ان القائمة ‪ etoile‬ستزيد بدرجة كلما ادخلنا عنصر جديد و ل‬
‫نستطيع استعمال الدالة ‪ replace‬لنها ل تتعامل مع القوائم‬
‫هنا يواجهنا مشكل و الخطوة الثالثة تعالج هذا المشكل‬
‫الخطوة الثالثة تقوم هذه الخطوة بحذف العنصر الخير من القائمة ‪ etoile‬حتى نتخلص من مشكل ازدياد حجم‬
‫القائمة مع كل عنصر جديد‬
‫)]‪etoile.remove(etoile[c‬‬

‫استخدمنا الدالة ‪ remove‬لزالة العنصر الخير المبين في الصيغة‬


‫‪ [etoile[c‬بحيث اننا رأينا أن المتغير ‪ c‬يمثل آخر عنصر للقائمة‬
‫الخطوة الرابعة تقوم بطابعة القائمة ‪etoile‬‬
‫‪print etoile‬‬
‫و في الخير نقوم بإختبار ‪ etoile‬و ‪ word_split‬فإذا كانا متساويين فهذا يعني ان المستخدم قد نجح في‬
‫اكمال كل الكلمة فنطبع له رسالة تخبره بأنه فاز ثم نخرج من الحلقة بواسطة ‪break‬‬

‫‪if etoile[0:c]==word_split[0:c]:‬‬
‫"*******‪print "***** YoU WiN‬‬
‫‪break‬‬

‫و إذا لم تتساوى القائمتين نقوم بزيادة العداد و تعاد نفس الخطوات السابقة‬
‫‪I+=1‬‬
‫قد يقوا قائل منا أن هذا الرنامج جميل لنو افادنا في بعض المو و لكن كلعبة فليس له أي معنا لننا نحن من‬
‫ادخل الكلمة فنحن على علم مسبق بها أي أن عنصر التخمين معدوم في هذه اللعبة و هذا كلم صحيح ‪.‬‬
‫و لو أردنا اضافة عنصر التخمين على البرنامج يتوجب علينا استدعاء مكتبة ‪ random‬و هي مكتبة تحتوي‬
‫على الكثير من الدوال التي تساعد على التعامل مع الرقام و ما يهمنا من هذه المكتبة هو دالة ‪randrage‬‬
‫بحيث أن هذه الدالة تقوم باختيار اعداد بصفة عشوائية‬
‫مثل لو كتبنا‬
‫‪(random.ranrage(10‬‬
‫ستقوم الدالة باختيار عدد عشوائي محصور بين المجال )‪(10-0‬‬
‫و للستعانة بهذه الدالة نقوم بالتعديل على القسم الول من الكود فقط‬

‫‪import random‬‬
‫]'‪words=['cat','dog','watch','house‬‬
‫)‪r=random.randrange(3‬‬
‫]‪word=words[r‬‬
‫][ ‪word_split, etoile=[],‬‬
‫''=‪tampon‬‬
‫‪i, l, y=0, 0, 0‬‬

‫بحيث اننا انشئنا قائمة تحتوي على العديد من الكلمات‬


‫ثم انشئنا المتغير ‪ r‬الذي ستسند له قيمة عشوائية من ‪ 0‬إلى ‪ 3‬و هنا يجب النتباه لن العدد القصى يحب أن‬
‫يكون مساوي لعدد الكلمات‬
‫بعد ذلك يأخذ النتغير ‪ word‬الكلمة المختارة من القائمة ‪ words‬و باقي الكود يبقى على حاله دون تغير‬

‫و هنا نكون قد انتهينا من التمرين الخير في هذه المرحلة و حاول فهم هذا التمرين جيدا أخي القارئ لنه‬
‫يحتوي على فوائد كثيرة ستحتاجها في المراحل القادمة ‪.‬‬

‫تم بحمد ال‬


‫هذه بعض الفكار لحل الخوارزمية المطروحة في التمارين‬

‫اول لحذف الحروف الغير مرغوب تستطيع استعمال طريقة مشابهة لهاته‬
‫]'@'‪point=['!',':',‬‬
‫""=‪text‬‬
‫)'‪text=raw_input(' test :‬‬
‫""=‪sms‬‬
‫)‪c=len(text‬‬
‫‪i=0‬‬
‫‪while i<c:‬‬
‫‪if text[i]in point:‬‬
‫)''‪sms=text.replace(text[i],‬‬
‫‪i+=1‬‬

‫‪print sms‬‬

‫تستطيع ادراج هذا الكود في دالة و تسميها مثل ‪ ()remove_char‬و تقوم باستدعائه مرة او اثنبن حتى‬
‫تتمكن الدالة من حذف كل الحروف الغير مرغوب بها و لتصغير حروف الرسالة نستعمل الدالة ‪lower‬‬

‫"‪message=" dergr fADS ZD fbfg hbZEEZ‬‬


‫)(‪sms=message.lower‬‬
‫‪print sms‬‬
‫و للختصارات توجد عدة طرق من بينها‬
‫]'‪trans=['&','8','@','u‬‬
‫'‪message='you and me at 10pm‬‬
‫)]‪sms=message.replace('you',trans[3‬‬
‫‪print sms‬‬

‫المطلوب منك تجد طريقة يقوم بها البرنامج باستبدال جميع الكلمات مرة واحدة‬

‫المهم هذه بعض الفكار المساعدة و يبقى عليكم التعديل عليها و توجيهها لكي تؤدي العمل المطلوب ‪.‬‬
‫الدرس السادس]الدوال[‪:‬‬
‫تكلمنا سابقا عن الدوال و رأينا انها تساعدنا في تنظيم اكواد البرنامج خاصتا الطويلة منها بحيث اننا نقسم كود‬
‫البرنامج على عدة اقسام ثم نقوم ببرمجة كل قسم على حدى بحيث ان هذا القسم يكون داخل دالة و بعد النتهاء‬
‫نقوم باستدعاء الدوال و ترتيبها حسب البرنامج كما رأينا في التمرين الول )مشاركة ‪ (40‬حيث قمنا ببرمجة‬
‫اربع دوال لكل دالة عمل معين تقوم به و في الكود الرئيسي نقوم باستدعاء هذه الدوال حسب الرغبة بل رأينا‬
‫اننا نستطيع حفظ هذه الدوال و استدعائها متى تدعوا الحاجة و هنا يتبين لنا ان الدوال لها فائدة كبيرة جدا بحيث‬
‫انها تسهل علينا لعمل كما انها تختزل الوقت في كتابة الكواد بحيث انك تقوم ببرمجة الدوال التي ترى انك‬
‫تحتاجها دائما ثم تحفظها في ملف و تستدعيها في أي مرة تحتاجها‪.‬‬
‫و ل الدوال فائدة اخرى تتجلى في المساعدة على اكتشاف الخطاء افرض مثل انك كتبت برنامج يحتوي على‬
‫‪ 200‬سطر و حدث خطا في هذا البرنامج كيف ستجد مصدر الخطأ سيكون هذا كاتلبحث عن ابرة في قومة‬
‫قش فلو استعملت الدوال في الكود لن يتطلب اكتشاف الخطأ و قتا كبيرا لنك تذهب مباشرتا الى الدالة التي ل‬
‫تؤدي عملها و تقوم بتعديلها ‪.‬‬

‫ويوجد نوعان من الدوال‬


‫الدوال الفارغة )الجرائات ‪ (procedure‬هذه الدوال ا وان صح التعبير الجرائات تقوم بعمل معين دون‬
‫شرط ان تعطي نتيجة معينة أي انها ل تعود على قيمة معينة‬
‫مثل‬

‫‪def add():‬‬
‫)' ‪a=raw_input(' A :‬‬
‫)'‪b=raw_input(' B :‬‬
‫‪print "res : ",a+b‬‬

‫"***************"‪print‬‬
‫)(‪add‬‬

‫كما نلحظ الدالة تقوم بجمع عددين يدخلهما المستخدم و مع ذلك تسمى هذه الدالة اجراء لنها ل تعود بقيمة‬
‫معينة أي انها مجرد عدة اجرائات متسلسلة‬
‫الدوال )‪(function‬‬
‫الدوال التي سنتكلم عنها الن تعتبر الدوال الحقيقية و هي التي تأخذ قيم و تقوم بإجراء تعديلت عليها ثم تعود‬
‫لنا بنتيجة أي ان الدالة في الخير تعود بقيمة معينة عكس الجراءات التي ل تعود بقيمة‬
‫لحظوا نفس المثال السابق و لكن هذه المرة سنطبقه داخل دالة حقيقة‬

‫‪def add(x,y):‬‬
‫‪return x+y‬‬
‫"***************"‪print‬‬
‫))' ‪a=int(raw_input(' A :‬‬
‫))'‪b=int(raw_input(' B :‬‬
‫)‪print add(a,b‬‬

‫الفرق الول يكمن في تعريف الدالة في المرة الولى كتبنا ‪ ()def add‬بحيث ان القواس بقية خالية و نسمي‬
‫ما بين القواس بالتعديلت الخاصة بالدالة ‪parameter‬‬
‫و يكون جسم الدالة كالتالي‬
‫‪def function-name( parameter-list ):‬‬
‫‪statements‬‬

‫اول نقوم باختيار اسم الدالة )يجب ان يكون السم غير محجوز من طرف اللغة(‬
‫ثم نضع التعديلت التي نريدها )حسب عمل الدالة (‬
‫بعد ذلك نقوم ببكتابة جسم الدالة و في الخير ستعطينا الدالة النتائج المرجوة و في هذه المرحلة ستكونم قييمة‬
‫الدالة مساوية لقيمة النتيجة التي تعود عليها‬
‫نعود للمثال السابق‬
‫اول اعطينا اسما للدالة ‪ add‬ثم ادرجنا متغيرين ‪ x,y‬الذين يعتبران ‪ parameter‬للدالة ‪add‬‬
‫و هنا الدالة ستعود على قيمة ‪ x+y‬أي ان الدالة ستحجز قيمة جمع ‪ x‬مع ‪y‬‬
‫و عند استدعاء الدالة نقوم بتعويض ‪ x,y‬بالمتغيرات التي ادخلها المستخدم هنا ستقوم الدالة ‪ add‬بتعويض‬
‫‪ a,b‬مكان ‪ x,y‬أي ان الدالة ‪ add‬تصبح على الشكل التالي‬
‫‪def add(a,b):‬‬
‫‪return a+b‬‬
‫و الدالة ‪ return‬كما يدل اسمها تجبر الدالة على الحجز ناتج الجمع و لهذا نقول ان الدالة ‪ add‬تعود بقيمة‬
‫الجمع‬
‫مثال آخر‬
‫‪def count_name(name):‬‬
‫‪c=0‬‬
‫)‪c=len(name‬‬
‫‪return c‬‬

‫)' ‪user=raw_input('Name :‬‬


‫)‪print count_name(user‬‬

‫تقوم الدالة ‪ count_name‬بحساب عدد احرف اسم او عبارة‬


‫استعملنا البارامتر ‪ name‬الذي سيعوض عند استدعاء الدالة و قمنا بحساب عدد احرف ‪ name‬كأنه متغير‬
‫حقيقي و في النهاية تعود الدالة بقيمة ‪ c‬الذي يحتوي على عدد حروف البارامتر‬
‫و عند الستدعاء نعوض البارامتر بالمتغير الذي نريد و ستقوم الدالة بحساب عدد احرف المتغير و طباعة عدد‬
‫أحرفه‬
‫و البارامتر يستطيع ان يكون واحد او اثنين او ثلثة او اكثر حسب الحاجة و يجب علينا الحذر عند التعامل معه‬
‫لن مجموعة البارمترات يجب ان تلبي رغبات الدالة أي تشمل كل ما تحتاجه الدالة لكي تؤدي عملها على‬
‫اكمل وجه‬
‫ل حظوا المثال التالي‬
‫‪def max_value(a,b,c):‬‬
‫‪mx=a‬‬
‫‪if b>mx:‬‬
‫‪mx=b‬‬
‫‪if c>mx:‬‬
‫‪mx=c‬‬
‫‪return mx‬‬
‫))' ‪w=int(raw_input(' A :‬‬
‫))' ‪y=int(raw_input(' B :‬‬
‫))' ‪z=int(raw_input(' C :‬‬

‫"******************‪print "************** result‬‬


‫‪print " the maximam value is : ",max_value(w,y,z‬‬

‫نفس الترتيب نقوم بتسمية الدالة ثم نعطيها البارامترات التي تحتاجها أو بالحرى التي نحتاجها نحن‬
‫ثم نقوم بكتابة الكود عادي جدا كأننا نتعامل مع متغيرات حقيقية‬
‫و في النهاية تعود الدالة على النتيجة المرجوة وهي هنا تتمثل في أكبر قيمة من بين ثلث قيم‬
‫و عند استدعاء الدالة نعوض البارامترات بالمتغيرات التي ادخلها المستخدم ثم نقوم بطبعه النتيجة معتمدين على‬
‫القيمة التي تحتويها الدالة )التي تعود إليها (‪.‬‬
‫اظن ان فكرة الدوال بدئت تتضح قليل و نضع تلخيص لما رايناه الجراء عبارة عن دالة فارغة أي انها ل‬
‫تعود على قيمة معينة الدالة تأخذ بارامتلرات و تعود على نتيجة معينة و نستطيع ان نتعامل مع الدالة كأي‬
‫متغير آخر عكس الجراءات‬
‫مثل‬

‫‪def add(x,y):‬‬
‫‪return x+y‬‬
‫"***************"‪print‬‬
‫))' ‪a=int(raw_input(' A :‬‬
‫))'‪b=int(raw_input(' B :‬‬
‫)‪print add(a,b‬‬
‫‪print add(a,b)*2‬‬

‫ل حظوا لقد قمنا بضرب الدالة في ‪ 2‬لن الدالة في هذه المرحلة تعبر عن القيمة التي تحتويها كما أننا نستطيع‬
‫التعامل معها بباقي المعاملت الرياضية و حتى في الجمل الشرطية‬
‫‪def add(x,y):‬‬
‫‪return x+y‬‬
‫"***************"‪print‬‬
‫))' ‪a=int(raw_input(' A :‬‬
‫))'‪b=int(raw_input(' B :‬‬
‫)‪print add(a,b‬‬
‫‪if add(a,b)>20:‬‬
‫"‪print " the result of A + B is bigger than 20‬‬
‫كما اننا نستطيع ان نسند قيمة الدالة للمتغير آخر‬
‫)‪y=add(a,b‬‬
‫المتغيرات في الدوال‬
‫نواصل مع الدوال و هذه المرة سنتحدث عن المتغيرات في الدوال و الموضوع مهم جدا لدى ارجوا منكم‬
‫اخواني الكرام التركيز جيدا ‪.‬‬
‫عند استعمال الدوال يتغير استعمال المتغيرات بالطريقة التي اعتدنا عليها لن المتغيرات تنقسم إلى قسمين‬
‫المتغيرات الكلية ‪ global variable‬و تعرف هذه المتغيرات في الكود الرئيسي و تستطيع أي دالة استعمالها‬
‫لنها متغيرات كلية تابعة للبرنامج ككل‬
‫مثل‬
‫‪x=2‬‬
‫‪def a():‬‬
‫‪print x‬‬
‫)(‪a‬‬

‫كما نلحظ عرفنا المتغير ‪ x‬في الكود الرئيسي و لقد استعملنا هذا المتغير داخل الدالة ‪ a‬دون مشاكل لن‬
‫المتغير ‪ x‬متاح لكل الدوال المكتوبة داخل كود البرنامج‬
‫المتغيرات الداخلية ‪ local variable‬تسمى هذه الدوال بالدوال الداخلية لنها تعرف داخل دالة و ليس في‬
‫الكود الرئيسي و تستطيع الدالة التي عرف المتغير داخلها استعمال هذا المتغير بكل حرية و لكن الدوال‬
‫الخرى ل تستطيع استعمال هذا المتغير لنه تابع للدالة التي عرف داخلها‬

‫‪def a():‬‬
‫‪x=22‬‬
‫‪print x‬‬
‫‪def b():‬‬
‫‪print x*2‬‬
‫)(‪a‬‬
‫)(‪b‬‬

‫عند تنفيد هذا الكود سيرسل المفسر رسالة خطأ كالتالي‬


‫‪Exeptions.Name.Error :global name ‘X’ is not defined‬‬
‫و معنى الرسالة ان المتغير ‪ X‬غير معروف و سبب لنا هذا الخطأ الدالة ‪ b‬لننا استعملنا المتغير ‪ x‬داخلها و‬
‫ليس لها الصلحية باستعمال هذا المتغير لنه تابع للدالة ‪ a‬و هذه هي المتغيرات الداخلية ‪local‬‬
‫إذا نلخص‬
‫تنقسم المتغيرات إلى قسمين المتغيرات ذات النوع ‪ global‬و هي التي تعرف في الكود الرئيسي و تستطيع أي‬
‫دالة استعمالها و القسم الثاني يعتبر هي المتغيرات ذات النوع ‪ local‬و هي المتغيرات التي تعرف داخل الدوال‬
‫و ل تستطيع الدوال الخرى استعمالها لنها تبقى تابعة للدالة التي عرفت داخلها‬
‫الن نركز قليل‬
‫نحن لما نعرف متغير في الكود الرئيسي و ننشئ دالة قطعا ستستطيع هذه الدالة التعامل مع هذا المتغير و لكن‬
‫هل تستطيع التغير في محتواة ؟؟‬
‫ل حظوا المثال التالي‬
‫‪def a():‬‬
‫‪print x*3‬‬
‫‪x=2‬‬
‫)(‪a‬‬
‫‪print x‬‬

‫انظروا مع ناتج هذا الكود سيطبعه البرنامج في المرة الولى ‪ 6‬و هذا هو الجزء التابع للدالة و في المرة الثانية‬
‫يطبع ‪2‬‬
‫لماذا ؟؟‬
‫من المفروض ان يطبع ‪ 6‬و في المرة الثانية ‪ 6‬لننا نتعامل مع متغير واحد أي ان الدالة ‪ a‬قد غيرت محتوى‬
‫المتغير ‪ x‬فلماذا يعود لصله في المرة الثانية ؟؟ !!‬
‫هنا نستنتج ان الدالة ل تستطيع تغير محتوى المتغير حتى و ان كان متغير ‪ global‬سيحدث التغير داخل الدالة‬
‫فقط ثم يعود لصله‬
‫مثال آخر‬
‫‪def a():‬‬
‫‪print x*3‬‬
‫‪def b():‬‬
‫‪print x*9‬‬
‫‪x=2‬‬
‫)(‪a‬‬
‫)(‪b‬‬
‫‪print x‬‬

‫لحظوا كل دالة استطاعة التعامل مع المتغير ‪ x‬و استطاعة تغير محتواه و لكن بصفة مؤقتة فقط او بالحر‬
‫استطاعة التغير عليه داخل صلحياتها فقط اما خارج حدود الدالة سيعود المتغير لصله و هي القيمة ‪2‬‬
‫نلخص مرة أخرى‬
‫تستطيع الدالة التعامل مع المتغير ‪ global‬بكل حرية و لكنها ل تستطيع تغير قيمته بصورة نهائية و انما‬
‫تستطيع التغير في قيمته داخل صلحيتها فقط ثم يعود المتغير إلى قيمته الصلية و هي التي عرف بها في الكود‬
‫الرئيسي ‪.‬‬
‫الن ماذا لو احتجنا لتغير قيمة المتغير داخل دالة كيف سنعطي الصلحية لهذه الدالة لتغير قيمة المتغير بصورة‬
‫نهائية ؟؟‬
‫هنا يتوجب علينا استعمال العبارة ‪ global‬داخل الدالة لكي نبين للمفسر ان هذه الدالة لها الصلحيات الكاملة‬
‫في تغير محتوى المتغير‬
‫مثال‬
‫‪def a():‬‬
‫‪global x‬‬
‫‪print" global x in function a()",x‬‬
‫‪x*=10‬‬
‫‪print"global x*10 in function a()",x‬‬
‫‪x=7‬‬
‫‪print "global x in code of programme before fun a()",x‬‬
‫)(‪a‬‬
‫‪print "global x in code of programme after fun a()",x‬‬
‫ل حظو جيدا‬
‫اول طبعنا رسالة تبين قيمة ‪ x‬قبل استدعاء الدالة ‪a() =========>7‬‬
‫ثانيا طبعنا رسالة تبين ‪ x‬داخل الدالة ‪ a‬لكن قبل التغير ‪x =========> 7‬‬
‫ثالثا طبعنا رسالة تبين ‪ x‬داخل الدالة ‪ a‬بعد التغير ‪x============>70‬‬
‫رابعا طبعنا رسالة تبين ‪ x‬خارج الدالة ‪) a‬في الكود الرئيسي( بعد استدعاء الدالة ‪a x=====>70‬‬
‫و هنا نكون قد تعلمنا كيف نغير في قيمة المتغير الرئيسي داخل الدالة بصورة نهائية‬

‫ملحظة ‪:‬‬
‫ليس بالضرورة تغير قيمة المتغير داخل الدالة بصورة نهائية في كل مرة و انما عند الحاجة فقط أي اذا كانت‬
‫تحتاج تغير قيمة المتغير داخل الدالة بصورة نهائية فاستعمل العبارة ‪ global‬اما اذا كنت ل تحتاج هذا التغير‬
‫النهائي فاستعمل الطريقة التي رأيناها سابقا‬
‫أي لك الخيار في استعمل هذه الطرق حسب الحاجة ‪.‬‬

‫و هنا الخبرة و الممارسة تلعب دور في اختيار نمط العمل و ستكتسب هذه الخبرة من كتابة الكثير من الكواد‬
‫لن مهمة كتابة كود خالي من الثغرات تبدئ من اختيار المتغيرات و تحديد انواعها و التعامل بهذه المتغيرا‬
‫بواسطة الدوال‬

‫مثال شامل يوضح لنا المتغيرات بصورة احسن‬

‫‪def a():‬‬
‫‪x = 25‬‬
‫"‪print "\nlocal x in a is", x, "after entering a‬‬
‫‪x += 1‬‬
‫"‪print "local x in a is", x, "before exiting a‬‬
‫‪def b():‬‬
‫‪global x‬‬
‫"‪print "\nglobal x is", x, "on entering b‬‬
‫‪x *= 10‬‬
‫"‪print "global x is", x, "on exiting b‬‬
‫‪print "global x is", x‬‬
‫‪x = 7‬‬
‫‪print "global x is", x‬‬
‫)(‪a‬‬
‫)(‪b‬‬
‫)(‪a‬‬
‫)(‪b‬‬
‫‪print "\nglobal x is", x‬‬

‫استعملنا في هذا المثال دالتين‬


‫الدالة ‪ a‬و الدالة ‪b‬‬
‫عرفنا متغيرين و المتغيرين لهما نفس السم ‪x‬‬
‫المتغير الول تابع للدالة ‪()a‬‬
‫‪def a():‬‬
‫‪x = 25‬‬
‫"‪print "\nlocal x in a is", x, "after entering a‬‬
‫‪x += 1‬‬
‫"‪print "local x in a is", x, "before exiting a‬‬

‫يبتدئ بقيمة ‪ 25‬ثم يضاف لهذه القيمة ‪1‬‬


‫و طبعا سيكون ناتج الطباعة ‪ 25‬في المرة الولى و ‪ 26‬في المرة الثانية‬
‫المتغير الثاني متغير ‪ X‬أيضا لكنه من نوع ‪ global‬و يبتدئ بقيمة ‪7‬‬
‫‪x = 7‬‬

‫الدالة ‪ ()b‬تستعمل المتغير ‪ x‬الخاص بالكود الرئيسي )‪ (global‬الذي يبتدئ بقيمة ‪ 7‬كما ذكرنا سابقا و‬
‫تقوم هذه الدالة بضرب المتغير في ‪10‬‬
‫و ناتج الطباعة سيكون ‪ 7‬في المرة الولى و ‪ 70‬للمرة الثانية و الثالثة‬
‫و في الكود الرئيسي استدعينا الدوال وفق الترتيب التالي‬
‫‪print "global x is", x‬‬
‫)(‪a‬‬
‫)(‪b‬‬
‫)(‪a‬‬
‫)(‪b‬‬
‫‪print "\nglobal x is", x‬‬

‫في المرة الولى سيطبع ‪ 7‬عادي‬


‫في المرة الثانية سيكبع ‪ 25‬و ‪ 26‬لننا استدعينا الدالة ‪ ()a‬التي ل تتعامل مع المتغير الرئيسي بل تستعمل‬
‫متغير خاص بها و بالرغم من ان السم متشابه )‪ (X‬فالمتغير يعتبر ان ‪ x‬التابعة ل ‪ ()a‬مختلفة عن ‪ x‬التابعة‬
‫للدالة ‪ ()b‬و الكود الرئيسي‬

‫في المرة الثانية سيطبع‬


‫‪ 7‬و ‪ 70‬ثم ‪ 70‬و هنا نكون قد عدلنا على المتغير الرئيسي ‪ x global‬و لم تبقي قيمته ‪ 7‬بل تحولت إلى ‪70‬‬

‫في المرة الثالثة يطبع ‪ 25‬ثم ‪ 26‬و هذا يأكد لنا مرة أخرى ان المفسر يفرق بين ‪ x‬التابعة ل ‪ ()a‬و ‪ x‬الرئيسية‬

‫في المرة الخيرة ل يطبع ‪ 70 70 7‬لماذا ؟؟‬


‫لننا قلنا أن المتغير ‪ x‬قد تغيرت قيمته تماما و اصبحت ‪ 70‬بدل ‪7‬‬
‫أي انه في هذه المرة سيطبع ‪700 700 70‬‬

‫ارجوا ان يكون هذا الشرح البسيط قد قرب المور إليكم و أجاب على بعض تساؤلتكم‬
‫الدرس السابع ]التعامل مع الخطاء[‪:‬‬
‫تعتبر الخطاء في البرمجة من أكبر الخطار التي تهدد البرنامج سواء من الجهة المنية )الثغرات( أو من‬
‫جهة الفعالية )السرعة و الثبات(‬
‫كما أن الخطاء تسبب الحباط للمبرمج و تنقص من فعاليته و تركيزه أثناء كتابة الكود و هذا ما يؤدي إلى‬
‫انخفاض مستوى انتاجية المبرمج و تهدر وقته و جهده‬
‫و المبرمج المتمكن هو الذي يستطيع كتابة أكواد بأقل عدد من الخطاء‬
‫و المبرمج المحترف هو الذي يستطيع كتابة أكواد دون أخطاء تقريبا و يستطيع أن يكتشف الخطاء بنوعيها‬
‫)سنتكلم عن النواع( من النظرة الولى للكود‬
‫و في الحقيقة يعتبر هذا المبرمج من صنف المطورين و لقد تكلمت في المقال عن الفرق بين المبرمج و‬
‫المطور‬
‫و تنقسم الخطاء في البرمجة إلى نوعين‬
‫الخطاء الكتابية ‪ :‬و هي الخطاء الكتابية في الكود كنسيان حرف أو كتابة عبارة مجهولة ل تحتويها اللغة مثل‬
‫في العوض ان نكتب ‪ else‬كتبنا ‪ elqe‬أو نسيان النقطتين بعد عبارة ‪ ... if‬الخ‬
‫و هذا النوع من الخطاء هو السهل في الكتشاف لنك بمجرد ان تنفد البرنامج سيحدد لك المفسر مكان‬
‫الخطئ فتقوم بتصليحه‬
‫الخطاء المنطقية ‪ :‬كما يدل اسمها تعتبر هذه الخطاء منطقية أي ان الكود أو جزء منه غير منطقي ترى الكود‬
‫ينفد بدون مشاكل لكن ل يقوم هذا الكود بعمله‬
‫و ل يعطينا النتائج المرجوة منه‬
‫مثال‬
‫)'‪age=raw_input('enter your age :‬‬
‫‪if age>18:‬‬
‫'‪print' OK.........‬‬
‫‪else:‬‬
‫'‪print'NO...............‬‬
‫نفذوا هذا الكود عندكم سيشتغل دون مشاكل لكن ل يعطينا النتائج المرغوبة لنه يقوم بطبع الرسالة الولى‬
‫بالرغم اننا ادخلنا عدد أقل من ‪18‬‬
‫هذا احسن مثال عن الخطاء المنطقية ‪.‬‬
‫الكود من الناحية الكتابية صحيح لكن من الناحية المنطقية غير صحيح‬
‫لنن المتغير ‪ age‬من النوع الحرفي و في عبارة الشرط تعاملنا معه على أنه متغير عددي‬
‫و لتصحيح هذا الخطئ يجب ان نحدد للمفسر أن المتغير ‪ age‬متغير عددي و ذلك بإضافة ‪ int‬فتصبح العبارة‬
‫كالتالي‬

‫))'‪age=int(raw_input('enter your age :‬‬


‫تعتبر الخطاء المنطقية الصعب على الطلق لنه يصعب علينا اكتشافها و تتطلب قراءة الكود و تحليله من‬
‫الول إلى الخر ‪.‬‬
‫و أريد أن أنوه أن إكتشاف الخطاء المنطقية يتطلب خبرة و ممارسة كبيرة في البرمجة و القدرة على تحليل‬
‫الكود و فهم كيفية عمله منطقيا أي انك لكي تكتشف الخطاء المنطقية يجب عليك التعامل مع هذه الخطاء‬
‫بنفس نوعيتها و يلزمك لهذا تحليل الكود و فهم طريقة عمله و هذا كما قلت يتطلب بعض الشيئ من الخبرة‬
‫توجد الكثير من الطرق للتقليص من الخطاء المنطقية و الحد من خطورتها من هذه الطرق‬
‫• تنظيم الكود و تقسيمه إلى دوال بحيث ان كل عمل معين تتكفل به دالة و هذا سيفيدنا بثلث أمور‬
‫تنظيم الكود‬
‫إكتشاف الخطاء المنطقية بسهولة و ذلك بالتجاه مباشرتا للدالة التي ل تعمل جيدا دون البحث في كافة الكود‬
‫الستفادة من الدوال في اكواد أخرى و ذلك بحفظها على هيئة مكتبة كما رأينا سابقا‬
‫• استعمال طريقة تسير الخطاء ‪try-except‬‬
‫تعتبر هذه الطريقة من أهم الطرق لتفادي الخطاء و تنظيم الكود و هي ما يهمنا الن‬
‫شرح الطريقة‬
‫نحن كما سنرى بإذن ال في البرامج المستقبلية سيتغير شكل الكود تماما بحيث انه يصبح مقسم لعدة أقسام مثل‬
‫مقسم لعدة دوال )او كلس ‪ class‬او ثريد ‪ (thread‬و كل قسم او جزء مرتبط بالجزاء الخرى بحيث ان‬
‫مخرجات جزء معين او بالحرى نتائجه تصب في مدخلت جزء آخر‬
‫فلو فشل جزء من الكود سينهار البرنامج كامل و هذه تعتبر كارثة بأتم معنى الكلمة لن الخطئ الواحد يقضي‬
‫على البرنامج ككل‬
‫و كما قلت المشاريع المتوسطة او الضخمة تكون دائما مقسمة و ما يهمنا نحن ان يبقى مشروعنا يعمل و يقدم‬
‫النتائج للمستخدم حتى لو حدث خطئ معين و لو حدث خطئ يطبع البرنامج للمستخدم سبب الخطئ و ل يتوقف‬
‫عن العمل دون ابلغ المستخدم عن السبب لنه لو فعل هذا سيعتبر برنامج رديئ و سيعتبر عمل مبتدئين و‬
‫نحن بإذن ال ل نريد ان نبرمج اكواد مبتدئين‬

‫‪try-except‬‬
‫هي عبارة او عدة عبارات كما سنرى مهمتها تقسيم الكود إلى عدة أقسام‬
‫قسم يقوم بتنفيد الوامر في حالة عدم وجود مشاكل‬
‫و قسم آخر يقوم بتنفيد أوامر أخرى في حالة وجود خطئ و هنا بيت القصيد لن يتوقف البرنامج عند حدوث‬
‫خلل بل سينفد القسم الثاني‬

‫و قبل أن ننطلق في دراسة هذه التقنية يتوجب علينا تقسيم الخطاء بطريقة أكثر تعمقا‬
‫النوع الول – السماء المجهولة‪NameError -‬‬
‫يحدث هذا الخطئ عندما تكتب اسم لمتغير غير معرف من قبل فعندما يصل المفسر لهذا السم يطبع رسالة‬
‫خطئ تنبؤك بأن هذا السم مجهول‬
‫مثل نفرض أن اسم هذا المتغير ‪value‬‬
‫ستكون رسالة الخطئ كالتالي‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫‪NameError: name 'value' is not defined‬‬

‫النوع الثاني –التقسيم على الصفر‪ZeroDivisionError -‬‬


‫يحدث هذا الخطئ عند تقسيم عدد على الصفر و قد يرى البعض أنه خطئ مستحيل أن نقع فيه لن الكل يعلم‬
‫أنه ل يوجد عدد يقسم على الصفر لكنه ممكن الحدوث في قلب البرنامج فمثل لو تطلب منا عمل حلقة و العدد‬
‫المقسم عليه ينقص بدرجة كل مرة فهنا ممكن ان ننسى هذا الخطئ‬
‫رسالة الخطئ‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫‪ZeroDivisionError: integer division or modulo by zero‬‬

‫النوع الثالث – الخطاء الكتابية‪SyntaxError -‬‬


‫كما رأيناها سابقا هي أخطاء تحدث عند الخطئ في كتابة عبارة معينة‬
‫رسالة الخطئ‬
‫‪SyntaxError: invalid syntax‬‬

‫النوع الرابع –أخطاء الفهرس‪IndexError -‬‬


‫تحدث هذه الخطاء عند التعامل مع السلسل أو القوائم و يحدث خطئ في تحديد الفهرس او رتبة العنصر مثل‬
‫تكون عندنا سلسلة تحتوي على ‪ 5‬عناصر و نحدد العنصر رقم ‪9‬‬
‫رسالة الخطئ‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫‪IndexError: list index out of range‬‬

‫النوع الخامس‪-‬أخطاء عناصر القواميس‪KeyError -‬‬


‫هذا النوع من الخطاء متعلق بالقواميس و يحدث هذا النوع عند تحديد عنصر غير موجود بالقاموس‬
‫مثال‬

‫}‪aDict = {'host': 'earth', 'port': 80‬‬


‫]'‪print aDict['server‬‬
‫رسالة الخطئ‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫‪KeyError: server‬‬
‫النوع السادس‪-‬أخطاء المدخلت و المخرجات‪IOError -‬‬
‫هذا النوع من الخطاء شائع كثيرا و يحدث عندما يوجد خلل في مدخلت المستخدم أو في التعامل مع الملفات‬
‫و قواعد البيانات‬
‫فمثل لو طلبنا من المستخدم ادخال عدد و ادخل حرف او طلبنا من المفسر فتح ملف و هذا الملف ل يوجد‬
‫بالجهاز او طلبنا منه حجز بينات و ل يوجد اتصال مع قاعدة البيانات‪.....‬‬
‫طبعا لكل حالة من هذه الحالت رسالة معينة لكنها تشترك ب ‪ IOError‬فكلما تجد هذه العبارة اعلم ان الخطئ‬
‫يكمن في المدخلت او المخرجات‬
‫و هذا مثال يوضح ذلك بحيث اننا طلبنا من المفسر فتح ملف غير موجود أصل بالجهاز‬
‫رسالة الخطئ‬

‫)"‪f = open("blah‬‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫'‪IOError: [Errno 2] No such file or directory: 'blah‬‬

‫النوع السابع‪ -‬اخطاء اسناد الكلس‪AttributeError -‬‬


‫هذا النوع من الخطاء مرتبط بالبرمجة الموجهة بحيث انه يحدث عندما نسند لكلس ميثود غير معرفة أو غير‬
‫موجودة أصل‪.‬‬
‫سنرى هذا مستقبل‬
‫رسالة الخطئ‬
‫‪Traceback (innermost last):‬‬
‫? ‪File "<stdin>", line 1, in‬‬
‫‪AttributeError‬‬

‫هنا نكون قد بينا كل انواع الخطاء البرمجية و يفيدنا هذا في معرفة سبب الخطئ و تحديد مكانه كما سيفيدنا‬
‫أيضا معرفة نوع الخطئ في اختيار الرسالة المثلى للخطئ كما سنرى‪.‬‬

‫استعمال ‪try-exept‬‬
‫كما قلنا سابقا تفيدنا هذه العبارة أو الطريقة في تسير الخطاء و تجنب فشل تنفيد البرنامج عند حدوث خطئ و‬
‫تفيدنا أيضا في ابلغ المستخدم بنوع الخطئ و اسباب حدوثه‬
‫و كما نلحظ أن هذه العبارة تنقسم إلى قسمين‬

‫‪try :‬‬
‫هنا نضع الكود أو الوامر التي ستنفد في الحالة العادية أي إذا لم يحدث خطئ‬

‫‪execpt : Exception[, reason]:‬‬


‫هنا نضع الوامر التي ستنفد عند حدوث خلل في التنفيد و نستطيع كذلك وضع رسالة لتنب‬
‫يه المستخدم بالخطئ و سبب حدوثه‬
‫مثال‬
‫}'‪name={'user1':'ab256','user2':'9857oki','user3':'8fgd5ft‬‬
‫)'‪search=raw_input('enter the name :‬‬
‫)‪name.pop(search‬‬

‫هذا الكود يقوم بحذف إسم من القاموس جربوا هذا الكود عندكم و ادخلو اسم ل يوجد في القاموس‬
‫ماالذي سيحدث؟؟‬
‫سيتوقف البرنامج تماما و يطبع لنا المفسر رسالة خطئ ‪.‬‬
‫طيب نحن الن قمنا بكتابة هذا الكود و سنقوم بتصحيح الخطئ لكن لو كان هذا الكود جزء من كود كبير‬
‫لمشروع و حدث هذا الخطئ ‪.‬‬
‫ستكون النتائج وخيمة جدا لن البرنامج سيتوقف عن العمل و سيتوقف النظام أو يبطئ لدقائق ‪.‬‬
‫إذا سنستغل الطريقة التي رأيناها بحيث إذا حدث خطئ لن يتوقف البرنامج بل يطبع لنا رسالة تنبؤنا بسبب‬
‫الخطئ‬

‫}'‪name={'user1':'ab256','user2':'9857oki','user3':'8fgd5ft‬‬
‫)'‪search=raw_input('enter the name :‬‬
‫‪try:‬‬
‫)‪name.pop(search‬‬
‫‪except Exception,e:‬‬
‫‪print e‬‬

‫نفس البرنامج ولكننا أدخلنا عليه عبارة ‪try-except‬‬


‫داخل عبارة ‪ try‬قمنا بوضع الوامر التي ستنفد في حالة وجود السم داخل القاموس ‪.‬‬
‫داخل عبارة ‪ except‬أضفنا أمامها كلمة ‪ Exception‬و التي تعني سبب الخطئ ثم فاصلة و تليها ‪ e‬و هذا‬
‫الخير سيحجز داخله عبارة تبين سبب الخطئ أي نستطيع أن نعتبره متغير يحجز داخله الرسالة التي سيرسلها‬
‫النظام في حالة وجود خطئ‬
‫طبعا نستطيع استبدال ‪ e‬بأي حرف آخر و لكن المتعارف عليه في كل لغاة البرمجة استعمال حرف ‪e‬‬
‫‪ e‬هذا سيحجز لنا سبب الخطئ و نستطيع التصرف في الرسالة كما نريد‬

‫‪except Exception,e:‬‬
‫‪print "Error Invalid entry‬‬ ‫‪!",e‬‬

‫و مايهمنا أن البرنامج سيواصل العمل مهما أدخل المستخدم‬


‫مثال ثاني‬
‫سيبين لنا هذا المثال فائدة عبارة ‪ try-except‬أكثر‬
‫لدينا دالة محجوزة للغة البايثون اسمها ‪ ()float‬تقوم بتحويل العداد من صيغتها الصلية إلى صيغة ‪float‬‬
‫مثل جربوا لديكم‬
‫)‪print float(54158‬‬

‫طيب لو أدخلنا بدل العداد أحرف سيحدث خطئ وهذا طبيعي‬


‫)‪print float(qsdzs‬‬

‫و ستكون رسالة الخطئ كالتالي‬


‫‪Message‬‬ ‫‪File Name‬‬ ‫‪Line‬‬ ‫‪Position‬‬
‫‪Traceback‬‬
‫>‪<module‬‬ ‫>‪<Module1‬‬ ‫‪1‬‬
‫‪exceptions.NameError: name 'qsdzs' is not defined‬‬

‫طيب انا قلت أن حدوث الخطئ في هذه الحالة طبيعي جدا لن هذه الدالة مخصصة للعداد و ليس للحرف‬
‫لكن الذي ليس طبيعي لنا هو توقف البرنامج عن العمل و دائما أقول ضعوا في حسبانكم المشاريع الكبيرة خطئ‬
‫بسيط كهذا سيسبب لنا كارثة‬
‫طيب سنتعامل مع إمكانية حدوث هذا الخطئ بواسطة ‪try-except‬‬
‫سنعمل دالة اسمها ‪ float1‬تقوم بنفس عمل الولى لكنها أأمن من الولى‬

‫‪def float1(obj):‬‬
‫‪try:‬‬
‫)‪retval = float(obj‬‬
‫‪except :‬‬
‫"‪message = "could not convert non-number to float‬‬
‫‪return message‬‬

‫)'‪print float1('uu‬‬

‫نستطيع أيضا أن نحدد أو نتوقع نوع الخطئ الممكن الوقوع لكي نساعد المفسر على طباعة الرسالة المناسبة‬
‫في حالتنا هذه نوع الخطئ متعلق بالمتغير و تسمى هذه الخطاء بـ ‪ValueError‬‬
‫و نقوم بتعديل القسم الثاني من الكود فيصح كالتالي‬
‫‪except ValueError :‬‬
‫"‪message = "could not convert non-number to float‬‬
‫‪return message‬‬

‫استعمال أكثر من ‪except‬‬


‫إذا كان لدينا توقع بحدوث أكثر من خطئ في قسم معين من الكود نستطيع أن نعالج هذا الوضع بإدراج أكثر من‬
‫عبارة ‪ except‬على النحو التالي‬
except Exception1[, reason1]:
suite_for_exception_Exception1
except Exception2[, reason2]:
suite_for_exception_Exception2
:
‫فيصبح الكود كالتالي‬
def float1(obj):
try:
retval = float(obj)
except ValueError:
retval = 'could not convert non-number to float'
except TypeError:
retval = 'object type cannot be converted to float'
return retval

print float1('a')

‫كما أننا نستطيع ان نجمع عدة احتمالت في عبارة واحدة على النحو التالي‬
except (Exception1, Exception2)[, reason]:
suite_for_Exception1_and_Exception2

‫فيصبح الكود على النوح التالي‬


def float1(obj):
try:
retval = float(obj)
except (ValueError, TypeError):
retval = 'argument must be a number or numeric string'
return retval

print float1(())
print float1('rr')
print float1([])

‫طيب الن لو أردنا أن نكتفي من عناء كتابة رسائل الخطاء أو إن أردنا أن تكون رسائل الخطاء ذات صيغة‬
‫احترافية أي تكون كالتي يطبعها لنا المفسر عند حدوث خطئ هنا يتوجب علينا استعمال الطريقة التالية‬
‫نبقى مع نفس المثال‬-
def float1(object):
try:
message = float(object)
except (ValueError, TypeError), diag:
message= str(diag)
return message

print float1(22)
print float1('rr')
‫كما نلحظ بقي المثال على حاله و لكننا اضفنا عليه العبارة التالية‬
‫)‪message= str(diag‬‬

‫تعطينا لغة البايثون الخيار باستعمال عبارة ‪ else‬مع عبارة ‪ try-except‬إذا تطلبت الحاجة لذلك‬
‫و يكون جسم التشكيلة كالتالي‬
‫‪try:‬‬
‫‪A‬‬
‫‪except MyException:‬‬
‫‪B‬‬
‫‪else:‬‬
‫‪C‬‬
‫فنبتدئ بعبارة ‪ try‬و اذا حدث خطئ ينتقل المفسر لتنفيد أوامر عبارة ‪except‬‬
‫وهنا نضع ملحظة‬
‫ل إذا نجحت عبارة ‪ try‬أي ان المفسر لم يواجه أي خطئ‬
‫عبارة ‪ else‬في هذه الحالة ستنفد إ ّ‬
‫‪try:‬‬
‫هذه الرسالة ستطبع إذا لم يحدث خطئ » ‪print‬‬
‫‪except MyException:‬‬
‫» إذا حدث خطئ و لم تطبع الرسالة الولى هذه الرسالة هي التي ستطبع» ‪print‬‬
‫‪else:‬‬
‫» هذه الرسالة ستطبع عند نجاح المفسر في طباعة الرسالة الولى» ‪print‬‬

‫مثال‬
‫))'‪x=int(raw_input('Entrer votre age‬‬
‫‪try:‬‬
‫‪c=x+8‬‬
‫‪print c‬‬
‫‪except Exception, e:‬‬
‫‪print "Error",e‬‬
‫‪else:‬‬
‫"‪print"operation terminer avec sucsses‬‬

‫إذا في هذا المثال إذا نجح الكود ستطبع رسالة ‪ else‬و التي ستنبئ المستخدم بنجاح العملية‬
‫سنعود لهذا المثال بعد قليل‬
‫عبارة ‪ finally‬دائما نبقى مع ابداعات هذه اللغة الرائعة‬
‫تتيح لنا لغة بايثون استعمال عبارة أخرى و هي عبارة ‪ finally‬و توضع هذه العبارة آخر التشكيلة الهرم على‬
‫الشكل التالي‬
‫‪try:‬‬
‫‪A‬‬
‫‪except MyException:‬‬
‫‪B‬‬
‫‪else:‬‬
‫‪C‬‬
‫‪finally:‬‬
‫‪D‬‬
‫و عمل هذه العبارة أن المفسر ينفد أوامرها مهما حدث سواء نجح المفسر في تنفيد الكود أم لم ينجح‬
‫‪try:‬‬
‫هذه الرسالة ستطبع إذا لم يحدث خطئ » ‪print‬‬
‫‪except MyException:‬‬
‫» إذا حدث خطئ و لم تطبع الرسالة الولى هذه الرسالة هي التي ستطبع» ‪print‬‬
‫‪else:‬‬
‫» هذه الرسالة ستطبع عند نجاح المفسر في طباعة الرسالة الولى» ‪print‬‬
‫‪finally:‬‬

‫مهما يحدث في الحالت الولى ستطبع هذه الرسالة سواء نجح البرنامج أم لم ين » ‪Print‬‬
‫»جح‬

‫ملحظة‪:‬‬
‫استعمال عبارة ‪ else‬او عبارة ‪ finally‬اختياري و ليس اجباري و هذا يرجع لحتياجات المبرمج لتمام الكود‬
‫أو يرجع لخصوصيات الكود و الحالة فكل حالة لها خصوصيات تتميز بها فهنا انت أخي القارئ الذي تختار‬
‫بين هذه العبارات و الطرق ما يناسب برنامجك‪.‬‬
‫طيب نرجع الن للمثال السابق‬
‫اعد تنفيد ذلك المثال و أدخل حرف بدل عدد ؟ سيتوقف البرنامج ‪.‬‬
‫و نحن مللنا من هذا السلوب البدائي لنه لو اخطئ المستخدم و أدخل حرف أو لم يفهم جيدا ما طلبه منه‬
‫البرنامج فأدخل اسمه سيتوقف البرنامج بسبب هذا الخطئ البسيط ‪.‬‬
‫و بما أننا درسنا طرق تسير الخطاء سنعدل عليه قليل حتى نعطيه صفة لئقة‬
‫‪try:‬‬
‫‪try:‬‬
‫))' ‪x=int(raw_input('Entrer votre age :‬‬
‫‪c=x+8‬‬
‫‪except Exception,e:‬‬
‫‪print "Error ",e‬‬
‫‪except Exception,e:‬‬
‫‪print"Error ",e‬‬

‫استعملنا عبارة ‪ try‬داخل عبارة ‪ try‬أخرى و هذا امر عادي لننا كما قلت نستعمل هذه العبارات بما يناسب‬
‫الحالة التي نحن بصددها‪.‬‬
‫إذا ‪ try‬الثانية تقوم بمعالجة مدخلت المستخدم فإذا كانت صحيحة اضيفة لها ‪ 8‬أما ان حذث خطئ سينتقل‬
‫المفسر لعبارة ‪ except‬و التي بدورها ستطبع للمستخدم سبب الخطئ‬
‫و في هذه الحالة لن يتوقف البرنامج مها حدث و هذا الذي يهمنا‪.‬‬
‫هذا كل شيئ بالنسبة لتسير الخطاء في الوقت الراهن مازالت بعض المور لم ندرسها و لكننا سنراها في‬
‫التطبيقات بإذن ال و كل مرة نصل لشيئ جديد سنتوقف لشرحه لني وجدت صعوبة في وضع المثلة المناسبة‬
‫لهذا الموضوع فكل المثلة الخاصة بتيسر الخطاء تكون متقدمة جدا‪.‬‬
‫ما أطلبه منكم الن هو استيعاب الشياء التي رأيناها في هذا المحور ليس بالضرورة فهمها و تطبيقها و إنما‬
‫اخذ صورة صحيحة عنها لن معالجة الخطاء موضوع كبير جدا و يتطلب الخبرة و الممارسة أكثر من‬
‫الدراسة ‪.‬‬
‫الدرس الثامن ]تابع الدوال[‪:‬‬
‫سنحاول في هذا الدرس أن نطور في أسلوبنا في الكاتبة حتى ل نواجه صعوبات في الدروس القادمة و سنحاول‬
‫أيضا أن نتعلم كيفية تنظيم الكود لن المشاريع المستقبلية ل تخلو من الدوال بحيث ان المشروع المتوسط‬
‫يحتوي على أكثر من ‪ 10‬دوال حتى ولو درسنا البرمجة الموجهة و‬
‫استعملنا الكلس سنبقى نحتاج للدوال‬
‫فلو وضعنا في حسبننا كثرة الدوال في الكود و ضف لذالك تعدد مهام البرنامج بحيث أن كل دالة تقوم بعمل‬
‫معين و كل دالة تعتمد على نتائج دالة أخرى و هذه الخيرة تقدم نتائجها لدالة أخرى و هكذا ‪.....‬‬
‫و هنا يتوجب علينا التعامل مع هذه التشكيلة بحذر شديد كما يتوجب علينا تنظيم الكود بحيث لو فتحنا الكود مرة‬
‫أخرى يسهل علينا فهم محتواه او لو قرء الكود مبر مج آخر يستطيع فهم هذا الكود‬
‫كما أننا ذكرنا سابقا أن تنظيم الكود و تقسيمه إلى عدة دوال يسهل علينا اكتشاف الخطاء و تصحيحها و يسهل‬
‫علينا أيضا التطوير في هذا الكود مستقبل ‪.‬‬
‫لعمل برنامج منظم و آمن نسبيا يتوجب علينا أن نضع في حسباننا عدة معاير منها‬
‫أول أن يستدعي الكود أكثر من مكتبة أو على القل مكتبة واحدة‬
‫أن يكون الكود مقسم إلى دوال حسب مهامه‬
‫أن يكون الكود الرئيسي مكتوب داخل دالة تسمى دالة ‪main‬‬
‫أن نستعمل فيه طرق تسير الخطاء‬
‫أن يكون الكود مدعم بعبارات لشرح مهمة كل قسم‬
‫أن تحتوي كل دالة على جملة تبين مهمتها و إن كانت هذه الدالة مطورة نضع الرقم التسلسلي لهذه الدالة‬
‫‪version‬‬
‫هذه هي أهم المعايير لعمل مشروع آمن و منظم من جهة و يكون ذو نكهة احترافية من جهة أخرى أي أنك‬
‫اخري القارئ لو احترمت هذه المعايير تستطيع أن تطرح مشروعك على النت بفخر‬
‫تبقى معايير أخرى لم أذكرها الن من أهمها رخصة المشروع و سنتوقف عندها في المراحل المستقبلية ‪.‬‬
‫الن سنشرح النقاط المذكورة بسرعة‬
‫أستندعاء المكاتب‪ :‬ل يخفى عليكم اخواني القراء أن المشروع الذي ل يستدعي مكتبة أو أكثر يعتبر مشروع‬
‫رديئ لن المكاتب وجدت لكي تعين المبرمج و تختصر عليه الوقت كما أنها وجدت لنشاء برامج تحتوي على‬
‫أعمال ل تستطيع اللغة القيام بها كابرمجة الشبكات )التصالت المرئية السمعية( أو التعامل مع برامج عالمية‬
‫مشهورة او استغلل موارد النظام و اللتحكم به و استعمال بروتوكولت الشبكات ‪...‬الخ‬
‫فنحن كطلب للغة البايثون سيأتي الوقت الذي سننهي فيه دراسة هذه اللغة بإذن ال م الذي سنفعله في ذلك‬
‫الوقت ؟؟تبقى تبرمج برامج بسيطة لا‬
‫أطلق العنان لخيالك و ابحث عن مكاتب جديدة و حاول أن تستغلها في برامجك لن المكاتب انشئت لهذا السبب‬
‫ثانيا تقسيم الكود ‪ :‬ذكرنا سابقا الفائدة من تقسيم الكود لعدة الدوال و سنطبق بعض المثلة في هذا الدرس و‬
‫اريد أن انوه لفائدة أخرى من استعمال الدوال تتجلى في استغللها في برامج و مشاريع أخرى فأنت نثل عندما‬
‫تستعمل أكثر من دالة و مع مرور الوقت سيتضح أسلوبك و ستستطيع أن تميز أكثر العمال التي تقوم بها و‬
‫تحتاجها )حسب نوعيت عملك( هنا ماعليك سوى حفظ هذه الدوال و استدعائها كلما دعت الحاجة فتختصر‬
‫على نفسك الجهد و الوقت‬
‫النقاط المتبقية سنبتدئ بها الدرس‬
‫أول معلومات الدالة‬
‫في الحالت المتقدمة و عندما يكون يحتوي على العديد من الدوال و إذا كانت الدالة تحتوي على الكثير من‬
‫السطور أو كان عملها معقد نوعا ما يستحسن أن نضيف لها بعض السطور التي تبين عملها و دورها في الكود‬
‫و يكون ذلك على الشكل التالي‬
‫‪def a():‬‬
‫‪return a+a‬‬
‫‪a.__doc__='function a() added‬‬ ‫‪a to a‬‬ ‫'‬

‫__‪print a.__doc‬‬

‫كما نلحظ قمنا بإضافة معلومات عن الدالة ‪ a‬و ذلك بواسطة العبارة‬
‫‪__a.__doc‬‬
‫و لكي تتحصل على السطر الذي يسبق اسم الدالة و السطر الذي يلي السم ماعليك إل الضغط على رقم ‪8‬‬
‫العلوي مرتبن و كل ما يكتب بين خطين في لغة البايثون يعتبر بّناء للكلس ‪constructeur‬‬
‫و سنشرح طريقة عمله عندما نصل لمحور البرمجة الموجهة و نستطيع أن نعرف مهام الدالة بطريقة أخرى‬
‫‪def a():‬‬
‫‪'function a() added‬‬ ‫‪a to a‬‬ ‫'‬
‫‪return a+a‬‬
‫__‪print a.__doc‬‬

‫و كل الطريقتين تعطينا نفس النتائج و إذا أردت ان تقرء المعلومات الخاصة بالدالة ماعليك إلى طباعة المر‬
‫__‪ __doc‬بعد اسم الدالة‬
‫__‪print name of function.__doc‬‬

‫تمكنك هذه الطريقة من وضع كل المعلومات التي تحتاجها انت أو أي مبرمج آخر بحيث أن هذا الخير يستطيع‬
‫فهم الدالة و طريقة عملها بسهولة عند قراءة التعريفات التي قمت بإضافتها انت ‪.‬‬
‫و اذا كنت بصدد تطوير برنامج فحتما ستطور الدوال الخاصة به و تضيف عليها بعض الخصائص ففي‬
‫هذه الحالة يتوجب عليك اضافة الرقم التسلسلي للنسخة الدالة و ذلك بواسطة السطر التالي‬
‫‪def a():‬‬
‫‪'function a() added‬‬ ‫‪a to a‬‬ ‫'‬
‫‪return a+a‬‬

‫'‪a.__version__='1.0‬‬

‫__‪print a.__doc‬‬
‫__‪print a.__version‬‬
‫طبعا نحن في هذه المرحلة لن نستعمل هذه المور كثيرا و لكني أردت أن أذكرها من باب المانة العلمية و من‬
‫الباب التذكير حتى إذا وصلنا إليها لن نحتاج لتكرار شرحها‬
‫كما أنه يتوجب عليك أخي القارئ أن تعود نفسك على إضافة هذه المور على أكوادك حتى تطفي عليها صفة‬
‫احترافية و يتوجب علينا ايضا من الن فصاعدا إضافة سطور‬
‫تعريفية قبل كل دالة أو قبل كل مهمة في الكود و ذلك بإضافة قبل بداية السطر علمة ‪#‬‬
‫‪def a():‬‬

‫‪#début de la fonction‬‬
‫‪'function a() added a to a‬‬ ‫'‬
‫‪return a+a‬‬
‫‪#fin de la fonction‬‬
‫'‪a.__version__='1.0‬‬

‫__‪print a.__doc‬‬
‫__‪print a.__version‬‬

‫إذا راينا لحد الن ثلث طرق تساعدنا في توضيح عمل الدوال و اضافة معلومات خاصة بهذه الدوال‬

‫إما عن طريق ‪'*************'=__name function.__doc‬‬


‫أو عن طريق وضع هذه نفس السطور أعلى الدالة بين علمتين ''‬

‫كما رأينا الطريقة الثالثة و هي صالحة لكافة الكود و ليس فقط للدوال و هي وضع علمة ‪ #‬قبل السطر الذي‬
‫تريد وضعه و رأينا أيضا كيفية وضع الرقم التسلسلي لنسخة الدالة‬
‫ثانيا تنظيم الدوال‬
‫قلنا قبل قليل أنه يتوجب علينا تنظيم الكود و تقسيمه لعدة الدوال و كتابة الكود الرئيسي داخل دالة تسمى ‪main‬‬
‫بحيث أن كل لغات البرمجة تستعمل هذه الطريقة‬
‫فيكون جسم الكود كالتالي‬
‫إستدعاء المكتبة الولى‬
‫أستدعاء المكتبة الثانية‬
‫استدعاء ‪.....‬المكتبة ‪....‬الخ‬
‫هنا إذا اردت التوضيح يمكنك وضع اسم البرنامج و تاريخ كتابة الكود و اسم الكاتب أو اسم المنظمة او‬
‫المؤسسة التي كتبت الكود‬
‫كما يمكنك وضع إيميلك الشخصي و كل هذا يأتي قبله علمة ‪#‬‬
‫في هذا القسم يبدئ جسم الكود بحيث أن كل الدوال التي يحتويها الكود تكتب تحت بعضها البعض‬
‫الدالة الولى‬
‫الدالة الثانية‬
‫الدالة الثالثة‬
‫الدالة‪....‬الخ‬
‫و عند النتهاء من كتابة الدوال يأتي القسم الرئيسي للكود و الذي كنا نكتبه من قبل في الفراغ أي ل تحتويه أي‬
‫دالة لكن من الن فصاعدا سنكتب هذا الجزء داخل الدالة الرئيسية التي تسمى ‪main‬‬
‫الدالة ‪main‬‬
‫هنا نضع جسم الكود و في الخير نستدعي الدالة الرئيسية و ينفذ البرنامج باختصار يكون جسم الكود كالتالي‬
‫‪import xxx‬‬
‫‪from xxxxx import yyyyyy‬‬
‫‪# name of programme xxxxxxxxxxxx‬‬
‫‪#writen by xxxxxxxxxxxxxxx‬‬
‫‪# date xx/xx/xx/‬‬
‫‪# Email [email protected]‬‬
‫‪# site of xxxxx‬‬ ‫‪www.xxxxxxx.com‬‬

‫‪def function1():‬‬
‫‪xxxxxxxxxxxxxxxxx‬‬
‫‪def function2():‬‬
‫‪xxxxxxxxxxxxxxxxx‬‬
‫‪def function3():‬‬
‫‪xxxxxxxxxxxxxxxxx‬‬

‫‪def main():‬‬
‫‪xxxxxxxxxxxxxxxxxx‬‬
‫‪xxxxxxxxxxxxxxxxxx‬‬
‫‪xxxxxxxxxxxxxxxxxx‬‬

‫‪if __name__ == '__main__':‬‬


‫)(‪main‬‬

‫بالضافة أن هذه الطريقة هي المعمول بها عالميا ستفيدنا أيضا في تنظيم الكود و تجنب البحث المطول عن‬
‫الخطاء كما أنها تساعد في زيادة التركيز أثناء كتابة أو قراءة الكود‬
‫و الن سنقوم بكتابة كود بسيط نطبق فيه كل مارايناه‬
‫هو عبارة عن برنامج يمثل لعبة للولد الصغار يقوم بعرض عملية على الشاشة ثم يطلب منك نتيجة العملية‬
‫فإذا كان الجواب صحيح يمر للعملية أخرى و إذا كان الجواب خاطئ يعيد نفس العملية مرتبن فإن لم يتمكن‬
‫الطفل من الجابة يظهر له البرنامج الجواب الصحيح ثو يعيد عليه نفس السؤال‬
‫أول استدعاء المكاتب‬
‫سنحتاج لمكتبتين‬
‫الولى اسمها ‪operatort‬‬
‫و تحتوي هذه المكتبة على العديد من المعاملت الرياضية‬
‫و المكتبة الثانية سبق و تعاملنا معها و هي مكتبة ‪random‬‬
‫كود البرنامج‬
‫‪from operator import add, sub‬‬
‫‪from random import randint, choice‬‬

‫}‪ops = {'+': add, '-': sub‬‬


‫‪MAXTRIES = 2‬‬

‫‪def doprob():‬‬
‫)'‪op = choice('+-‬‬
‫])‪nums = [randint(1,10) for i in range(2‬‬
‫)‪nums.sort(reverse=True‬‬
‫)‪ans = ops[op] (*nums‬‬
‫)]‪pr = '%d %s %d = ' % (nums[0], op, nums[1‬‬
‫‪oops = 0‬‬
‫‪while True:‬‬
‫‪try:‬‬
‫‪if int(raw_input(pr)) == ans:‬‬
‫'‪print 'correct‬‬
‫‪break‬‬
‫‪if oops == MAXTRIES:‬‬
‫)‪print 'answer\n%s%d'%(pr, ans‬‬
‫‪else:‬‬
‫'‪print 'incorrect... try again‬‬
‫‪oops += 1‬‬
‫‪except (KeyboardInterrupt,‬‬
‫‪EOFError, ValueError):‬‬
‫'‪print 'invalid input... try again‬‬

‫‪def main():‬‬
‫‪while True:‬‬
‫)(‪doprob‬‬
‫‪try:‬‬
‫)(‪opt = raw_input('Again? [y]').lower‬‬
‫‪if opt and opt[0] == 'n' :‬‬
‫‪break‬‬
‫‪except (KeyboardInterrupt, EOFError):‬‬
‫‪break‬‬

‫‪if __name__ == '__main__':‬‬


‫)(‪main‬‬

‫شرح البرنامج‬
‫‪from operator import add, sub‬‬
‫‪from random import randint, choice‬‬

‫أول قمنا باستدعا المكتبتين كالعادة و الجديد هنا أننا لم نستدعي كل المكتبة بل استدعينا دالتين من كل مكتبة و‬
‫هذا بواسطة العبارة ‪from‬‬
‫أي من المكتبة ****استدعي *****و ****‬
‫و تفيدنا هذه الميزة في التخفيف على المفسر و تسريع البرنامج‬
‫‪add‬و ‪ sub‬معاملن الول يعني الحمع و الثاني يعني الطرح وهما مرادفان ل ‪+‬و ‪-‬‬

‫و الدالة ‪ randint‬تعمل نفس عمل ‪ random‬و لكن الختلف بينهما ان هذه الدالة التي استدعيناها تتعامل مع‬
‫العداد فقط من نوع ‪int‬‬
‫‪ choice‬يساعدنا في التعرف على اختيار المستخدم دون استعمال الجمل الشرطية كما اعتدنا فهذه الدالة تتكل‬
‫بالتعرف على إختيار المستخدم و التعامل معه‬
‫}‪ops = {'+': add, '-': sub‬‬
‫‪MAXTRIES = 2‬‬

‫قمنا بانشاء قاموس يسند لكل معامل العلمة المطابقة له لن المستخدم لن يدخل عبارة ‪ add‬بل سيدخل علمة‬
‫‪+‬و‬
‫ولهذا قمنا بانشاء القاموس ‪ops‬‬
‫لكي ينشئ لنا علقة بين النعامل المستدعي من المكتبة و العلمة التي ادخلها المستخدم‬
‫‪MAXTRIES = 2‬‬

‫يعبر هذا المتغير عن عدد المحاولت الخاطئة المسموح بها قبا اظهار الجابة الصحيحة للمستخدم‬
‫هذا القسم الول من الكود قمنا فيه باستدعاء المكاتب التي نحتاجها كما عرفنا‬
‫المتغيرات الساسية التي يحتاجها البرنامج و تستطيع أخي القارئ أن تضيف هنا تعريف للكود مثل أن تكتب‬
‫‪#Randomly chooses numbers and an arithmetic function,‬‬
‫‪#displays the question, and verifies the results.Shows answer after three wrong‬‬
‫‪tries‬‬
‫‪#and does not continue until the user enters the correct answer‬‬

‫أو تستطيع ان تكتب هذه السطور داخل جسم الدالة ‪ dobrob‬كمعلومات تعبر عنها و يبقى لك الخيار في‬
‫وضع معلوماتك الشخصية أول الكود‬
‫‪def doprob():‬‬
‫)'‪op = choice('+-‬‬

‫هنا عرفنا الدالة التي ستقوم بالعمليات الزمة المتغير ‪ op‬سيحجز لنا العبارتين ‪- +‬‬
‫])‪nums = [randint(1,10) for i in range(2‬‬
‫المتغير ‪ nums‬سيحجز قيمتين من ‪ 1‬إلى ‪ 10‬ففي الولى قمنا بتحديد مجال العداد‬
‫)‪randint(1,10‬‬
‫و الكتابة الثانية معناها أن المتغير ‪ nums‬سيحجز عددين و لو أردنا استعمال ثلثة اعداد نستبدل رقم ‪ 2‬ب ‪3‬‬
‫و هكذا حسب اختيارنا‬
‫)‪nums.sort(reverse=True‬‬
‫هنا قمنا بترتيب العداد ترتيبا تصاعديا ثم عكسنا الترتيب في نفس الوقت بحيث أنه العدد الذي على اليمين‬
‫يكون دائما أكبر من العدد الذي على اليسار‬
‫لماذا؟؟ حتى نتجنب أن تكون النتائج ذات اشارة سلبية بحيث أن العمليات التي ستظهر للطفل تكون نتائجها كلها‬
‫موجبة‬
‫‪2=5-7‬‬
‫‪2= 3 – 5‬‬
‫‪.......‬‬
‫)‪ans = ops[op] (*nums‬‬

‫المتغير ‪ ans‬سيحجز لنا نتيجة العملية و انظرو إلى القوة و الحرية التي تضيفها المكاتب على الكود بحيث اننا‬
‫قمنا بانشاء عملية علة عددين بغض النظر عن نوع العملية جمع أو طرح‬
‫فـ المتغير ‪ ops‬رأينا أنه عبارة عن قاموس يربط بين العلمات و دوال الدوال المستدعية و المتغير ‪ op‬يأخذ‬
‫من الدالة ‪ choice‬إما عملية الجمع أو عملية الطرح )في كل مرة واحدة( و ‪ nums‬يحتوي على العددين‬
‫العشوائيين‬
‫ومعنى هذه الكتابة أن المفسر سيطبق المعامل الذي يحتويه ‪ op‬على العددين المحتويين في المتغير ‪nums‬‬
‫و كل هذا بواسطة النجمة * التي تسبق هذا المتغير‬
‫)توجد طريقة اخرى مطابقة لهذه سنراها في درس القبل (‬

‫)]‪pr = '%d %s %d = ' % (nums[0], op, nums[1‬‬


‫‪oops = 0‬‬
‫انشأنا في هذا السطر الرسالة التي ستظهر للطفل و حجزنا هذه الرسالة داخل المتغير ‪ pr‬و ستكون الرسالة‬
‫على الشكل التالي‬
‫‪=5+1‬‬
‫و المتغير ‪ oops‬سيحجز لنا عدد محاولت الطفل‬
‫‪while True:‬‬
‫‪try:‬‬
‫‪if int(raw_input(pr)) == ans:‬‬
‫'‪print 'correct‬‬
‫‪break‬‬

‫هنا تبدئ حلقة بالعمل‬


‫أول شيئ سنطبع للطفل نص العملية المحجوز في المتغير ‪ pr‬و نأخذ منه الجابة في نفس الوقت و في نفس‬
‫الوقت أيضا نقارن هذه الجابة مع المتغير ‪ans‬‬
‫فإذا كانت الجابة صحيحة ننبؤه بذالك و نخرج من الحلقة‬
‫‪if oops == MAXTRIES:‬‬
‫)‪print 'answer\n%s%d'%(pr, ans‬‬

‫فإذا أخطئ الطفل مرتين نطبع له الجابة الصحيحة‬


‫‪else:‬‬
‫'‪print 'incorrect... try again‬‬
‫‪oops += 1‬‬

‫و إذا أخطئ الطفل مرة واحدة فقط نطبع له رسالة تنبؤه بذلك ثم نرفع درجة العداد ‪oops‬‬
‫كل هذه الوامر ستنفد إذا لم يحدث خطئ و سارت المور على مايرام لنها مكتوبة داخل عبارة ‪try‬‬
‫‪except (KeyboardInterrupt,‬‬
‫‪EOFError, ValueError):‬‬
‫'‪print 'invalid input... try again‬‬

‫فإذا حدث خطئ في المدخلت كإدخال حرف بدل عدد ‪ ValueError‬أو لم يدخل الطفل شيئا‬
‫‪KeyboardInterrupt EOFError‬أو أدخل عدد بالفاصلة سينتقل المفسر لعبارة ‪ except‬و التي بدورها‬
‫ستطبع له رسالة خطئ‬
‫انتهينا الن من هذه الدالة الثانوية و لم يبقى لنا سوى تهيئة الدالة الرئيسية‬
‫‪def main():‬‬
‫‪while True:‬‬
‫)(‪doprob‬‬
‫‪try:‬‬
‫)(‪opt = raw_input('Again? [y]').lower‬‬
‫‪if opt and opt[0] == 'n' :‬‬
‫‪break‬‬
‫كما قلت سابقا يكون اسم الدالة الرئيسية دائما‬
‫‪ main‬داخل هذه الدالة قمنا بانشاء حلقة تبقى تعيد عمل الدالة ‪doprob‬‬
‫و كلما نفدتها مرة تطلب من المستعمل ان كان يريد مواصلة البرنامج للمحاولة أخرى فإن أدخل حرف ‪y‬‬
‫ستبقى الحلقة في العمل و ان ادخل حرف ‪ n‬ستتوقف الحلقة عن العمل و أر يد أن أنوه |اننا صغرنا في الحرف‬
‫المدخل من طرف المستخدم حتى نتجنب علم احتمالين فلو أدخل الطفل حرف ‪ y‬لن يعرفه البرنامج و سيعتبره‬
‫خطئ لدى مهاما ادخل الطفل سواء كان الحرف كبير او صغير سيقوم البرنامج بتصغيره بواسطة الدالة‬
‫‪lower‬‬
‫طيب الن كيف نستدعي الدالة الرئيسية ؟ نستدعيها بواسطة هذان السطرين‬
‫‪if __name__ == '__main__':‬‬
‫)(‪main‬‬

‫هنا قمنا بأمر المفسر باختبار اسم الدالة فإذا كان اسمها مطابق ل ‪main‬‬
‫‪if __name__ == '__main__':‬‬

‫سيقوم باستدعائها‬
‫)(‪main‬‬
‫و بهذا نكون أنهينا شرح هذا البرنامج و ل يلزمك اخي القارئ تطبيق كل هذه المور منذ المرة الولى وانما‬
‫افهم هذه الطريقة و حاول ادخال هذه الطرق على اسلوبك شيئا فشيئا و بإذن ال كل الكوا التية في هذه الدورة‬
‫ستكون مثل هذا الكود في الطريقة‪.‬‬
‫هو صحيح ان البرنامج بسيط و لكن صدقني اخي الكريم السلوب الذي كتبنا به الكود اسلوب احترافي مئة‬
‫بالمئة و تستطيع التأكد من هذا بقراءة بعض أكواد لغة البايثون ستجدها كلها بنفس أسلوب هذا البرنامج مازالت‬
‫بعض البرامج سنعملها مع بعضنا البعض و سأحاول في كل مرة التعامل مع مكاتب جديدة و طرق جديدة حتى‬
‫تترسخ لديك فكرة ان اساليب كتابة الكواد‪.‬‬

‫و اعتذر لكم اخواني القراء عن الكثار من الشرح في الدرس الماضي و هذا الدرس و ربما اصبح الشرح ممل‬
‫نوعا ما و لكني أريد ان نشرح هذه المور الن و ننهيها حتى ل نواجه المصاعب في الدروس المقبلة ‪.‬‬
‫و اعتذر ايضا عن الطالة في طرح الدروس لني أريد أن يكون الدرس كامل عند طرحه و ليس متقطع‬
‫سنواصل في الدرس القادم الدوال مع بعض المثلة الخرى‬

‫تم بحمد ال‬


‫الدرس التاسع ‪:‬‬
‫سنحاول في هذا الدرس الختصار قدر المكان بحيث سنشرح بسرعة بعض المور المتعلقة بالدوال فما علينا‬
‫ل الفهم و الستيعاب و سنتوقف عند كل فصل بالشرح المطول في التطبيقات و المثلة‬
‫الن إ ّ‬
‫نستطيع ان ننشئ دالة داخل دالة أخرى أو اكثر أي ان الدالة الواحدة تستطيع ان تحتوي هي ايضا دوال اخرى‬
‫مثال‬
‫‪def fun_a(val):‬‬
‫'‪print 'in fun_a‬‬
‫‪c=val%2‬‬
‫‪def fun_b():‬‬
‫'‪print 'in fun_b‬‬
‫‪if c ==0:‬‬
‫'‪print 'paire‬‬
‫‪else:‬‬
‫'‪print 'impaire‬‬
‫)(‪fun_b‬‬

‫)‪fun_a(40‬‬

‫و تحتوي هذه الدالة على دالة فرعية تقوم‬ ‫فكما نلحظ الدالة الم ‪ fun_a‬تأخذ باقي قسمة العدد على ‪2‬‬
‫باختبار باقي القسمة‬
‫ملحظة ‪ :‬الدالة الفرعية تكون معرفة و مستعملة من طرف الدالة الم فقط إذ ان الدوال الخرى ل تستطيع‬
‫التعامل معها فلو كتبنا اسفل الكود ‪ ()fun_b‬سيطبع لنا المفسر رسالة خطئ مفادها ان هذه الدالة غير معرفة‬
‫بارامترات الدالة‬
‫نستطيع التعامل مع البرارمترات بكل حرية بحيث ان لغة البايثون تعطينا صلحيات واسعة في التعامل مع‬
‫البرامترات فنستطيع ان ننشئ سلسلة او قاموس بصورة باراميتر‬
‫‪def database(name,data=[ ]):‬‬
‫)‪data.append(name‬‬
‫)‪print ' %s saved'%(name‬‬
‫‪return data‬‬
‫)'***‪database('user‬‬
‫و نستطيع ان ندرج الكثير من البرامترات و لكن يستحسن ان نقسم المهام على البرامترات‬
‫بحيث انه يوجد نوعان من البرارميتر‬
‫‪formal_args‬‬
‫وهي البراميترات العادية التي استعملناها في المثلة السابقة‬
‫*‪var_args_tuple‬‬
‫هذا النوع الثاني من البراميترات و تسبقه دائما علمة * و نستعمل هذا النوع عندما ل نريد ان نحدد نوع‬
‫البارميتر هل هو سلسلة او عدد ‪,,‬الخ‬
‫كما نستعمل هذا النوع ايضا عندما يكون لدينا حاجة لستعمال كثير من البراميترات فنعرف البراميترات‬
‫الساسية كما في النوع الول و الباقية سيتكلف بها البراميتر الثانوي‬
‫‪def info(name,age,*others):‬‬
‫)‪print '%s args 1' %(name‬‬
‫)‪print '%d args 2'%(age‬‬
‫‪for each in others:‬‬
‫‪print ' anothers args' ,each‬‬
‫)'‪info('chouaib',22,'algeria','constantine','2008','blablabla‬‬
‫و كما عودتنا هذه اللغة الرائعة فإننا نستطيع ان ندرج أي نوع من المتغيرات دون الحاجة لتحديدها مسبقا‬
‫)‪info('chouaib',22,33.5,'aaaaaa',694589.265‬‬

‫و لهذا تسمى هذه البراميترات ب ‪ tupl_args‬لن ‪ tuple‬كما رأينا سابقا تحجز كل أنواع البيانات بغض‬
‫النظر عن نوعها‬
‫و يتعدد استعمال هذا النوع من البراميترات و لكن الستعمال الكثر يكون مع قواعد البيانات و الملفات لنها‬
‫تتيح لنا ادراج معلومات او بيانات غير محدودة من ناحية النوع او الكم‬
‫كما اننا نستطيع الستعانة بهذا النوع في بعض المور الحسابية‬
‫مثال‬
‫‪def sum(*numbers):‬‬
‫‪result = 0‬‬
‫‪for number in numbers: result += number‬‬
‫‪return result‬‬
‫)‪print sum(23,42‬‬
‫يوجد نوع آخر من البراميترات يسمى بـ براميتر القاموس ‪dico_args‬‬
‫و يرمز له ب ** قبل اسم البراميتر‬
‫مثال‬
‫‪def data_dico(**data):‬‬
‫‪return data‬‬
‫)‪data_dico(chouaib=22,muslim=23‬‬

‫او‬
‫‪def data_dico(**data):‬‬
‫‪return data‬‬
‫)‪print data_dico(chouaib=22,muslim=23‬‬

‫عبارة ‪lambda‬‬
‫تمكننا هذه العبارة من انشاء دوال مبهمة ‪anonymous‬‬
‫ونقول عنها انها مبهمة لنها ل تعرف بالطريقة التي جرت العادة عليها و تستطيع هذه الدوال ان تحمل اي عدد‬
‫من البراميترات و لكنها تعود على قيمة واحدة فقط‬
‫‪lambda parameters: expression‬‬
‫مثال‬
‫‪def hellow():‬‬
‫'‪return 'hellow‬‬
‫)(‪print hellow‬‬

‫'‪lambda :'hellow‬‬

‫‪def a(x,y):‬‬
‫‪return x*y‬‬
‫)‪a(9,5‬‬

‫‪x=lambda a,b: a*b‬‬


‫)‪x(9,5‬‬

‫و في حالة ما اردنا ان ندرج البراميترات المختلفة‬


‫‪info=lambda *tup:tup‬‬
‫)‪print info('chouaib',22‬‬
‫او‬
‫‪database=lambda **data:data‬‬
‫)‪print database(user1=182158,user2=6585485,user3=4765465‬‬
‫او الثنين معا‬
‫‪database=lambda **data:data‬‬
‫)‪print database(user1=182158,user2=6585485,user3=4765465‬‬
‫واضح جدا التسهيل الذي تمنحه لنا هذه العبارة بحيث انها تجنبنا التعقيدات و الكواد المطولة و لكن تستعمل‬
‫عبارة ‪ lambda‬عندما يكون لدينا عمل بسيط و ل نريد انشاء دالة كاملة لجله‬
‫صحيح ان العبارة تسهل علينا العمل و لكن في نفس الوقت تقيد الحرية المتاحة لنا و خلصة القول هي ان نتجه‬
‫نحو هذه العبارة لمعالجة المور الثانوية في الكود التي ل تتطلب انشاء دالة كاملة‬
‫عبارة ‪apply‬‬
‫تمكننا هذه العبارة من تنفيد اجراء على بيانات معينة او تنفيد عمل على عمل آخر او تطبق مخرجات دالة على‬
‫مدخلت دالة دالة اخرى‬
‫فلو عدنا للمثال الول الذي ابتدئنا به الذي برمجنا فيه لعبة ايجاد ناتج العملية بحيث انني ذكرت اننا سنطبق‬
‫العمليات على العداد بطريقة اخرى و هاهي الطريقة التي كنت اتحدث عنها‬
‫‪from operator import add, sub, mul‬‬
‫)'*'‪op=('+','-',‬‬
‫)))'‪nums=(int(raw_input('Enter number 1: ')),int(raw_input('Enter number 2 :‬‬
‫}‪ops={'+':add, '-':sub, '*':mul‬‬
‫)'* ‪ch=raw_input('Enter an operator, + -‬‬
‫‪if ch in op:‬‬
‫)‪res=apply(ops[ch],nums‬‬
‫)‪print '%s%s%s=%d' %(nums[0],ch,nums[1],res‬‬
‫‪else:‬‬
‫'‪print'invalide operator‬‬
‫لحظوا السطر التالي‬
‫)‪res=apply(ops[ch],nums‬‬

‫قمنا بتطبيق عمل ‪ ops‬على العداد المحجوزة في المتغير ‪nums‬‬


‫عبارة ‪filter‬‬
‫كما يدل اسمها تقوم هذه العبارة بتحديد مخرجات دالة معينة و تصفيتها او توجيهها حسب رغبتنا‬
‫مثال‬

‫‪def leap(n):‬‬
‫‪return n%4==0‬‬
‫][=‪list_yr‬‬
‫)' ? ‪ch=raw_input('Do you want to enter a year‬‬
‫‪while 1:‬‬
‫‪if ch in ('y','yes','Y'):‬‬
‫)'‪yr=raw_input('Enter a year:‬‬
‫))‪list_yr.append(int(yr‬‬
‫)' ? ‪ch=raw_input=('Do you want to enter another year‬‬
‫‪else:‬‬
‫‪break‬‬
‫)‪leap_yrs=filter(leap,list_yr‬‬
‫)‪print 'You have entered %d leap years, they are : \%s'%(len(leap_yrs),leap_yrs‬‬

‫يطلب هذا البرنامج من المستخدم ادخال سنوات معينة ثم يقوم البرنامج بطبع السنوات الكبيسة فقط‬
‫)‪leap_yrs=filter(leap,list_yr‬‬

‫في هذا السطر قمنا بفلترة مخرجات السلسلة ‪ list_yr‬بحيث ان السلسلة ‪ leap_yrs‬ستحجز المخرجات‬
‫المتوافقة مع الدالة ‪ leap‬فقط‬

‫بهذا نكون قد مررنا على أهم المحطاة المتعلقة بالدوال سنطبق في الدرس القادم بعض المثلة على كل‬
‫مادرسناه سابقا ثم نمر لموضوع آخر‬

‫تم بحمد ال‬


‫تمرين‪:‬‬
‫سنضع بإذن ال في هذا الدرس مشروع مفتوح للتطوير نضع له حجر الساس في هذا الدرس ثم نطوره شيئا‬
‫فشيئا فكرة المشروع تكمن في انشاء استمارة تسجيل لموقع او لشركة ‪,,,,‬‬
‫بحيث تأخذ من المستخدم المعلومات الزمة ثم تفحص هذه المعلومات و يقوم البرنامج في الخير بحفظ‬
‫المعلومات في ملف كما قلت هذه النظرة الولى حول المشروع و سنضيف له الكثير من المور كما سنرى‬
‫البرنامج يحتوي مبدئيا على ‪ 7‬دوال زائد الدالة الرئيسية اي بالكل ‪ 8‬دوال‬
‫و يستدعي البرنامج مكتبتين‬
‫رأس البرنامج‬
‫‪import time‬‬
‫‪from time import sleep‬‬
‫‪import sys‬‬
‫‪month, day, year, age=0, 0, 0, 0‬‬
‫‪cur_year, cur_month, cur_day=0, 0, 0‬‬

‫استدعينا الدالة ‪ time‬للتعامل مع الوقت و من نفس المكتبة استدعينا الدالة ‪ sleep‬و اخيرا استدعينا الدالة‬
‫‪ sys‬للتعامل مع الملفاة‬
‫ثم قمنا بتعريف المتغيرات الساسية و التي ستتعامل معها الدوال بحيث ان كل دالة تحتاج التعامل مع هذه‬
‫المتغيرات نعرف هذه المتغيرات داخلها بصيغة ‪global‬‬
‫دوال البرنامج‬
‫دالة ‪isblank‬‬
‫‪def isblank(var):‬‬
‫‪while len(var)==0:‬‬
‫‪try:‬‬
‫'‪print 'you can\'t leav it blank‬‬
‫)'‪var=raw_input('Enter a value :‬‬
‫‪except Exception ,e:‬‬
‫‪print "Error !!",e‬‬
‫‪return var‬‬

‫تقوم هذه الدالة بفحص مدخلت المستخدم بحيث لو لم يدخل شيئ ستطالبه هذه الدالة باعادة الدخال مرة اخرى‬
‫دالة ‪alpha‬‬
‫‪def alpha(var):‬‬
‫‪while 1:‬‬
‫‪if not var.isalpha():‬‬
‫'‪print'Invalid entry‬‬
‫)'‪var=raw_input('re-enter pleas :‬‬
‫‪continue‬‬
‫‪else:‬‬
‫‪break‬‬
‫‪return var‬‬

‫تقوم هذه الدالة بفحص مدخلت المستخدم هل هي حرفية او رقمية و سنحتاجها لفحص اسم و لقب المستخدم و‬
‫مكان اقامته ‪-‬بلده‪ -‬لنه من المستحيل ان تحتوي هذه المدخلت على ارقام‬
‫و اذا حدث و ادخل المستخدم ارقام ستطالبه الدالة باعادة الدخال‬

‫دالة ‪def date_of_b‬‬


‫‪def date_of_b():‬‬
‫‪global month‬‬
‫‪global year‬‬
‫‪global day‬‬
‫‪global age‬‬
‫‪while 1:‬‬
‫)'‪d_of_b=raw_input('Enter your date of birth, /*format*/ ==> mm-dd-yyyy‬‬
‫)‪d_of_b=isblank(d_of_b‬‬
‫‪if len(d_of_b)<> 10:‬‬
‫'!! ‪print 'Enter date in correct format‬‬
‫‪continue‬‬
‫)]‪month=int(d_of_b[:2‬‬
‫)]‪day=int(d_of_b[3:5‬‬
‫)]‪year=int(d_of_b[6:10‬‬
‫)(‪age=age_fun‬‬
‫‪if chek_valid_fun()==0:‬‬
‫'‪print 'Invalid date of birth‬‬
‫‪continue‬‬
‫‪else:‬‬
‫‪break‬‬

‫تقوم هذه الدالة بالطلب من المستخدم ادخال تاريخ ولدته و بعد ادخال المستخد للتاريخ نقسم هذا التاريخ حسب‬
‫اليام و الشهور و السنة و نسند كل جزء لمتغير منفصل‬
‫)]‪month=int(d_of_b[:2‬‬
‫)]‪day=int(d_of_b[3:5‬‬
‫)]‪year=int(d_of_b[6:10‬‬
‫و قمنا بهذا التقسيم حتى نتمكن من حساب العمر و يكون هذا الحساب بواسطة دالة اخرى اسمها ‪age_fun‬‬

‫دالة ‪age_fun‬‬
‫‪def age_fun():‬‬
‫‪global cur_year‬‬
‫‪age=cur_year-year-1‬‬
‫‪if month<cur_month or (month==cur_month and day<cur_day):‬‬
‫‪age=age+1‬‬
‫)‪return str(age‬‬
‫عمل هذه الدالة بسيط بحيث انها تقوم بطرح السنة الحالية ‪ cur_age‬و التي سنراها بعد قليل بالسنة التي ولد‬
‫بها المستخدم‬
‫و الشاهد هنا ان هذه الدالة تحسب العمر بدقة اي مع احتساب فوارق الشهور‬
‫و لو عدنا للدالة ‪ date_of_b‬سنلحظ اننا استخدمنا دالة اخرى مع دالة ‪ age_fun‬و هي دالة‬
‫‪chek_valid_fun‬‬
‫دالة ‪chek_valid_fun‬‬
‫‪def chek_valid_fun():‬‬
‫‪while 1:‬‬
‫‪if year<=0 or month <=0 or day<=0:‬‬
‫‪break‬‬
‫‪if cur_year<year:‬‬
‫‪break‬‬
‫‪if month>12:‬‬
‫‪break‬‬
‫‪if month in (1,3,5,7,8,10,12):‬‬
‫‪if day>31:‬‬
‫‪break‬‬
‫‪elif month in (4,6,9,11):‬‬
‫‪if day>30:‬‬
‫‪break‬‬
‫‪if year%4==0 and month==2:‬‬
‫‪if day>29:‬‬
‫‪break‬‬
‫‪return 1‬‬
‫‪return 0‬‬
‫تقوم هذه الدالة بالتحقق من التاريخ الذي يدخله المستخدم بدقة عالية بحيث انها تساعدنا على اكتشاف خطئ في‬
‫تاريخ ولدة المستخدم و بهذه الصورة نتجنب التواريخ الغير منطقية‬
‫و لقد استعملنا في هذه الدالة طريقة جديدة و هي العودة على عدة قيم حسب الحالت‬
‫‪if year%4==0 and month==2:‬‬
‫‪if day>29:‬‬
‫‪break‬‬
‫‪return 1‬‬
‫‪return 0‬‬

‫هنا لو ادخل المستخدم تاريخ خاطئ اي كانت السنة كبيسة و الشهر فيفري و عدد اليام اكبر من ‪ 29‬و هذا‬
‫مستحيل ان يحصل هذا و لو ادخل المستخدم تاريخ مشابه له سنخرج من الحلقة ككل الحالت التي تسبق هذه‬
‫الحالة‬
‫فعند ادخال المستخدم للتاريخ ستفحص هذه الدالة هذا التاريخ بناء على حالت ‪ if‬التي اوردنها فلو لم يتطابق‬
‫تاريخه مع هذه الحالت ‪-‬اي ان التاريخ صحيح‪ -‬ستأخذ هذه الدالة قيمة ‪ 1‬و لو حدث خطئ في التاريخ ستخرج‬
‫الدالة من الحلقة و تأخذ قيمة صفر‬
‫و تفيدنا هذه الطريقة بدراسة احتمالت عديدة فلو رجعنا للدالة الولى ‪ date_of_b‬سنرى فائدة هذا العمل‬
‫‪if chek_valid_fun()==0:‬‬
‫'‪print 'Invalid date of birth‬‬
‫‪continue‬‬

‫هنا يتبين المر الكثر‬


‫قمنا بفحص القيمة التي ترجع عليها الدالة ‪ chek_valid_fun‬فلو كانت هذه القيمة مساوية للصفر معنى هذا‬
‫ان التاريخ خاطئ و سيطبع البرنامج للمستخدم رسالة خطئ و ل نخرج من الحلقة حتى يدخل المستخدم التاريخ‬
‫الصحيح‬
get_chek_info ‫دالة‬
def get_chek_info (question):
var=raw_input(question)
var=isblank(var)
var=alpha(var)
return var

‫قمنا بانشاء هذه الدالة حتى تساعدنا على استقبال المدخلت من المستخدم بحيث اننا نعطيها عنوان الرسالة التي‬
‫نريد فتظهر هذه الرسالة للمستخدم و تأخذ من المدخل‬
saving ‫دالة‬
def saving():
i=0
p='.'
while i<5:
print p,
sleep(1)
i+=1
print 'saving'
‫تضيف هذه الدالة بعض الحيوية و الحركة في نهاية البرنامج بحيث اننا سنحجز المدخلت في ملف فتقوم هذه‬
‫ نقاط متتابعة و بين كل نقطة واخرى يتوقف‬5 ‫الدالة برسم نقاط متتابعة لعملية حفظ الملف فتقوم الحلقة بطبع‬
‫البرنامج لمدة ثانية واحدة ثم يطبع النقطة التالية‬

‫الدالة الرئيسية‬
def main():
global cur_year
global cur_month
global cur_day
t=time.localtime(time.time())
cur_year=t[0]
cur_month=t[1]
cur_dat=t[2]
username=get_chek_info('Enter your name :')
userlname=get_chek_info('Enter your last name :')
ucontry=get_chek_info('Contry : ')
us=get_chek_info('(b)oy or (g)irl :')
date_of_b()
uothers=raw_input('others information :')
print 'You can choose one of following login names : '
first=username+"_"+userlname
print '1. : ',first
second=userlname[0].upper()+"_"+username+str(age)
print '2. :',second
print 'you age is :',age
save=open('/home/chouaib/save', 'w')
save.write('%s %s %s %s %s ' % (username, userlname, ucontry, us, uothers))

save.close()
saving()
‫اول قمنا بتعريف المتغيرات التي سنستعملها بصيغة ‪ global‬حتى تتمكن الدالة الرئيسية من التعديل عليهم و‬
‫التعامل معهم بحرية ثم انشئنا المتغير ‪ t‬و الذي سيأخذ قيمة التاريخ الحالي‬
‫))(‪t=time.localtime(time.time‬‬

‫ثم بواسطة هذا التاريخ اسندنا للمتغيرات ‪ cur_year‬و ‪ cur_month‬و ‪ cur_day‬القيم المناسبة لها‬
‫ثم قمنا بأخذ معلومات المستخدم بواسطة الدالة ‪ get_chek_info‬التي رأيناها سابقا‬
‫ونلحظ ان ‪ uothers‬لم نستعمل فيها هذه الدالة لنها ل تقبل المدخلة العددية و يمكن ان يدخل المستخدم‬
‫اعداد في المعلومات الضافية‬
‫و في الخير نعرض على المستخدم اسمين يمكنه التسجيل بواسطتهما ثم نحجز كل مدخلته في ملف خاص‬

‫)'‪save=open('/home/chouaib/save', 'w‬‬
‫))‪save.write('%s %s %s %s %s ' % (username, userlname, ucontry, us, uothers‬‬

‫)(‪save.close‬‬
‫)(‪saving‬‬
‫اسم المتغير الذي سيسند اليه الملف ‪ save‬و سمينا النلف بنفس اسم المتغير‬
‫ثم انشئنا ملف جديد بواسطة الدالة ‪ open‬و نضع في الول مسار الذي سيحجز فيه الملف‬
‫مثل‬
‫)'‪save=open('C:\my project\save','w‬‬

‫و عبارة ‪ W‬معنها ان يفتح البرنامج الملف للكتابة و ان لم يوجد هذا الملف سيقوم البرنامج بانشائه‬
‫بعدها نقوم بكتابة مدخلة المستخدم بواسطة الدالة ‪write‬‬
‫ثم يأتي دور الدالة التي انشأناها من قبل ‪ saving‬لتعرض النقاط على المستخدم و تنئؤه ان معلوماته حفظة‬

‫كود البرنامج الكامل‬


‫‪import time‬‬
‫‪from time import sleep‬‬
‫‪import sys‬‬
‫‪month, day, year, age=0, 0, 0, 0‬‬
‫‪cur_year, cur_month, cur_day=0, 0, 0‬‬
‫‪def isblank(var):‬‬
‫‪while len(var)==0:‬‬
‫‪try:‬‬
‫'‪print 'you can\'t leav it blank‬‬
‫)'‪var=raw_input('Enter a value :‬‬
‫‪except Exception ,e:‬‬
‫‪print "Error !!",e‬‬
‫‪return var‬‬
‫‪def alpha(var):‬‬
‫‪while 1:‬‬
‫‪if not var.isalpha():‬‬
‫'‪print'Invalid entry‬‬
‫)'‪var=raw_input('re-enter pleas :‬‬
continue
else:
break
return var

def chek_valid_fun():
while 1:
if year<=0 or month <=0 or day<=0:
break
if cur_year<year:
break
if month>12:
break
if month in (1,3,5,7,8,10,12):
if day>31:
break
elif month in (4,6,9,11):
if day>30:
break
if year%4==0 and month==2:
if day>29:
break
return 1
return 0

def age_fun():
global cur_year
age=cur_year-year-1
if month<cur_month or (month==cur_month and day<cur_day):
age=age+1
return str(age)
def saving():
i=0
p='.'
while i<5:
print p,
sleep(1)
i+=1
print 'saving'

def date_of_b():
global month
global year
global day
global age
while 1:
d_of_b=raw_input('Enter your date of birth, /*format*/ ==> mm-dd-yyyy')

d_of_b=isblank(d_of_b)
if len(d_of_b)<> 10:
print 'Enter date in correct format !!'
continue
month=int(d_of_b[:2])
day=int(d_of_b[3:5])
year=int(d_of_b[6:10])
age=age_fun()
if chek_valid_fun()==0:
print 'Invalid date of birth'
continue
else:
break
def get_chek_info (question):
var=raw_input(question)
var=isblank(var)
var=alpha(var)
return var
def main():
global cur_year
global cur_month
global cur_day
t=time.localtime(time.time())
cur_year=t[0]
cur_month=t[1]
cur_dat=t[2]
username=get_chek_info('Enter your name :')
userlname=get_chek_info('Enter your last name :')
ucontry=get_chek_info('Contry : ')
us=get_chek_info('(b)oy or (g)irl :')
date_of_b()
uothers=raw_input('others information :')
print 'You can choose one of following login names : '
first=username+"_"+userlname
print '1. : ',first
second=userlname[0].upper()+"_"+username+str(age)
print '2. :',second
print 'you age is :',age
save=open('/home/chouaib/save', 'w')
save.write('%s %s %s %s %s ' % (username, userlname, ucontry, us, uothers))

save.close()
saving()

main()

‫طبعا مازال البرنامج يحتاج لتعديل كبير و لكي نتم هذا التعديل يتوجب علينا ان ندرس الملفاة و هذا ما سنفعله‬
‫في الدرس القادم‬
‫بعد انهاء الملفاة ستعود للبرنامج و سنضيف عليه القدرة على حفظ معلوات اكثر و بصورة اكثر تنظيما‬
‫ و امور اخرى مفيدة بإذن ال‬... ‫سنضيف عليه خاصية المستعملين و صلحيات مدرير البرنامج‬

‫إذن درسنا المقبل سيكون عن الملفات‬

‫تم بحمد ال‬


‫الدرس العاشر ]الملفات[‪:‬‬
‫تسمح لنا لغة البايثون ككل اللغاة بالتعامل مع الملفاة و يكون هذا التعامل ب الوصول للملفاة و فتحها و قراءة‬
‫محتواها و التعديل عليه او انشاء ملفاة جديدة و حفظ المعلومات بداخلها‬
‫و نستطيع التعامل مع عدة صيغ للملفاة و ليس الملفاة النصية فقط‬
‫فتح الملف‬
‫لكي نستطيع فتح ملف معين يتوجب علينا اول ان ننشئ متغير و يكون هذا المتغير هو الوسيط بيننا و بين‬
‫الملف اي ان كل الوامر التي نريد تنفيدها على هذا الملف نطبقها على المتغير و هو بدوره ينقلها للملف‬
‫و يسمى هذا المتغير ب الوبجيكت ‪ object‬و الدالة التي نستعملها لفتح الملفات تدعى دالة ‪()open‬‬
‫)'‪file_object=open(file_name, access_mode=',,,‬‬
‫يعتبر المتغير او بالحرى الوبجيكت الذي يتولى التعالم مع الملف‬
‫ثم نفتح دالة ‪open‬‬
‫و نحدد اسم الملف او مسار حفظه‬
‫‪access_mode‬‬
‫تعبر عن انواع او الصفة التي نريد فتح الملف من خللها و يوجد عدة صيغ لفتح الملف نذكر منها‬
‫‪ r‬فتح الملف لقراءة محتواه‬
‫‪ w‬فتح الملف للكتابة و نستعمها ايضا لنشاء ملف جديد‬
‫‪ a‬لفتح الملف و الضافة على محتواه‬
‫عمل المرين معا‬ ‫و نستطيع ان باضافة علمة ‪+‬‬
‫‪ r+ w+ +a‬للكتابة و القراءة في وقت واحد‬
‫توجد صيغ اخرى تستعمل لفتح ملفاة لكن ما يهمنا الن هي هذه الصيغ السابق ذكرها ‪binary‬‬
‫طيب نعطي مثال كامل عن فتح ملف و قراءة محتواه قم بانشاء ملف جديد و اكتب فيه بعض السطور ثم احفظه‬
‫افتح مفسر البايثون و اكتب السطور التالية‬
‫)'‪file_name=open('/home/chouaib/test', 'r‬‬
‫)(‪all_lines=file_name.read‬‬
‫)(‪file_name.close‬‬
‫‪print all_lines‬‬

‫داخل دالة ‪ open‬اكتب المسار الكامل للملف‬


‫في السطر الثاني قمنا بانشاء اوبجيكت آخر يقوم هذا الوبجيكت بقراءة كل الملف و ذلك من خلل دالة ‪read‬‬
‫و في السطر الثالث قمنا بغلق الملف لننا انتهينا من استعماله و ل يجب ترك الملف مفتوحا‬
‫و في السطر الخير قمنا بطباعة محتوى الملف‬
‫توجد طريقة اخرى تمكننا من قراءة الملف و لكن هذه الطريقة تعطينا ميزة معرفة نهاية السطور و تستعمل‬
‫هذه الطريقة دالة ‪ readlines‬و تمكننا هذه الدالة من طباعة الملف سطرا سطرا‬
‫)'‪file_name=open('/home/chouaib/test', 'r‬‬
‫)(‪all_lines=file_name.readlines‬‬
‫)(‪file_name.close‬‬
‫‪for line in all_lines:‬‬
‫‪print line‬‬
‫دالة ‪ readlines‬تستطيع التفرقة بين السطور و ستفيدنك هذه الميزة كثيرا في كل برامجك‬
‫الكتابة في الملف‬
‫للكتابة في الملف نتبع نفس الخطواة السابقة و لكن الدوال تتغير في هذه الحالة كما ان صيغة الفتح تصبح ‪w‬‬
‫)'‪file_name=open('/home/chouaib/test', 'w‬‬
‫)' ‪line=raw_input('enter a line‬‬
‫)‪file_name.write(line‬‬

‫و اذا اردنا كتابة اكثر من سطر داخل الملف ما علينا سوى اضافة حلقة على الشكل التالي‬
‫)'‪file_name=open('/home/chouaib/test', 'w‬‬
‫‪while True:‬‬
‫)" ‪line=raw_input("enter a line '.' to quit‬‬
‫‪if line !='.':‬‬
‫)‪file_name.write(line‬‬
‫‪else:‬‬
‫‪break‬‬
‫)(‪file_name.close‬‬
‫و لكن لو فتحنا الملف لوجدنا ان السطور التي كتبناها في البرنامج كتبت في سطر واحد و اذا اردنا ان يكتب‬
‫كل سطر ادخلناه في البرنامج في سطر منفرد داخل الملف يجب ان نعدل على البرنامج فيصبح الخامس كالتالي‬
‫)) ‪file_name.write('%s %s' %(line, os.linesep‬‬
‫بحيث اننا استعملنا الدالة ‪ linesep‬و التي تعني ‪ line separate‬بحيث انها تفرق بين السطور ‪.‬‬
‫و لستعمال هذه الدالة يتوجب علينا استدعاء مكتبة ‪ os‬اول البرنامج‬
‫‪import os‬‬
‫)'‪file_name=open('/home/chouaib/test', 'w‬‬
‫‪while True:‬‬
‫)" ‪line=raw_input("enter a line '.' to quit‬‬
‫‪if line !='.':‬‬
‫)) ‪file_name.write('%s %s' %(line, os.linesep‬‬
‫‪else:‬‬
‫‪break‬‬
‫)(‪file_name.close‬‬
‫طيب الن لو لحظتوا اننا عندما نعيد تشغيل البرنامج يحذف كل محتوى الملف و يكتب السطور الجديدة و لو‬
‫عاودنا مرة اخرى ستحذف هذه السطور و تكتب سطور جديدة ‪,,,,‬‬
‫و لو اردنا فتح الملف و الضافة على سطوره دون حذفها نفتح الملف بصيغة ‪ -a- append‬فيصبح السطر‬
‫الول من البرنامج‬
‫)'‪file_name=open('/home/chouaib/test', 'a‬‬
‫و بهذا نستطيع اضافة سطور جديدة على الملف دون حذف محتواه و لو اردنا الكتابة و القراءة معا نستعمل‬
‫الصيغة ‪ +r‬او ‪+w‬‬
‫‪import os‬‬
‫)'‪file_name=open('/home/chouaib/test', 'r+‬‬
‫)(‪rline=file_name.readlines‬‬
‫‪for l in rline:‬‬
‫‪print l‬‬

‫‪while True:‬‬
‫)" ‪line=raw_input("enter a line '.' to quit‬‬
‫‪if line !='.':‬‬
‫)) ‪file_name.write('%s %s' %(line, os.linesep‬‬
‫‪else:‬‬
‫‪break‬‬
‫)(‪file_name.close‬‬
‫و لكن هنا احسن الصيغ لمثل هذه الحالت استعمال صيغة ‪ +a‬بحيث نستطيع قراءة سطور الملف و الضافة‬
‫عليها دون حذفها و نستطيع ايضا ان نحدد عدد الحرف الذي نريد ان ينسخها البرنامج و ذلك باضافة هذا‬
‫العدد داخل الدالة ‪()read‬‬
‫)‪rline=file_name.read(20‬‬

‫التعامل مع النظام من خلل مكتبة ‪os‬‬

‫توفر لنا مكتبة ‪ os‬عدة دوال للتعامل مع الملفات من خلل النظام كانشاء ملفات جديدة و اعادة تسمية الملف‬
‫حذف الملفات ‪,,,‬الخ‬
‫اعادة تسمية الملف‬
‫اول نقوم باستدعاء المكتبة ‪os‬و الدالة المستعملة لتغير السم هي دالة ‪rename‬‬
‫‪import os‬‬
‫)'‪os,reanme('old_file', 'new_file‬‬
‫مثال‬
‫‪import os‬‬
‫)'‪os.rename('/home/chouaib/test', '/home/chouaib/test1‬‬
‫طبعا على نظام الويندوز ل يتغير شيئ سوى المسار‬
‫‪import os‬‬
‫)'‪os.rename('C:\My ********s\test', 'C:\My ********s\test1‬‬
‫انشاء مجلد جديد‬
‫تسمح لنا نفس المكتبة انشاء مجلد جديد من خلل الدالة ‪()mkdir‬‬
‫)'‪os,mkdir('new_dir‬‬
‫مثال‬
‫‪import os‬‬
‫)'‪os.mkdir('/home/chouaib/pythondir‬‬
‫اظهار محتوى المجلد‬
‫لكي نستعرض محتوى مجلد معين اي نستعرض الملفات و المجلدات التي يحتويها المجلد الول نستعمل الدالة‬
‫‪()listdir‬‬
‫مثال‬
‫‪import os‬‬
‫)'‪print os.listdir('/home‬‬
‫و يكون المخرج عبارة عن سلسلة كهذه‬
‫]'‪['lost+found', 'chouaib‬‬
‫و بهذا نستطيع ان ننشئ متغير يحجز لنا محتوى هذه السلسلة لستعماله و استغلله في البرنامج‬
‫مثل‬
‫‪import os‬‬
‫)'‪list= os.listdir('/home/chouaib‬‬
‫‪i=1‬‬
‫‪for a in list:‬‬
‫‪print 'file ID : %d __ name :‬‬ ‫)‪%s' %(i,a‬‬
‫‪i+=1‬‬
‫حذف ملف‬
‫نستعمل الدالة ‪remove‬لحذف الملفات‬
‫مثال‬
‫‪import os‬‬
‫)'‪os.remove('/home/chouaib/test1‬‬
‫اظهار المسار و تغيره‬
‫اذا كنت تريد ان تعرف المسار الكامل الذي انت فيه فعليك استعمال دالة‬
‫‪()getcwd‬‬
‫و لتغير هذا المسار او الذهاب للمسار جديد نستعمل دالة ‪ ()chdir‬ثم نضع المسار الذي نريد الذهاب اليه‬
‫مثال‬
‫‪import os‬‬
‫)'‪os.chdir('/home/chouaib‬‬
‫)(‪print os.getcwd‬‬
‫)'‪os.chdir('/usr‬‬
‫)(‪print os.getcwd‬‬

‫‪()print os.getcwd‬‬
‫اذا فالدالة الولى تغير المسار و الدالة الثانية تعلمنا بالمسار الحالي نبقى مع نفس المكتبة لنرى خصائص اخرى‬
‫تقدمها لنا من خلل مكتبة ‪path‬‬
‫تحليل المسار‬
‫تمكننا دالة ‪ basename‬و دالة ‪dirname‬‬
‫من تحليل المسار و معرفة اسم المجلد و اسم الملف‬
‫مثال لمعرفة اسم الملف‬
‫‪import os.path‬‬
‫)'‪print os.path.basename('/home/chouaib/save‬‬
‫مثال لمعرفة المجلد الب‬
‫‪import os.path‬‬
‫)'‪print os.path.dirname('/home/chouaib/save‬‬
‫حفظ المسار على شكل سلسلة‬
‫في احيان كثيرة ستحتاج لحجز اسم المسار و تقسيمه للستغلله في برنامج و لهذا تقدم لك لغة البايثون دالة‬
‫‪ split‬التي تقسم المسار و تحجزه في متغير آخر انت تختاره‬
‫مثال‬
‫‪import os.path‬‬
‫)'‪dir= os.path.split('/home/chouaib/save‬‬
‫‪print dir‬‬
‫فيكون الناتج‬
‫)'‪('home/chouaib', 'save/‬‬
‫معرفة حجم الملف‬
‫لمعرفة حجم ملف او مجلد معين نستعمل دالة ‪()getsize‬‬
‫مثال‬
‫‪import os.path‬‬
‫)'‪print os.path.getsize('/home/chouaib/save‬‬
‫و يكون الحجم بالبايت ‪byte‬‬
‫دوال اخرى مفيدة‬
‫دالة ‪exist‬‬
‫لمعرفة ان كان يوجد الملف او ل و تعود الدالة على قيمة ‪ 1‬ان كان الملف موجود و قيمة ‪ 0‬ان كان الملف‬
‫غير موجود‬
‫مثال‬
‫‪import os.path‬‬
‫)'‪e=os.path.exists('/home/chouaib/save‬‬
‫‪if e==1:‬‬
‫'‪print ' file exist‬‬
‫‪else:‬‬
‫'‪print 'file does not exist‬‬
‫دالة ‪isdir‬‬
‫لمعرفة ان كان آخر المسار عبارة عن ملف او مجلد و كالدالة السابقة تعود على قيمة ‪ 1‬ان كان مجلد و ‪ 0‬ان‬
‫كان ملفا‬
‫مثال‬
‫‪import os.path‬‬
‫)'‪e=os.path.exists('/home/chouaib/save‬‬
‫‪if e==1:‬‬
‫'‪print ' file exist‬‬
‫‪else:‬‬
‫'‪print 'file does not exist‬‬
‫ثوجد دالة اخرى مشابهة لهذه الدالة و لكنها مخصصة للملفات اسمها دالة ‪ isfile‬و نستعملها كالدالة السابقة و‬
‫لكن هذه الدالة تعود على قيمة ‪ 1‬ان كان آخر المسار ملفا و تعود على قيمة ‪ 0‬ان كان شيئ آخر عدى ملف‬
‫هذه ابرز الدوال المخصصة للتعامل مع الملفاة و استغلل هذه الدوال يتيح لنا حرية كبيرة في البرمجة بواسطة‬
‫الملفات‬
‫سنحاول اتمام البرنامج الذي بدئنا فيه مسبقا و نحاول استغلل كل هذه الدوال لنشاء برنامج نستعمل فيه هذه‬
‫الطرق التي رأينها لكي تترسخ لدينا فكرة واضحة عن الملفاة و لتدعيم او اكتساب بعض الخبرة‬

‫تم بحمد ال‬

‫يا جماعة من المستحسن ان نستعمل من هنا فصاعدا برنامج ‪ eclips‬لنه الروع‬


‫بالنسبة للغة البايثون‬

‫للتحميل البرنامج‬

‫‪http://www.eclipse.org/downloads‬‬
‫الدرس الحادي عشر]‪:[OOP‬‬
‫نبتدئ يا اخوة اليوم بحمد ال تعالى في البرمجة الكائنية الموجهة‬
‫أرجو منك اخي القارئ ان تكمل القراءة إلى آخر الدرس و تركز قليل لني اعتمدت اكثر من تعريف و في كل‬
‫مرة اضيف شيئا جديدا في التعريفات و بإذن ال ستنهي الصفحة و انت فاهم للدرس‬
‫‪Object-Oriented Programming‬‬

‫مقدمة حول البرمجةالكائنية الموجهة ‪,‬‬


‫في جميع برامجنا وحتى الن ‪ ،‬قمنا بتصميم برنامجنا حول دوال أو كتل من البيانات التي تتلعب‬
‫بالبيانات‪.‬فمعظم برامجنا الخيرة كانت عبارة عن مجموعة من الدوال التي تحتوي بنفسها على مجموعة من‬
‫التعليمات و في الكود الرئيسي قمنا بتوجيه هذه الدوال حتى تقوم بالعمل الذي نريده ويسمى هذا طريقة البرمجة‬
‫الجرائية الموجهة ‪.procedure-oriented‬‬
‫وهناك طريقة أخرى لتنظيم برنامجك الذي هو الجمع بين الوظيفة والبيانات وتغليفها معا فيما يسمى بالكائن أي‬
‫أننا نقوم بجمع الوظائف او التعليمات مع البيانات و نقوم بتغليفها و جمعها في كائن وهذا ما يسمى نموذج‬
‫البرمجة الكائنية التوجه ‪Object-Oriented Programming‬‬
‫للمبرمج الحرية في استعمال اي طريقة تناسبه و لكن في البرامج الكبيرة التي تحتوي على كم هائل من‬
‫المعلومات و المهام لبد من استعمال البرمجة الكائنية الموجهة لننها و كما قلنا سابقا تمكن المبرمج من جمع‬
‫البيانات و الوظائف معا و تمكنه من تغليفها في كائن واحد و هذا ما يساعد في تنظيم البرنامج حتى و لو كان‬
‫ضخما و يعطي هذا النمط من البرمجة الحرية للمبرمج بتوجيه الكائنات و الوظائف حتى تعطيه النتائج الماردة‬
‫من خلل مشروعه‬
‫لن أستطيع ان اعرف البرمجة الكائنية الموجهة في مقدمة فهذا محال لننا الن أمام نمط برمجي جديد علينا‬
‫كليتا لذا سأحاول في هذا الدرس تعريف أقسام هذا النمط و اعطاء العديد من المثلة و في كل مرة نتوقف‬
‫بالشرح عند كل جزء و عندما تتكون لدينا صورة واضحة سندعم فهمنا بمجموعة من البرامج الكاملة‬
‫الكلس ‪Class‬‬
‫ح التعبير‬
‫تعتبر الكلس كوعاء يحوي العديد من الوظائف و المعرفات فالكلس هي عبارة عن بيضة ان ص ّ‬
‫تحوي داخلها على بيانات و وظائف و نستطيع تشبيهها بالدوال التي رأيناها سابقا إذ ان الدالة تحوي بداخلها‬
‫مجموعة من التعريفات و التعليمات ثم تطبق هذه التعليمات على المتغير الذي نسنده لهذه الدالة و ذلك عن‬
‫طريق التعريفات‬
‫نفس الشيئ بالنسبة للكلس و لكن مع توسع كبير هذه المرة‬
‫نقبل بهذا التعريف الولي و سندعمه بتعريفات أخرى في باقي الدرس‬
‫إنشاء الكلس‬
‫لنشاء كلس جديد نقوم بكتابة الكلمة المخصصة ‪ class‬ثم تليها اسم الكلس‬
‫مثال‬
‫‪class My_class:‬‬
‫'‪'exemple of class data atributes‬‬
‫‪a=125‬‬
‫‪b=8958‬‬
‫‪print My_class.a‬‬
‫‪print My_class.b‬‬
‫قمنا باختيار اسم للكلس ‪My_class‬‬
‫و هنا ملحظة‬
‫يستحسن كتابة الحرف الول من اسم الكلس بالحجم الكبير فهذا يعتبر عرف عند كل المبرمجين و في كل لغاة‬
‫البرمجة‬
‫طيب الن ركزو معي قليل‬
‫ماهي الكلس ؟؟‬
‫تعتبر الكلس صنف مثل من الكائنات الحية نأخذ الطيور فالطيورصنف من الكائنات الحية‬
‫لو دققنا في هذا الصنف نجد ان لكل طائر صفاة خاصة به‬
‫اللون و الطول الوزن ‪,,,,,,,,,,‬‬
‫كذلك لكل كلس صفات خاصة بها و تسمى الصفاة بـ ‪attributes‬‬
‫مثال‬
‫فلننشئ كلس و نسميها ‪ Bird‬ثم نعطيها صفات خاصة بها‬
‫‪class Bird:‬‬
‫‪pass‬‬
‫'‪Bird.color='yellow‬‬
‫'‪Bird.poid='58gr‬‬
‫'‪Bird.name='coucou‬‬

‫‪print Bird.color‬‬
‫‪print Bird.poid‬‬
‫‪print Bird.name‬‬
‫قمنا بإنشاء الكلس و تركناها فارغة و نستطيع فعل هذا بواسطة الكلمة ‪pass‬‬
‫المهم بعد النشاء اعطينا هذه الكلس ‪ attributes‬او صفاة خاصة بها تميزها عن باقي الكلس الخرى في‬
‫البرنامج و هذه الصفاة هي اللون و الوزن و السم‬

‫نعرف الكلس مرة أخرى‬


‫ل وعاء يحوي داخله مجموعة من الصفاة و الوظائف‬ ‫الكلس ماهي إ ّ‬
‫أو بعبارة اخرى الكلس عبارة عن بويضة تظم داخلها مجموعة من الصفات و التي نستعملها في البرنامج‬
‫كأساس لتعبئة البيانات بالضافة للصفاة تضم الكلس ايضا مجموعة من الوظائف ‪methodes‬‬
‫تمثل هذه الـ ‪ methodes‬الوظائف و المهام التي تقوم بها الكلس‬
‫فلو عدنا للمثال الذي ضربناه سابقا صنف الطيور له صفات تميزه عن باقي الصناف و كذلك له مهام يقوم بها‬
‫مثل الطيران الكل النوم الصيد ‪,,,‬‬
‫كذلك الكلس لها وظائف معينة تقوم بها في البرنامج و تنبني هذه الوظائف على الصفاة‬
‫و نستطيع ان نلخص تعريف الكلس في السطر التالي‬
‫الكلس= مجموعة من الصفات‪ +‬مجموعة من الوظائف‬
‫نتفق الن ان الكلس تحتوي على صفاة و وظائف رأينا مثال بسيط جدا عن الصفاة سندرس الن الوظائف و‬
‫الطريقة المعتمدة لدراج الصفاة‬
‫لكن قبل هذا ندرس الحالت ‪ Instances‬فهي بسيطة جدا ننهيها و نمر للوظائف‬
‫‪Class Instances‬‬
‫معنى ‪Instances‬هي اسناد الكلس إلى كائن ‪ -Instances-‬يرث هذا الخير كل خصائص الكلس و‬
‫بواسطة هذا الـ ‪ Instances‬نستطيع استغلل وظائف الكلس و نقول ان هذه ‪ instance‬صارة عبارة عن‬
‫حالة للكلس‬
‫مثال‬
‫‪class My_class:‬‬
‫'‪'exemple of class Instance‬‬
‫‪a=125‬‬
‫‪b=8958‬‬
‫)(‪inst=My_class‬‬
‫‪print inst.a‬‬
‫‪print inst.b‬‬
‫‪print inst.a+inst.b‬‬
‫كما نلحظ قمنا بإسناد ‪ instances inst‬الى الكلس ‪My_class‬‬
‫و بهذا ورث ‪ inst‬كل خصائص الكلس و استطعنا من خلله استغلل بينات الكلس‬
‫طيب الن سنعرف أهمية استعمال ‪instance‬‬
‫عندما ندخل الن للوظائف‬
‫) ‪Method (Functional attributes‬‬
‫ما هي الميثود ؟؟‬
‫قلنا قبل قليل أن الكلس تحتوي على صفاة و وظائف الصفاة رأيناها تبقى لنا الوظائف سنضرب الن مثال آخر‬
‫نفرض انه لدينا سيارة تمثلها كلس‬
‫طبعا كل سيارة لها صفاة خاصة بها هي اللون و الحجم ‪.........‬‬
‫هذه صفاة السيارة‬
‫و للسيارة أيضا وظائف تتمثل هذه الوظائف في‬
‫النطلق التوقف الدوران ‪...................‬‬
‫سننشأ الن كلس نسميها ‪ Car‬و نعطيها الصفات اول‬
‫‪class Car:‬‬
‫‪def __init__(self, color, size):‬‬
‫‪self.color=color‬‬
‫‪self.size=size‬‬
‫نشرح خطوة خطوة‬
‫بعدما انشأنا الكلس قمنا باعطائها صفاة معينة لها‬
‫__‪ __init‬هي عبارة عن كلمة محجوزة للغة البايثون و هي ميثود ايضا معنها ‪ initialisation‬أي التهيئة و‬
‫اسمها يدل على وظيفتها تقوم هذه الميثود بتهيئة الصفاتو هي تبقى بل عمل فإذا اسندنا حالة ‪instance‬‬
‫للكلس‬
‫تنطلق الميثود __‪ __init‬في العمل و تقوم بتهيئة الصفاة و اسنادها للحالة التي انشأنها سنفهم هذا عندما نكمل‬
‫الكود‬
‫و كل ماكتبناه في هذا الكود يعتبر صفة للكلس ‪ Car‬و هي ليست دالة فل يجب الخلط حتى و لو ابتدئ السطر‬
‫بـ ‪ def‬ل تسمى هنا دالة بتاتا و إنما تسمى ‪ method‬للكلس ‪ Car‬الن قمنا بإنشاء الكلس و اعطيناها صفاة‬
‫كيف سنستفاد من هذه الصفاة يجب اول ان ننشئ حالة ‪ instance‬و من خللها نستغل هذه الصفاة‬
‫مثال‬
‫)'‪BMW=Car('red', '5 places‬‬
‫‪print BMW.color‬‬
‫‪print BMW.size‬‬
‫قمنا بإنشاء حالة ‪ BMW‬و اسنادناها للكلس في هذه اللحظة تنطلق الميثود __‪ __init‬و تقوم بتهيئة الكلس‬
‫و تهيئة الصفاة ثم تقوم بتعويض ‪ self‬الخاص بالكلس و نقله للكائن الجديد ‪BMW‬‬
‫‪ self‬هنا تلعب دور الوسيط بين الميثود التابعة للكلس و ماأدخلناه من بيانات في الكائن الجديد او الحالة‬
‫الجديدة ‪ BM‬و لنا الخيار باستعمال ‪ self‬أو ‪this‬‬
‫طبعا مستعملين الجافا و السي شارب سيفضلون ‪ this‬لنها هي نفسها التي في لغة الجافا و السي شارب نعطي‬
‫نفس المثال و لكن بعبارة ‪this‬‬
‫‪class Car:‬‬
‫‪def __init__(this, color, size):‬‬
‫‪this.color=color‬‬
‫‪this.size=size‬‬

‫)'‪BMW=Car('red', '5 places‬‬


‫‪print BMW.color‬‬
‫‪print BMW.size‬‬
‫كما في ‪ self‬تماما تقوم ‪ this‬بربط صفاة الكلس ‪ Car‬إلى الحالة او الكائن الجديد ‪BMW‬‬
‫أظن يا اخوتي أن مفهوم البرمجة الكائنية بدئ يتضح نوعا ما ‪ .‬الن رأينا صفاة الكلس و رأينا كيفية استعمالها‬
‫سنرى الن الوظائف‬
‫في نفس المثال سنقوم بإضافة وظائف لهذه السيارة او بمعنى ادق نضيف ميثود وظيفية للكلس ‪Car‬‬
‫‪class Car:‬‬
‫‪def __init__(this, color, size):‬‬
‫‪this.color=color‬‬
‫‪this.size=size‬‬
‫‪def start(self):‬‬
‫"‪print "the car started‬‬
‫‪def stop(self):‬‬
‫"‪print "this car stoped‬‬

‫)'‪BMW=Car('red', '5 places‬‬


‫‪print BMW.color‬‬
‫‪print BMW.size‬‬
‫)(‪BMW.start‬‬
‫)(‪BMW.stop‬‬
‫أظفنا للنفس الكلس وظائف و هي النطلق و التوقف و نلحظ ان الميثود ‪start‬و الميثود ‪stop‬تشبه الدوال‬
‫و لكن قلنا انها في هذه الحالة تسمى ‪method‬و السطر الول ‪-‬صفاة الكلس‪ -‬تسمى ‪attributes‬‬
‫مثال آخر اكثر واقعي‬
‫لدينا كلس اسمها ‪ student‬تحتوي على صفاة و هي السم و العمر و النقطة الول و النقطة الثانية كما‬
‫تحتوي هذه الكلس على وظيفة واحدة و هي حساب معدل النفطتين‬
‫‪class Student:‬‬
‫‪def __init__(self, name, age, n1, n2):‬‬
‫)‪self.name=str(name‬‬
‫)‪self.age=str(age‬‬
‫)‪self.n1=int(n1‬‬
‫)‪self.n2=int(n2‬‬

‫‪def moy(self):‬‬
‫‪m=(self.n1+self.n2)/2‬‬
‫‪print m‬‬

‫)‪s=Student('Ahmed', '18',15, 19‬‬


‫)(‪s.moy‬‬
‫نلحظ اننا اذا استعملنا احد صفاة الكلس يجب كتابة كلمة ‪ self‬أو ‪this‬‬
‫قبلها لنه كما قلنا ان وظيفة هذه العبارة هي تعويض القيم عند اسناد الكلس لكائن جديد و اسمه في الكود ‪s‬‬
‫نلخص مرة اخرى معتمدين على هذا المثال‬
‫الكلس عبارة عن صنف يضم داخلة قسمين اثنين مجموعة من الصفاة و تسمى ‪attributes‬‬
‫نقوم يادراجها من خلل الصيغة التالية‬
‫)‪def __init__(self or this, attributes‬‬
‫بعد ذلك نقوم بربط الصفاة بواسطة الكلمة ‪ self‬أو ‪this‬‬
‫‪,self‬صفة أ=صفة أ‬
‫‪,this‬صفة أ=صفة أ‬
‫بعد ذلك نقوم بإدراج الوظائف لهذه الكلس و هي شبيهة بالدوال و لكن ل تسمى دوال بل تسمى ‪method‬‬
‫هنا يصبح المر عادي نعتمد على الصفاة و البيانات المدرجة في ‪attributes‬‬
‫لكي ننشئ وظائف ‪ method‬للكلس‬

‫هذا يا اخواني يعتبر مدخل متواضع للبرمجة الكائنية الموجهة مازال ينتظرنا الكثير في هذا النمط في الدروس‬
‫القادمة‬
‫سأحاول التركيز اكثر على المثلة التطبيقية‬
‫الدرس الثاني عشر‪:‬‬
‫نتابع ما ابتدءناه في الدرس السابق و هذا الدرس يعتبر التعريف الصحيح و المعتمد لكل ما رأيناه في الدرس‬
‫السابق فلم اتعمد في الدرس السابق استعمال لكثير من التسميات و حاولت ان اشرح بعض المفاهيم بصورة‬
‫تقريبية و في هذا الدرس سنعرف كل مارأيناه سابقا بصورة‬
‫رسمية و من فهم الدرس السابق سيمر على هذا الدرس بسهولة لنه عبارة عن تثبيت المفاهيم السابق و لن نأتي‬
‫بشيئ جديد‬
‫و نبتدء بحول ال بمثال نراجع فيه الدرس السابق‬
‫المثال عبارة عن كلس اسمها ‪ Info‬تحتوي على صفاة و على وظائف‬
‫نتتبع المثال ثم نشرح‬
‫‪import os‬‬
‫‪import sys‬‬
‫‪class Info :‬‬
‫‪def __init__(self, name, mpass, age, email):‬‬
‫)‪self.name=str(name‬‬
‫)‪self.mpass=str(mpass‬‬
‫)‪self.age=int(age‬‬
‫)‪self.email=str(email‬‬
‫‪def save_info(self, nfile):‬‬
‫‪self.nfile = nfile‬‬
‫‪try:‬‬
‫)'‪ff= open(self.nfile, 'a+‬‬
‫‪ff.write('%s %s %d %s %s ' %(self.name, self.mpass, self.age, sel‬‬
‫))‪f.email, os.linesep‬‬
‫)(‪ff.close‬‬
‫‪except Exception, e:‬‬
‫‪print "Error",e‬‬
‫)'‪Chouaib=Info('chouaib', '00000', 22, '[email protected]‬‬
‫)'‪Chouaib.save_info('/home/chouaib/info_user‬‬

‫الكلس مجهزة بميثود __‪ __init‬و هذه الخيرة تحتوي على أربعة بارامترات و هي السم و رقم السري و‬
‫العمر و اليميل‬
‫بعد تهيئة الميثود __‪ __init‬تقوم بربط الصفة ‪ self‬مع الصفاة المدرجة في البارمتر‬
‫و كل هذا يدخل تحت وظيفة __‪__init‬التي تهيئ الصفاة )‪ (attributs‬و تقوم بعملية ربط هذه الصفات مع‬
‫الداة ‪self‬‬
‫فــ ‪ self‬أو ‪ this‬تعملن كأداة ربط بين الصفات )‪ (attributs‬و الوظائف التي تعتمد عليها داخل الكلس‬
‫نفسها من خلل الميثود‬
‫‪ff.write('%s %s %d %s %s ' %(self.name, self.mpass, self.age, self.email, o‬‬
‫))‪s.linesep‬‬

‫كما في المثال قمنا باستعمال الـ ‪ attributs‬الخاصة بالـميثود__‪__init‬في ميثود اخرى هي ‪save_info‬‬
‫هذا داخل الكلس نفسها و مثال آخر عن الكائنات المشتقة كما في الكائن الجديد الذي اشتققناه‬
‫)'‪Chouaib=Info('chouaib', '00000', 22, '[email protected]‬‬

‫ففي هذه الحالة تقوم ‪ self‬بربط الصفاة المدخلة الجديدة أو بتعبير آخر البيانات المدخلة‬
‫مع صفاة الكلس الصلية و ‪Info‬‬
‫و كل هذا العمل يدخل تحت عمل الميثود__‪ __init‬التي سنعرف اسمها الحقيقي بعد قليل‬
‫الكلس ‪ Info‬تحتوي على ميثود ثانية اسمها ‪ save_info‬تقوم هذه الميثود بحفظ البيانات المدخلة في ملف‬
‫خاص و هذا طبعا بالعتماد على الـ ‪ attributs‬في الميثود __‪__init‬‬
‫و هنا نلحظ ان الميثود ‪ save_info‬تحتوي هي الخرى على صفة ‪attribut‬‬
‫فل يمنع ان تضم الميثود صفات خاصة بها و في نفس الوقت تستعمل صفات خصاة بميثود اخرى و لكن قبل‬
‫استعمال الصفة يجب دائما تهيئتها و ربطها بالدات ‪self‬‬
‫‪def save_info(self, nfile):‬‬
‫‪self.nfile = nfile‬‬
‫اذا اخي القارئ بوصولك هنا تكون قد تكونت لديك صورة واضحة حول البرمجة الموجهة و سأحاول في‬
‫الفقرة التالية اعطاء التعريف المعتمد عليه و تثبيت المفاهيم التي اكتسبتها من الدرس السابق‬
‫**البرمجة الكائنية الموجهة هي نمط او اسلب جديد او طريقة برمجية لها قواعد خا ّ‬
‫صة بها لكتابة الكواد و‬
‫سنلحظ عند التعمق ان هذا السلوب صارم جدّا من ناحية اتباع قواعده‬
‫**صرامة قواعد ‪ OOP‬تساعد المبرمج على تنظيم مشاريعه مهما كانت كبيرة و معقدة فهي كقوانين المرور‬
‫فهذه الخيرة تنظم طريقة السير و تمنع الحوادث حتى داخل المدن المعقدة كذلك قوانين –ووب اذا‬
‫احترمها المبرمج سيتمكن من اكمال مشروعه و بطريقة منظمة و آمنة‬

‫**فكرة ‪OOP‬‬
‫الفكرة الساسية لـ ‪ OOP‬تكمن في جمع مجموعة من البيانات و المعطيات ‪attributs‬‬
‫و مجموعة من التعليمات او اللوغاريتميات التي تعالج هذه البيانات ‪methods‬‬
‫و كل هذا يكون مضغوط ‪ encapsul‬او محتوى داخل كائن واحد ‪object‬‬
‫و نستخلص من ما سبق المعادلة التالية‬

‫‪Object=attributes+Methodes‬‬
‫هذا الجمع لهذه البيانات و التعليمات داخل كائن واحد يتيح للمبرمج حرية كبيرة في استعمال مايشاء من‬
‫المعلومات او مجموعة المعلومات ‪ data‬و بصورة منظمة اكثر‬
‫مثل لدينا مشروع لتسير مستودع بضائع كبير‬
‫يقوم المبرمج بجمع البيانات و الوظائف الخاصة بالبضائع التي توجد داخل المستودع في كائن ‪ object‬واحد‬
‫و يقوم بجمع البيانات و الوظائف الخاصة بالبضائع التي خرجت من المستودع ‪-‬بيعت‪ -‬في اوبجيكت آخر‬
‫و البضائع التي لم تسدد قيمتها و التي اتلفت في اوبجيكت آخر وهكذا ‪.....‬‬
‫يكون المشروع متكون من العديد من الكائنات –‪ object‬فيقوم بتوجيه هذه الكائنات لكي يحصل على النتائج‬
‫المرجوة من المشروع ولهذا نسمي هذا النمط بـ البرمجة الكائنية الموجهة ‪Object-oriented‬‬
‫‪programming‬‬
‫**__‪init__ Constructeur‬‬
‫وقلنا ان مهمتها هي تهيئة الـ ‪ attributs‬الخاصة‬ ‫قمنا في الدرس السابق بتعريف الميثود __‪__init‬‬
‫بالكلس و هذا التعريف صحيح ل غبار عليه و لكن السم الصحيح لهذه الميثود هو ‪ Constructeur‬و‬
‫بـ بناء الكلس و السم يدل على مهمت ‪ Constructeur‬إذ انه‬ ‫باللغة العربية تدعى الميثود __‪__init‬‬
‫يقوم بتهيئة الكلس و بناء روابط بين الـ ‪ attributs‬و البيانات التي ستعوض بها‬
‫**‪method‬‬
‫باختصار الميثود هي كل دالة كتبت داخل الكلس او هي كل دالة تابعة للكائن فكل دالة كتبت داخل كلس‬
‫تسمى ميثود حتى ‪ Constructeur‬يسمى ميثود‬
‫هذه هي التعريف و المفاهيم الساسية لكل ما رأيناه سابقا طبعا ل تنتهي ‪ OOP‬هنا فمازال هناك الوراثة‬
‫‪ inheritance‬و تعدد الشكال ‪Polyphormisme‬‬
‫**الوراثة ‪ inheritance‬و تعدد الشكال ‪Polyphormisme‬‬
‫هما ثاني و ثالث مفاهيم الـ ‪ OOP‬الساسية فركائز البرمجة الكائنية الموجهة هي‬
‫التغليف ‪ Encapsulation‬و رأينا هذا سابقا كيف ان الصنف الواحد او الكلس يغلف داخلة مجموعة مختلفة‬
‫من الصفاة و الوظائف كلها تحت نفس المسمى و تحت نفس السم‬
‫الوراثة ‪ inheritance‬و سنرى تعريفها الن‬
‫تعدد الشكال ‪ Polyphormisme‬سنعرفه بعد قليل ايضا‬
‫و تجدر الشارة ان الوراثة و تعدد الشكال مرتبطان ببعضهما البعض و سنفهم هذا بعد قليل‬
‫ماهي الوراثة ‪ :‬في حياتنا اليومية نفسر الوراثة على انها اكتساب لشياء جديدة من طرف عنصر آخر فنقول‬
‫مثل ان الولد ورث صفاة ابيه فهذا يعني ان الولد قد اكتسب صفاة من طرف ابيه و صار بينهما شيئ مشترك و‬
‫ل يعني ان البن صورة طبق الصل عن ابيه و انما ورث بعض الصفاة فقط‬
‫نفس الشيئ بالنسبة لـ ‪OOP‬‬
‫نفرض مثل انه لدينا كلس اسمها ‪ Etud‬هذه الكلس مخصصة لصنف الطلب‬
‫و نريد ان ننشئ كلس اخرى اسمها ‪ Teach‬مخصصة لصنف الساتذة‬
‫للطلب صفاة معينة كالسم و اللقب و القسم و النقطة ‪..........‬‬
‫و للستاذ ايضا صفاة معينة‬
‫في هذه الحالة نستطيع ان ننشئ لكل صنف كلس مخصصة و لكن منحتنا ‪OOP‬‬
‫مفهوم جديد اسمه الوارثة يمكننا من استعمال عدة خصائص و صفاة لصناف مختلفة‬
‫نعود لمثالنا‬
‫بدل ان ننشئ كلس للستاذ و نعيد ادراج كل الصفاة الخاصة به نستفيد من تقنية الوراثة و ننشئ هذه الكلس و‬
‫لكن ل ندرج كل الصفاة فيها بل ندرج الصفاة التي ل تحتويها كلس الطلب فقط لنه بين الستاذ و الطلب‬
‫توجد العديد من الصفاة المشتركة كالسم و اللقب و القسم سنستغل هذه الصفاة المشتركة و في الكلس الخاصة‬
‫بالستاذ ندرج الصفاة التي ينفرد بها صنفه فقط ثم نقوم بإنشاء علقة وراثة بين كلس الطلب و كلس الستاذ‬
‫فنقول ان كلس الستاذ ترث خصائص كلس الطلب و هنا تدعى كلس الستاذ بالولد و كلس الطلب بالم‬
‫و البعض يسمي الكلس الم بـ ‪ Base class‬و الكلس الولد بـ ‪Subclass‬‬
‫الصيغة الكتابية للوراثة هي‬
‫‪class Sub_class_Name (Base_class1, Base_class2....):‬‬
‫‪class_suit‬‬
‫‪...........‬‬
‫‪..........‬‬

‫مثال‬
‫‪class My_Base_class():‬‬
‫‪def my_base_class_method(self):‬‬
‫'‪print 'Base calss method‬‬
‫‪class My_subclass(My_Base_class):‬‬
‫‪def my_subclass_method(self):‬‬
‫'‪print 'subclass method‬‬

‫لدينا في المثال الكلس الثانية ترث الكلس الم ‪My_Base_class‬‬


‫و هذا يعني انها تستطيع استعمال الميثود الخاصة بها‬
‫نتابع المثال‬
‫)(‪ins=My_subclass‬‬
‫)(‪ins.my_subclass_method‬‬
‫)(‪ins.my_base_class_method‬‬
‫فهنا الكلس البنت او ‪ subclass‬تستطيع ان تستعمل كل خصائصها و كل خصائص الكلس الم ‪base‬‬
‫‪ class‬لنها ترث منها و لكن العكس غير صحيح‬
‫حاول مثل ان تكتب السطر التالي‬
‫)(‪s=My_Base_class‬‬
‫)(‪s.my_subclass_method‬‬
‫ستفشل في تنفيد الكود لوجود خطئ لن الوارث هو فقط من يستطيع استعمال خصائص من ورث منه اما‬
‫العكس فل يصح‬
Multi inheritence ‫الوراثة الجماعية‬
‫تستطيع اي كلس ان ترث الخصائص عن عدة اصناف اخرى و هذا يسمى بالوراثة الجماعية‬
‫مثال‬
class My_Base_class():
def my_base_class_method(self):
print 'Base calss method'
class My_subclass(My_Base_class):
def my_subclass_method(self):
print 'subclass method'
class My_third_class(My_Base_class, My_subclass):
def My_third_class_method(self):
print 'third class method'
ins=My_third_class()
ins.my_base_class_method()
ins.my_subclass_method()
ins.My_third_class_method()
‫ ورثت من كل الكلس الموجودة و هذا يخولها بالستفادة من‬My_third_class ‫كما نلحظ الكلس الخيرة‬
‫كل خاصئصها كلها‬
Polyphormisme
‫ خطوة واعدة في مجال البرمجة و نقلة نوعية مما يعد بالكثير في المستقبل‬Polyphormisme ‫يعتبر‬
B ‫ ورثت من كلس‬A ‫قلنا سابقا ان الوراثة و تعدد الشكال مرتبطان ببعضهما البعض نفرض ان كلس‬
‫ امكانية استعمال اسماء متشابهة للميثود‬Polyphormisme ‫طبعا لكل كلس عدة ميثود خاصة بها يمنحنا‬
‫ تحتوي على ميثود بنفس السم و هذا بعني ان الكلس‬subclass ‫ و‬Base class ‫فتكون الكلس‬
‫ ميثود بنفس السم‬2 ‫ تحتوى على‬subclass

class My_class_A():
def class_a_method(self):
print ' classA method'

class My_class_B(My_class_A):
def class_b_method(self):
print 'classB method'

class My_class_C(My_class_A, My_class_B):


def class_a_method(self):
print 'classC method'
def class_b_method(self):
print 'classC 2 method'

ins=My_class_A()
s=My_class_B()
y=My_class_C()

ins.class_a_method()
s.class_b_method()
y.class_a_method()
y.class_b_method()
‫لدينا في المثال ‪ 3‬كلس‬
‫الكلس الخيرة ‪ My_class_C‬ترث من كلتى الكلس الخر و تحتوى بداخلها على ‪ 2‬ميثود بنفس اسم‬
‫ميثود الكلس التي ورثت منهم‬
‫و مع التطابق في اسماء الميثود لم يفشل تنفيد الكود و استطاع المفسر ان يفرق بين الميثود‬
‫و هذا هو مفهوم تعدد الشكال او ‪Poly‬‬

‫هذا ما ينبغي علينا معرقته حول ‪ Poly‬حتى الن كالعادة سنتوق بالشرح عند كل جديد في دروسنا القادمة فمن‬
‫لم يفهم الـ ‪ OOp‬جيدا فل يخف لن كل دروسنا القادمة بإذن ال مبنية على ‪OOP‬‬

‫هذات كل شيئ في هذا الدرس ارجوا ان اكون قد وفقت في شرح ‪OOP‬‬


‫الدرس القادم سيكون كالعادة مثال او مثالين شاملين نطبق فيهما كل ما رأيناه في هذا الدرس و الدرس الماضي‬

‫تم بحمد ال‬


‫تمرين شامل ]‪:[Libirary‬‬
‫الخوة الفاضل اتيتكم اليوم بمثال شامل بإذن ال هو عبارة عن مشروعه للمكتبة ‪Library‬‬
‫يعطي المستعمل الكثير من الخيارات للتعامل مع البيانات المدخلة‬
‫المشروع مكون من اربع كلس ‪ classes 4‬و هي‬
‫الكلس الم هي ‪ Libarary‬و ترث منها الكلس ‪ Book‬و الكلس ‪Software‬‬
‫الكلس الرابعة تدعى ‪ Root‬و ترث من ‪ Book‬و ‪Software‬‬

‫عمل البرنامج‬
‫المشروع عبارة عن برنامج لمكتبة يقوم المستخدم بحجز الكتب او السيديهات الموجودة في المكتبة بواسطة‬
‫البرنامج فالمستعمل يدخل البيانات الكاملة للكتاب او السيدي ثم يقوم البرنامج بحفظها كما يمكنه الرنامج من‬
‫البحث عن البيانات المحفوظة في البرنامج و حذفها‬
‫البرنامج يحتوي ايضا على ميزة مدير النظام اذ ان مدير البنامج ‪ root‬يستطيع الدخول بواسطة كلمة مرور‬
‫للبرنامج و يحذف كل البيانات المدخلة كما يستطيع ان ينسخ قاعدة البيانات في ملف احتياطي‬
‫في هذا البرنامج استعملت مجموعة من الملفات تلعب دور قاعدة البيانات و عندما اقول قاعدة البيانات فأنا اعني‬
‫الملف الذي تحفظ في المعلومات‬
‫شرح كود البرنامج‬
‫سنشرح الكود المصدري للبرنامج و ذلك بشرحنا لكل كلس على حدة‬
‫‪Library class -1‬‬
‫هي الكلس الم للبرنامج و يرث منها كل الكلسات الخرى تحتوي هذه الكلس على ‪ 3‬ميثود بالضافة لـ‬
‫‪constructor‬‬
‫فاجمال الميثود التي تحتويها هذه الكلس ‪ 4‬ميثود‬
‫** الكود الكامل للكلس ‪Library‬‬

‫‪class Library:‬‬
‫'‪'Library class‬‬
‫‪def __init__(self):‬‬
‫'‪'Library class constructor‬‬
‫‪LibCode=Title=Price='' #Initializes the attributes of Library class‬‬
‫''=‪FileName‬‬

‫‪def lib_method(self):‬‬
‫'‪'Enter common details for books and software‬‬
‫)'‪LibCode=raw_input('Enter the library code :‬‬
‫)'‪Title=raw_input('Enter the title :‬‬
‫)'‪Price=raw_input('Enter the price :‬‬
‫‪return LibCode, Title, Price‬‬

‫‪def empty_file_method(self, FileName):‬‬


‫'‪'delete all books and software records‬‬
‫)'‪File=open(FileName, 'a‬‬
‫‪File.seek(0,2) #Goes to the end of file‬‬
‫)(‪FileLen=File.tell‬‬ ‫‪#stor the length of file‬‬
if FileLen== 0L:
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************* FILE ALREADY EMPTY ******************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

else:
File.truncate(0) #Empty the file, if the length of file is not zer
o

if FileName=='BookDetails': #Checks if the filename is BookDetails


print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '***********ALL BOOK RECORDS DELETED **************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

else:
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '********** ALL SOFTWARE RECORDS DELETED ***********'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

File.close()

def clear_screen_method(self):
'Clear Screen method =>> Clear the screen '
KeyInput=0
while not KeyInput:
print
ch=raw_input('Press Entry to continue ... ')
if ch!='':
print
print
print 'Wrong Key pressed!! pleas press Entry key'
else:
ClearScreen=os.system('clear')
KeyInput=1
‫بسم ال‬

‫في الـ ‪ constructor‬قمنا بتعريف ‪ 4‬صفات و هي‬


‫‪LibCode Title Price FileName‬‬
‫هذه الصفات سنستعملها فيما بعد لحجز بيانات المستعمل و هذه الصفاة هي المشتركة بين الكتب ‪ Book‬و‬
‫السيدسهات او البرامج ‪ Software‬و لهذا قمنا بوضعها في الكلس‬
‫الم و فيما بعد كل كلس نضيف فيها الصفات التي تنفرد بها لوحدها‬
‫‪ ()lib_method‬تقوم بأخذ البينات من المستخدم ثم تجز هذه البانات في الصفات الخاصة بالكلس‬
‫‪ ()empty_file_method‬هذه الميثود تقوم بحذف كل البيانات المجوزة في الملف و هي ميثود المدري فقط‬
‫من يستطيع استعمالها كما سنرى‬
‫عملها بسيط جدا تقوم بفتح الملف ثم نذهب لخر الملف بواسطة ‪seek‬‬
‫‪ ()FileLen=File.tell‬هنا نقوم بحجز طول السلسلة الحرفية المحجوزة داخل الملف و هذا بواسطة الدالة‬
‫‪tell‬‬
‫اذا كانت ‪ FileLen‬تساوي الصفر فهذا يعني ان الملف فارغ اصل و اذا كانت تختلف عن الصفر نقوم بافراغ‬
‫الملف و الحظوا جيدا افراغ و ليس حذف‬
‫و الفراغ يتم بواسطة الدالة ‪ truncate‬الصفر بين القوسين معناه افراغ السلسلة الحرفية التي يحتويها الملف‬
‫حتى تساوي الصفر‬
‫اخواتني عندما اقول هنا دالة اعني بها دالة محجوزة اي تابعة للبايثون فـ ‪ seek‬و ‪ tell‬و ‪ truncate‬هي‬
‫دوال محجوزة للغة‬
‫‪ :()clear_screen_method‬تقوم هذه الميثود بافراغ الشاشة ‪ clear‬نفس المر في سطر الوامر‬
‫الخاص بالينيكس او الويندوز و استعملنا في هذه الميثود مكتبة ‪ os.system‬و تتيح لنا هذه المكتبة ان نستعمل‬
‫اوامر خاصة بالنظام و في هذا البرنامج استعملنا المر ‪clear‬‬
‫فعند ضغط المستعمل على ‪ entry‬تقوم الميثود بافراغ الشاشة اي حذف كل الكاتابات الظاهرة على شاشة‬
‫الجهاز و هذا طبعا لراحة مستعمل البرنامج و لكي يجد سهولة في التعامل معه‬
‫‪Book class -2‬‬
‫هذه الكلس تستكلف بالكتب فقط فكما قلنا ان البرنامج يفصل بين الكتب و البرامج او السيديهات و نستطيع ان‬
‫نجمعهما في كلس واحدة و لكن سيصبح البرنامج مقيد و سنخسر الكثير من الميزات و هذه هي فائدة الـ‬
‫‪ OOP‬اجمع كل البيانات المتشابهة في كلس واحدة ثم اعمل علقة بين مختلف الكلس التي يحتويها البرنامج‬
‫نحن هنا قمنا بجمع كل البيانات و الوظائف الخاصة بفئة الكتب في كلس واحدة اسمها ‪ Book‬هذه الكلس‬
‫ترث من ‪Library‬‬
‫الكود الكامل للكلس ‪Book‬‬

‫‪class Books(Library):‬‬
‫'‪'books class‬‬
‫‪def __init__(self):‬‬
‫'‪'class books constructor‬‬
‫‪Author=Publisher=PageCount=ISBN='' # Initialise attributes of the books‬‬

‫‪def bks_method(self):‬‬ ‫‪# Takes input for book details‬‬


‫'‪'Entry books details‬‬
‫‪BKFile=open('BookDetails', 'a') # Creat and open a file in append mode‬‬
libM=self.lib_method() # Calls the method of the base class, which take
s input for three attributes
# LibCode, Title and Price
BKFile.write(libM[0] + ',')
BKFile.write(libM[1] + ',')
Author=raw_input('Enter the name of author :')
BKFile.write(Author + ',')
Publisher=raw_input('Enter the name of publisher :')
BKFile.write(Publisher + ',')
ISBN=raw_input('Enter the ISBN :')
BKFile.write(ISBN + ',')
PageCount=raw_input('Enter the page count :')
BKFile.write(PageCount + ',')
BKFile.write(libM[2]+ '\n')
BKFile.close()
print '''
you have entered the following details for a book :
====================================================
Library code : %s
Title : %s
Author : %s
Publisher : %s
ISBN : %s
Page count : %s
Price : %s''' %(libM[0], libM[1], Author, Publisher, ISBN, PageCount,
libM[2])

def book_search(self):
'sreach for book record '
BKDet=open('BookDetails', 'r')
BKDet.seek(0,2)
BKFileLen=BKDet.tell()
if BKFileLen ==0L :
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************** NO RECORDS AVAILABLE ***************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

BKDet.close()
else:
BKDet=open('BookDetails', 'r')
lines=BKDet.readlines()
size=len(lines)
name=raw_input('enter name of book ')
i=0
reco=""
while i<size:
line=lines[i]
fd=line.find(name)
if fd>0:
reco=line.split(',')
print '''
View details for a book :
====================================================
Library code : %s
Title : %s
Author : %s
Publisher : %s
ISBN : %s
Page count : %s
Price : %s''' %(reco[0], reco[1], reco[2], reco[3], rec
o[4], reco[5], reco[6])
i+=1

else:
print 'no record avalibale '

def book_delete(self):
'delete entry from book library'
BKDet=open('BookDetails', 'r')
lines=BKDet.readlines()
BKDet.close()
name=raw_input('Enter name of book')
i=0
size=len(lines) #get size lines length
while i < size :
fd=lines[i].find(name) # search in line
if fd>0:
del lines[i] #delete the line from file
break
else:
if i == size-1 :
print ' no record availibal '
i+=1
BKDet=open('BookDetails' ,'w')
BKDet.writelines(lines)
BKDet.close()

Constructor

‫يحتوي بّناء هذه الكلس على كل الصفات التي تنفرد بها هذه الكلس و هي‬
Author Publisher PageCount ISBN
Library ‫ صفات اخرى و هي التي ادرجناها في‬Book ‫و هذه الصفات خاصة بالكتاب فقط و للكلس‬
LibCode Title Price FileName : ‫ و نعيد ذكرها‬class

‫ فبدل ان ندرج لكل كلس الصفات الكلية لها نختصر على‬OOP ‫و هنا نقف مرة اخرى مع فائد استعمال الـ‬
‫انفسنا الجهد و الوقت و نقوم بادراج الصفات المشتركة بين مجموعة الكلس داخل الكلس الم و في كل‬
‫كلس ندرج الصفاة الخاصة بها هي فقط‬
‫ صفة خاصة بالكاتب فقط لن السيدي ل يحتوي على صفحات‬PageCount ‫فهنا مثل الصفة‬
‫ للكتاب ثمن كما ان للسيدي ثمن فبدل ان ندرج هذه الصفة في كلس‬Price ‫اما الصفات المشتركة فمثل‬
‫ و بفضل الوراثة تستطيع كل كلس‬Library ‫ نقوم بادراجها في الكلس الم‬Software ‫ و كلس‬Book
‫استغلل او استعمل هذه الصفة‬
‫اظن ان الفكرة وصلت الن‬
‫‪:()bks_method‬‬
‫تقوم هذه الميثود باخذ البيانات من المستعمل ثم تحفظها داخل الملف ‪ BookDetails‬وهو الملف الخاص‬
‫بحفظ بيانات الكتب اي انه يلعب دور قاعدة البيانات الخاصة بالكتب‬
‫و نلحظ اننا لم نكتب المسار الكامل عند فتح او حفظ الملف و لهذا سيقوم المفسر بحفظه داخل ملف المشروع‬
‫الذي انشأناه لحظو معي السطرين التاليين‬
‫‪libM=self.lib_method() # Calls the method of the base class, which takes input‬‬
‫‪for three attributes‬‬
‫‪# LibCode, Title and Price‬‬
‫)'‪BKFile.write(libM[0] + ',‬‬
‫)'‪BKFile.write(libM[1] + ',‬‬
‫هنا قمنا بانشاء مشتق للميثود ‪ lib_method‬الخاصة بالكلس الم لكي نحفظ في الملف البيانات المشتركة بين‬
‫كل كلس و هي ‪ LibCode‬و ‪ Title‬و ‪Price‬‬
‫بعد ذلك نقوم بحجز البيانات الخاصة بالكتاب فقط‬
‫‪()book_search‬‬
‫تقوم هذه الميثود بعملية البحث داخل الملف عن كتاب معين بقوم المستخدم بادخال اسم هذا الكتاب‬
‫اول شيئ عادي جدا نقوم بفتح الملف نقيس طول الملف اذا كان الطول مساوي للصفر نشير للمستخدم ان‬
‫القاعدة فارغة المحتوى في حالة العكس‬
‫‪else:‬‬
‫)'‪BKDet=open('BookDetails', 'r‬‬
‫)(‪lines=BKDet.readlines‬‬
‫)‪size=len(lines‬‬
‫)' ‪name=raw_input('enter name of book‬‬
‫‪i=0‬‬
‫""=‪reco‬‬
‫‪while i<size:‬‬
‫]‪line=lines[i‬‬
‫)‪fd=line.find(name‬‬
‫‪if fd>0:‬‬
‫)'‪reco=line.split(',‬‬
‫نقوم بفتح الملف و يقوم المتغير ‪ lines‬بحجز كل السطور التي يحتويها الملف و يجب ان اذكركم هنا ان‬
‫البرنامج يقوم بحجز المعلومات كل في سطر على حدى اي ان كل المعلومات الخاصة بالكتاب الواحد تحجز‬
‫في سطر واحد و هكذا ‪....‬‬
‫بعد ذلك ننشئ حلقة تقوم بالمرور على كل سطور الملف فكل مرة يقوم المتغير ‪ line‬بحجز سطر واحد من‬
‫‪ lines‬و في نفس الوقت نبحث عن السم المدخل في السطر‬
‫ان وجد السم و هذا معناه ان المتغير ‪ fd‬سيكون اكبر من الصفر لننا رأينا في درس السلسل الحرفية ان‬
‫الدالة ‪ find‬تعطينا موضع بداية الكلمة المبحوث عنها‬
‫عند وجود السم نقسم ‪ line‬الى عدة اقسام بواسطة الدالة ‪- split‬درسناها هي الخرى‪-‬‬
‫ثم نقوم بنسخ بيانات الكتاب على الشاشة‬
‫)'‪reco=line.split(',‬‬
‫''' ‪print‬‬
‫‪View details for a book :‬‬
‫====================================================‬
‫‪Library code : %s‬‬
‫‪Title : %s‬‬
‫‪Author : %s‬‬
‫‪Publisher : %s‬‬
‫‪ISBN :‬‬ ‫‪%s‬‬
‫‪Page count : %s‬‬
‫‪Price : %s''' %(reco[0], reco[1], reco[2], reco[3], rec‬‬
‫)]‪o[4], reco[5], reco[6‬‬
‫‪i+=1‬‬

‫‪:()book_delete‬‬
‫تقوم هذه الميثود بحذف بيانات كتاب معين يقوم المستخدم بادخال اسمه تعمل هذه الميثود كالميثود التي رأيناها‬
‫الن ‪book_search‬‬
‫نقوم اول بفتح الملف ثم يقوم المتغير ‪ lines‬بحجز كل سطور الملف فتبحث عن الكتاب ان كان موجود داخل‬
‫‪ lines‬ان وجد السم نقوم بحذف السطر كامل و ذلك بواسط ‪del‬‬
‫‪if fd>0:‬‬
‫]‪del lines[i‬‬ ‫‪#delete the line from file‬‬
‫‪break‬‬

‫‪ del‬محجوزة و مهمتها حذف سلسلة من ملف‬


‫طيب بعد حذف السطر نعيد فتح الملف مرة اخرى و ننسخ داخل كل محتوى ‪lines‬‬
‫يعني ببساطة قمنا بفتح الملف و حجزت ‪ lines‬كل السطور التي يحتويها الملف ثم قمنا بحذف السطر الذي‬
‫يحتوي على كل بيانات الملف ثم فتحنا الملف مرة اخرى و اعدنا نسخ محتوى ‪ lines‬داخل الملف و لحظو‬
‫جيدا لقد فتحنا الملف بصيغة ‪ W‬اي ان كل محتواه السابق سيمحى‬
‫‪Software class -3‬‬
‫هذه الكلس خاصة ببيانات البرامج و اللسيديهات التي تحتويها المكتبة و هي مشابهة جدا لكلس ‪Book‬‬
‫الكود الكامل للكلس‬

‫‪class Software(Library):‬‬
‫'‪'software class‬‬
‫‪def __init__ (self):‬‬
‫' ‪'software class‬‬
‫''=‪ProductOf=NmbCd‬‬

‫‪def softw_method(self): # takes input for software details‬‬


‫' ‪' Enter software details‬‬
‫)'‪SwFile=open('SoftwareDetails', 'a‬‬
‫)(‪libM=self.lib_method‬‬

‫)'‪SwFile.write(libM[0] + ',‬‬
‫)'‪SwFile.write(libM[1] + ',‬‬
‫)'‪ProductOf=raw_input(' Enter the name of the software vendor‬‬
‫)'‪SwFile.write(ProductOf + ',‬‬
‫)'‪NmbCd=raw_input('Enter the number of CDs :‬‬
‫)'‪SwFile.write(NmbCd + ',‬‬
‫)'‪SwFile.write(libM[2] + '\n‬‬
‫)(‪SwFile.close‬‬
print '''
you have entered the following details for a software :
=======================================================
Library code : %s
Title : %s
Vendor : %s
Number of CD : %s
Price : %s''' %(libM[0], libM[1], ProductOf, NmbCd, libM[2])

def sfw_search(self):
'sreach for software record '
SwFile=open('SoftwareDetails', 'r')
SwFile.seek(0,2)
SwFileLen=SwFile.tell()
if SwFileLen ==0L :
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************** NO RECORDS AVAILABLE ***************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

SwFile.close()
else:
SwFile=open('SoftwareDetails', 'r')
lines=SwFile.readlines()
size=len(lines)
name=raw_input('enter name of record ')
i=0
reco=""
while i<size:
line=lines[i]
fd=line.find(name)
if fd>0:
reco=line.split(',')
print '''
Library code : %s
Title : %s
Vendor : %s
Number of CD : %s
Price : %s ''' %(reco[0], reco[1], reco[2], reco[3], rec
o[4])
i+=1

else:
print 'no record avalibale '
def sfw_delete(self):
'delete entry from book library'
SwFile=open('SoftwareDetails', 'r')
lines=SwFile.readlines()
SwFile.close()
name=raw_input('Enter name of software ')
i=0
size=len(lines)
while i < size :
fd=lines[i].find(name)
if fd>0:
del lines[i]
break
else:
if i == size-1 :
print ' no record availibal '
i+=1
SwFile=open('SoftwareDetails' ,'w')
SwFile.writelines(lines)
SwFile.close()
‫الكلس ل تحتاج للشرح لنها مشابهة تماما للكلس السابق فقط نلحظ اننا ادرجنا في بناء هذه الكلس الصفات‬
‫ الولى تعني بائع البرنامج و الثانية تعني عدد السيديهات التي‬NbCd ‫ و‬ProductOf ‫الخاصة بها فقط و هي‬
‫اتت مع البرنامج‬
Root class -4
‫ او مدير البرنامج و تجمع هذه الكلس المهام التي يتمتع بها المدري عن‬root ‫هذه الكلس خاصة بمدير النظام‬
‫باقي مستعملي البرنامج و هذه المهام هي‬
-backup- ‫ انشاء نسخة احتياطية لقاعدة البيانات‬- ‫الملفات‬- ‫حذف كل محتوى قاعدة البيانات‬
‫كما ان هذه الكلس تحتوى على كلمة مرور المدير و امكانية تغيرها‬
‫الكود الكامل للكلس‬

class Root(Books, Software):

def __init__(self):
mpass=''

def pass_method(self):
rootfile=open('root_sys', 'a')
rootfile.seek(0, 2)
flen=rootfile.tell()
if flen == 0L :
print '********** PASSWORD ****************'
mpass=raw_input('pleas enter a password :')
rootfile.write(mpass)
rootfile.close()
return 1
else:
rootfile=open('root_sys', 'r')
ps=rootfile.read()
rpass=raw_input('enter the password :')
rootfile.close()
if rpass==ps:
return 1
else :
print 'Wrong password '

def change_pass(self):
rootfile=open('root_sys', 'a+')
oldpass=rootfile.readline()
tmp=raw_input('enter the old password : ')
if tmp==oldpass:
rootfile.truncate(0)
rootfile.close()
mpass=raw_input('pleas the new password :')
rootfile=open('root_sys', 'w')
rootfile.write(mpass)
rootfile.close()

else:
print 'wrong password '

def backup(self):
'creat a backup copy (file )'
print '''
creat a backup copy to :
1- Books file
2- Software file
'''
choice=raw_input('enter your choice 1 or 2 :')
if choice =='1':
file=open('BookDetails', 'r')
dst=os.getcwd()
file.close()
path=raw_input('enter the coplete path -ex-: /user/library/backup
:')
try:
path_dst=dst+"/BookDetails"
shutil.copyfile(path_dst, path)
except Exception, e:
print e
if choice == '2':
file=open('SoftwareDetails', 'r')
dst=os.getcwd()
file.close()
path=raw_input('enter the coplete path -ex-: /user/library/backup
:')
try:
path_dst=dst+"/SoftwareDetails"
shutil.copyfile(path_dst, path)
except Exception, e:
print e

()pass_method
‫تقوم هذه الميثود بالطلب من مدير النظام ادخال كلمة المرور‬
‫الفكرة بسيطة جدا‬
‫ مهة هذا الملف حجز كلمة المرور‬root_sys ‫قمنا بانشاء ملف جديد اسمه‬
‫اذا كان الملف فارغا فمعناها ان المدير لم يدخل كلمة مرور فانت مثل عندما تشغل ابرنامج لول مرة و تريد‬
‫ سيطلب منك البرنامج ادخال كلمة مرور جديدة‬root ‫ان تدخل بميزة‬

‫اما اذا كان الملف يحتوى على كلمة مرور سيطلب منك البرنامج ادخال كلمة المرور و يقارنها بالتي محوزة‬
‫داخل الملف فان تطابقا ترجع الميثود على قيمة واحد ‪ return 1‬و سنرى فائدتها بعد قليل و ان لم يتطابقا‬
‫سيخبرك البرنامج ان كلمة المرور خاطئة‬
‫‪()change_pass‬‬
‫تقوم هذه الميثود بتغير كلمة المرور مثل اذا اراد المدري ان يغير كلمة المرور نفتح الملف الخاص بكلمة‬
‫المرور نطلب من المدير ان يدخل الكلمة المرور القديمة فان تطابقت مع كلمة المرور في الملف نقوم بافراغ‬
‫الملف ثم نحجز كلمة المرور الجديدة‬
‫‪:()backup‬‬
‫تقوم هذه الميثود بانشاء بنسخ محتوى الملف الذي يحتوى على بيانات الكتب او البرامج في ملف جديد فهي‬
‫عبارة عن عملية ‪copy past‬‬
‫اول شيئ نطلب من المدير ان يختار اي ملف يريد ان ينسخه و بعد الختيار نذهب لذلك الملف و نقوم بحجز‬
‫مسار الملف كامل في المتغير ‪ dst‬و هذا بواسطة الدالة ‪ ()os.getcwd‬التي رأيناها في درس الملفات‬
‫بعد ذلك نطلب من المدير ان يدخل اسم المسار الكامل اين يريد انشاء الملف الجديد‬
‫و بواسطة الدالة ‪ coptfile‬التابعة للمكتبة ‪ shutil‬نقوم بنسخ الملف الى المسار الذي ادخله المدير‬
‫هذه هي كل الكلس التابعة للبرنامج بقي علينا الن ان ننشئ ‪ Menu‬يتعامل مع المستخدم‬
‫‪Menu‬‬
‫كود الخاص بالـ ‪Menu‬‬
‫‪def MainMenu():‬‬
‫‪# display the mani menu, takes input for choiceself‬‬
‫‪# and calls an appropriate method based on the choice‬‬
‫'''= ‪MenuItems‬‬

‫>‪<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#‬‬
‫>‪<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#‬‬
‫>‪<#><#‬‬ ‫>‪<#><#‬‬
‫>‪<#><#‬‬ ‫>‪<#><#‬‬
‫>‪<#><#‬‬ ‫‪LIBRARY PROGRAM‬‬ ‫>‪<#><#‬‬
‫>‪<#><#‬‬ ‫>‪<#><#‬‬
‫>‪<#><#‬‬ ‫>‪<#><#‬‬
‫>‪<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#‬‬
‫>‪<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#‬‬

‫* ‪* Main Menu‬‬
‫=========‬
‫‪1-‬‬ ‫‪Enter details for books‬‬
‫‪2-‬‬ ‫‪Enter details for software‬‬
‫‪3-‬‬ ‫‪View details of books‬‬
‫‪4-‬‬ ‫‪View details of software‬‬
‫‪5-‬‬ ‫‪Delete a record -book-‬‬
‫‪6-‬‬ ‫‪Delete a record -software-‬‬
‫‪7-‬‬ ‫‪:-.* Root *.-:‬‬
‫‪8-‬‬ ‫‪Quit‬‬

‫''' ‪Enter choice (1 - 8) :‬‬

‫‪done=0‬‬
‫‪while not done:‬‬
‫)‪MenuChoice=raw_input(MenuItems‬‬
‫)'‪ClearScreen=os.system('clear‬‬
print 'you entred : %s' %(MenuChoice)
if MenuChoice not in '12345678' :
print
print 'wrong choice . Enter 1, 2, 3, 4, 5, 6, 7 or 8 '
print
else:
if MenuChoice =='8':
done=1
if MenuChoice =='1':
print
print '*********** ENTER BOOK DETAILS **************'
print
bk.bks_method()
bk.clear_screen_method()

if MenuChoice == '2' :
print
print '*********** ENTER SOFTWARE DETAILS **************'
print
sw.softw_method()
sw.clear_screen_method()

if MenuChoice == '3' :
bk.book_search()
bk.clear_screen_method()

if MenuChoice == '4' :
sw.sfw_search()
sw.clear_screen_method()

if MenuChoice == '5' :
bk.book_delete()
bk.clear_screen_method()

if MenuChoice == '6' :
sw.sfw_delete()
sw.clear_screen_method()

if MenuChoice == '7' :
root.pass_method()
if root.pass_method()==1:
menu_root = '''
1- Delete all book records
2- Delete all software records
3- Creat a backup copy
4- Change your password
Enter your choice :
'''

ch=raw_input(menu_root)
if ch == '1':
bk.empty_file_method('BookDetails')
root.clear_screen_method()
if ch == '2':
sw.empty_file_method('SoftwareDetails')
root.clear_screen_method()
if ch == '3' :
root.backup()
root.clear_screen_method()
if ch == '4' :
root.change_pass()
root.clear_screen_method()

bk=Books()
sw=Software()
root=Root()
MainMenu()

‫اللئحة كما نلحظ بسيطة جدا فكلما اختار المستخدم رقما نقوم باستدعاء الميثود الخاصة للقيام بالعمل فقط اريد‬
‫ان انوه للسطر التالي‬

if MenuChoice == '7' :
root.pass_method()
if root.pass_method()==1:
menu_root = '''
1- Delete all book records
2- Delete all software records
3- Creat a backup copy
4- Change your password
Enter your choice :
'''
‫ فهذا معناه‬1 ‫ فان عادت هذه الخيرة على قيمة‬mpass_method ‫عندما يدخل مدير النظام نقوم باستدعاء‬
‫ان كلمة المرور صحيحة فنعرض له اللئحة الخاصة به‬
‫الكود الكامل للبرنامج‬
import os
import shutil
CleareScreen=os.system('clear')

class Library:
'Library class'
def __init__(self):
'Library class constructor'
LibCode=Title=Price='' #Initializes the attributes of Library class
FileName=''

def lib_method(self):
'Enter common details for books and software'
LibCode=raw_input('Enter the library code :')
Title=raw_input('Enter the title :')
Price=raw_input('Enter the price :')
return LibCode, Title, Price

def empty_file_method(self, FileName):


'delete all books and software records'
File=open(FileName, 'a')
File.seek(0,2) #Goes to the end of file
FileLen=File.tell() #stor the length of file
if FileLen== 0L:
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************* FILE ALREADY EMPTY ******************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

else:
File.truncate(0) #Empty the file, if the length of file is not zer
o

if FileName=='BookDetails': #Checks if the filename is BookDetails


print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '***********ALL BOOK RECORDS DELETED **************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

else:
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '********** ALL SOFTWARE RECORDS DELETED ***********'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

File.close()

def clear_screen_method(self):
'Clear Screen method =>> Clear the screen '
KeyInput=0
while not KeyInput:
print
ch=raw_input('Press Entry to continue ... ')
if ch!='':
print
print
print 'Wrong Key pressed!! pleas press Entry key'
else:
ClearScreen=os.system('clear')
KeyInput=1

class Books(Library):
'books class'
def __init__(self):
'class books constructor'
Author=Publisher=PageCount=ISBN='' # Initialise attributes of the books

def bks_method(self): # Takes input for book details


'Entry books details'
BKFile=open('BookDetails', 'a') # Creat and open a file in append mode

libM=self.lib_method() # Calls the method of the base class, which take


s input for three attributes
# LibCode, Title and Price
BKFile.write(libM[0] + ',')
BKFile.write(libM[1] + ',')
Author=raw_input('Enter the name of author :')
BKFile.write(Author + ',')
Publisher=raw_input('Enter the name of publisher :')
BKFile.write(Publisher + ',')
ISBN=raw_input('Enter the ISBN :')
BKFile.write(ISBN + ',')
PageCount=raw_input('Enter the page count :')
BKFile.write(PageCount + ',')
BKFile.write(libM[2]+ '\n')
BKFile.close()
print '''
you have entered the following details for a book :
====================================================
Library code : %s
Title : %s
Author : %s
Publisher : %s
ISBN : %s
Page count : %s
Price : %s''' %(libM[0], libM[1], Author, Publisher, ISBN, PageCount,
libM[2])
def book_search(self):
'sreach for book record '
BKDet=open('BookDetails', 'r')
BKDet.seek(0,2)
BKFileLen=BKDet.tell()
if BKFileLen ==0L :
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************** NO RECORDS AVAILABLE ***************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print

BKDet.close()
else:
BKDet=open('BookDetails', 'r')
lines=BKDet.readlines()
size=len(lines)
name=raw_input('enter name of book ')
i=0
reco=""
while i<size:
line=lines[i]
fd=line.find(name)
if fd>0:
reco=line.split(',')
print '''
View details for a book :
====================================================
Library code : %s
Title : %s
Author : %s
Publisher : %s
ISBN : %s
Page count : %s
Price : %s''' %(reco[0], reco[1], reco[2], reco[3], rec
o[4], reco[5], reco[6])
i+=1

else:
print 'no record avalibale '

def book_delete(self):
'delete entry from book library'
BKDet=open('BookDetails', 'r')
lines=BKDet.readlines()
BKDet.close()
name=raw_input('Enter name of book')
i=0
size=len(lines) #get size lines length
while i < size :
fd=lines[i].find(name) # search in line
if fd>0:
del lines[i] #delete the line from file
break
else:
if i == size-1 :
print ' no record availibal '
i+=1
BKDet=open('BookDetails' ,'w')
BKDet.writelines(lines)
BKDet.close()

class Software(Library):
'software class'
def __init__ (self):
'software class '
ProductOf=NmbCd=''

def softw_method(self): # takes input for software details


' Enter software details '
SwFile=open('SoftwareDetails', 'a')
libM=self.lib_method()

SwFile.write(libM[0] + ',')
SwFile.write(libM[1] + ',')
ProductOf=raw_input(' Enter the name of the software vendor')
SwFile.write(ProductOf + ',')
NmbCd=raw_input('Enter the number of CDs :')
SwFile.write(NmbCd + ',')
SwFile.write(libM[2] + '\n')
SwFile.close()

print '''
you have entered the following details for a software :
=======================================================
Library code : %s
Title : %s
Vendor : %s
Number of CD : %s
Price : %s''' %(libM[0], libM[1], ProductOf, NmbCd, libM[2])

def sfw_search(self):
'sreach for software record '
SwFile=open('SoftwareDetails', 'r')
SwFile.seek(0,2)
SwFileLen=SwFile.tell()
if SwFileLen ==0L :
print
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print '************** NO RECORDS AVAILABLE ***************'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
print
SwFile.close()
else:
SwFile=open('SoftwareDetails', 'r')
lines=SwFile.readlines()
size=len(lines)
name=raw_input('enter name of record ')
i=0
reco=""
while i<size:
line=lines[i]
fd=line.find(name)
if fd>0:
reco=line.split(',')
print '''
Library code : %s
Title : %s
Vendor : %s
Number of CD : %s
Price : %s ''' %(reco[0], reco[1], reco[2], reco[3], rec
o[4])
i+=1

else:
print 'no record avalibale '
def sfw_delete(self):
'delete entry from book library'
SwFile=open('SoftwareDetails', 'r')
lines=SwFile.readlines()
SwFile.close()
name=raw_input('Enter name of software ')
i=0
size=len(lines)
while i < size :
fd=lines[i].find(name)
if fd>0:
del lines[i]
break
else:
if i == size-1 :
print ' no record availibal '
i+=1
SwFile=open('SoftwareDetails' ,'w')
SwFile.writelines(lines)
SwFile.close()

class Root(Books, Software):

def __init__(self):
mpass=''

def pass_method(self):
rootfile=open('root_sys', 'a')
rootfile.seek(0, 2)
flen=rootfile.tell()
if flen == 0L :
print '********** NEW PASSWORD ****************'
mpass=raw_input('pleas enter a password :')
rootfile.write(mpass)
rootfile.close()
return 1
else:
rootfile=open('root_sys', 'r')
ps=rootfile.read()
rpass=raw_input('enter the password :')
rootfile.close()
if rpass==ps:
return 1
else :
print 'Wrong password '

def change_pass(self):
rootfile=open('root_sys', 'a+')
oldpass=rootfile.readline()
tmp=raw_input('enter the old password : ')
if tmp==oldpass:
rootfile.truncate(0)
rootfile.close()
mpass=raw_input('pleas the new password :')
rootfile=open('root_sys', 'w')
rootfile.write(mpass)
rootfile.close()

else:
print 'wrong password '

def backup(self):
'creat a backup copy (file )'
print '''
creat a backup copy to :
1- Books file
2- Software file
'''
choice=raw_input('enter your choice 1 or 2 :')
if choice =='1':
file=open('BookDetails', 'r')
dst=os.getcwd()
file.close()
path=raw_input('enter the coplete path -ex-: /user/library/backup
:')
try:
path_dst=dst+"/BookDetails"
shutil.copyfile(path_dst, path)
except Exception, e:
print e
if choice == '2':
file=open('SoftwareDetails', 'r')
dst=os.getcwd()
file.close()
path=raw_input('enter the coplete path -ex-: /user/library/backup
:')
try:
path_dst=dst+"/SoftwareDetails"
shutil.copyfile(path_dst, path)
except Exception, e:
print e

def MainMenu():
# display the mani menu, takes input for choiceself
# and calls an appropriate method based on the choice
MenuItems ='''

<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#>
<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#>
<#><#> <#><#>
<#><#> <#><#>
<#><#> LIBRARY PROGRAM <#><#>
<#><#> <#><#>
<#><#> <#><#>
<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#>
<#><#><#><#><#><#><#><#><#><#><#><#><#><#><#><#>

* Main Menu *
=========
1- Enter details for books
2- Enter details for software
3- View details of books
4- View details of software
5- Delete a record -book-
6- Delete a record -software-
7- :-.* Root *.-:
8- Quit

Enter choice (1 - 8) : '''

done=0
while not done:
MenuChoice=raw_input(MenuItems)
ClearScreen=os.system('clear')
print 'you entred : %s' %(MenuChoice)
if MenuChoice not in '12345678' :
print
print 'wrong choice . Enter 1, 2, 3, 4, 5, 6, 7 or 8 '
print
else:
if MenuChoice =='8':
done=1
if MenuChoice =='1':
print
print '*********** ENTER BOOK DETAILS **************'
print
bk.bks_method()
bk.clear_screen_method()
if MenuChoice == '2' :
print
print '*********** ENTER SOFTWARE DETAILS **************'
print
sw.softw_method()
sw.clear_screen_method()

if MenuChoice == '3' :
bk.book_search()
bk.clear_screen_method()

if MenuChoice == '4' :
sw.sfw_search()
sw.clear_screen_method()

if MenuChoice == '5' :
bk.book_delete()
bk.clear_screen_method()

if MenuChoice == '6' :
sw.sfw_delete()
sw.clear_screen_method()

if MenuChoice == '7' :
root.pass_method()
if root.pass_method()==1:
menu_root = '''
1- Delete all book records
2- Delete all software records
3- Creat a backup copy
4- Change your password
Enter your choice :
'''

ch=raw_input(menu_root)
if ch == '1':
bk.empty_file_method('BookDetails')
root.clear_screen_method()
if ch == '2':
sw.empty_file_method('SoftwareDetails')
root.clear_screen_method()
if ch == '3' :
root.backup()
root.clear_screen_method()
if ch == '4' :
root.change_pass()
root.clear_screen_method()

bk=Books()
sw=Software()
root=Root()
MainMenu()
‫اذن هذا هو البرنامج و هذه هي البرمجة انا اعمل اني لم اشرح البرنامج جيدا فمن له اي سؤال حول البرنامج‬
‫فل يتردد بطرحه و سأحاول الجابة عليه‬
‫شيئ آخر اطلب منك اخي القارء ان تحاول الضافة على البرنامج و لو شيئ يسير و صدقني لن تجد صعوبة‬
‫بالغة في التعديل على البرنامج لن هذه هي ميزة الـبرمجة الموجهة تستطيع ان تضيف عدة اشياء على‬
‫البرنامج دون ان تؤثر على محتواه لصلي‬
‫و في الحقيقة ان اقتبست الفكرة الساسية للبرنامج من كتاب و قمت بتطويرها و هآ أنا اطلب منك نفس الشيئ و‬
‫لن تجد صعوبة بإذن ال‬

‫تم بحمد ال‬


‫الدرس الثالث عشر ‪:‬‬
‫الخوة الفاضل السلم عليكم و رحمة ال و بركاته‬
‫درسنا اليوم يا اخوة هو آخر درس في الـ ‪ OOP‬قبل النطلق للواجهات الرسومية و يعتبر هذا الدرس تكملة‬
‫و بعض الضافات التي ربما تحتاجها في المستقبل سنرى بعض الميثود الخاصة‬
‫‪ special method‬تقدم لنا خدمات قد نحتاج لها في حال ت كثيرة‬
‫قبل ان نبدء في ال ‪ special method‬نمر بسرعة على ال ‪built-in function‬‬
‫و هي الخرى دوال خاصة تتعامل مع الكلس او ال ‪ instance‬او ‪ object‬و خاصيتها انها تبنى داخل ما‬
‫ذكرناه الن و تقدم لنا بعض المعلومات او الخصائص‬
‫و لهذا سميت ‪ built-in function‬لننا نقوم باستعمالها مع ‪ instance‬للكلس مثال فتقوم هذه الدوال‬
‫ببنيان نفسها داخل الكلس ثم تقوم بالعمل المرجو منها‬
‫سيكون الدرس عبارة عن تعريف مثال و شرح بدون اطالة كثيرة‬
‫‪()issubclass‬‬
‫هي عبارة عن ‪ built-in function‬تخبرنا هل الكلس عبراة عن ‪ sub-class‬او ل‬
‫و تكون الصيغة الكتابية كالتالي‬
‫‪(issubclass(sub, sup‬‬

‫‪class A:‬‬
‫‪pass‬‬
‫‪class B(A):‬‬
‫‪pass‬‬
‫)‪print issubclass(B,A‬‬

‫سيكون الناتج طبعا ‪True‬‬


‫‪()isinstance‬‬
‫نفس الدالة السابقة تقريبا لكن هذه الخيرة تخبرنا هل مابين القوسين ‪ instance‬او ل‬
‫مثال‬
‫‪class A:‬‬
‫‪pass‬‬
‫‪class B(A):‬‬
‫‪pass‬‬
‫)(‪a=A‬‬
‫)(‪b=B‬‬
‫)‪print isinstance(a,A‬‬
‫)‪print isinstance(b,B‬‬

‫الناتج ايضا عبارة عن ‪True True‬‬


‫‪()hasattr‬‬
‫هذه ايضا تعتبر دالة بوليين و تعود تستعمل لمعرفة الـ ‪ attribut‬بحيث تعود على ‪ True‬او ‪ False‬حسب‬
‫الحالة‬
‫مثال‬
‫‪class A:‬‬
‫‪def __init__(self):‬‬
‫"‪self.name="chouaib‬‬

‫)(‪a=A‬‬
‫)'‪print hasattr(a, 'name‬‬

‫‪()getattr‬‬
‫تقوم هذه الدالة بطباعة قيمة ‪ attribut‬ففي نفس المثال السابق نطبق هذه الدالة و سنرى الناتج‬
‫)(‪a=A‬‬
‫)'‪print getattr(a, 'name‬‬

‫سيكون الناتج القيمة التي المسندة الـ ‪attribut name‬‬


‫‪()setattr‬‬
‫تقوم هذه الدالة كما يدل اسمها بوضع ‪ attribut‬جديد لل ‪ instance‬و تضيف لهذا الخير القيمة التي‬
‫سيحجزها و تكون صيغتها كالتالي‬
‫‪(setattr(instance, new_attr, value_attr‬‬
‫مثال‬
‫‪class A:‬‬
‫‪def __init__(self):‬‬
‫"‪self.name="chouaib‬‬

‫)(‪a=A‬‬
‫)'‪setattr(a, 'age', '22‬‬
‫و عند استعمال ‪getattr‬‬
‫)'‪print getattr(a, 'age‬‬
‫سيكون الناتج ‪22‬‬
‫‪()delattr‬‬
‫تقوم هذه الدالة بحذف ‪ attribut‬معين‬
‫‪class A:‬‬
‫‪def __init__(self):‬‬
‫"‪self.name="chouaib‬‬

‫)(‪a=A‬‬
‫)'‪setattr(a, 'age', '22‬‬
‫)'‪print getattr(a, 'age‬‬
‫)'‪delattr(a, 'age‬‬
‫)‪print dir(a‬‬

‫هذه هي اهم الـ ‪ built-in function‬مازالت اخرى لم نراها اليوم لن المجال ل سيمح بهذا‬
‫‪customising class‬‬
‫طيب الن رأينا فيما سبق الدوال ‪ built-in‬و رأينا كيفية عملها مذا لو اردنا ان نستعملها داخل الكلس نفسها‬
‫مثل ‪ ()setattr‬استعملناها قبل قليل مع ‪ instance‬فهل نستطيع استعمالها داخل الكلس الصلية ؟؟‬
‫كما عودتنا هذه اللغة الرائة نستطيع فعل هذا بكل سلسة و هذا سيمنحنا فائدة كبيرة جدا‬
‫مثل انت امام مشروع او كود لحل مشكل معين و لم تحدد مسبقا مالذي ستستعمله بالضبط من التريبيت‬
‫او اذا كانت لديك عدة احتمالت او تريد ان تتيح للمستعمل برنامجك عدة خيارات في هذه الحالة تقدم لك لغة‬
‫البايثون امكانية استعمال مجموعة هائلة من ‪special method‬لتخصيص الكلس التي ستستعملها في‬
‫اكوادك حسب الحالت التي سيواجهها البرنامج‬
‫و لهذا يسمى هذا بالـ ‪ customizing class‬اي انك تخصص الكلس او تشخصها حسب حالتك‬
‫و شكل هذه الـ ‪ special method‬كالتالي‬
‫___اسم الميثود___‬
‫اي السم يتوسط الخطان‬
‫سنخصص الدرس على اهم هذه الميثود و كيفية استعمالها طبعا‬
‫__‪__str‬‬
‫عبارة عن ميثود خاصة توفرها لنا البايثون تقوم هذه الميثود بالعودة على قيمة )‪---‬سترينق(‬
‫مثال‬
‫‪class Login:‬‬
‫‪def __init__(self, name):‬‬
‫‪self.login=name[0:2]+'_'+name‬‬

‫‪def __str__(self):‬‬
‫‪return " login‬‬ ‫‪:‬‬ ‫)‪%s"%(self.login‬‬

‫‪user=raw_input('enter your name‬‬ ‫)'‪:‬‬


‫)‪login=Login(user‬‬
‫‪print login‬‬
‫كما نلحظ في المثال تقوم الميثود __‪ __init‬باستقبال الـ ‪ attribut‬ثم تكون ‪ attribut login‬من قطعتين‬
‫و الميثود الخاصة __‪ __str‬تعود على قيمة ‪login‬‬
‫و ما يثبت هذه العودة الكلس ‪ return‬على سلسلة اننا لو قمنا باستعمال ‪ print‬للكلس ستظهر لنا السلسلة‬
‫التي تعود عليها __‪ __str‬كالمثال التالي‬
‫‪class A:‬‬
‫‪def __init__(self):‬‬
‫" ‪self.name="My name‬‬
‫‪def __str__(self):‬‬
‫‪return self.name‬‬

‫)(‪print A‬‬

‫طيب نفرض انك انشأت كلس و ل تريد ان تحدد مسبقا قيم ‪ attribut‬أو أنك تريد ان تحدد القيم التي ستسند‬
‫للـ ‪ attribut‬اي انك ل تريده ان تقبل كل القيم في هذا الحالة يتوجب عليك استعمال‬
‫__‪ __setattr‬و __‪__getattr‬‬

‫مثال‬
‫في المثال التالي لدينا كلس اسمها ‪CLient‬‬
‫تحتوي هذه الكلس بالضافة للبناء __‪ __init‬على ‪ special method 3‬اخرى‬
‫للكلس صفتان و هما ‪ name‬و ‪age‬‬
‫و نظرا لهمية مشروعنا ل نريد ان يكون اسم العمليل )‪ (name‬يحتوي على ارقام حتى يكون اسم رسمي و‬
‫معتمد و ل نريد ايضا ان يكون عمر العميل اقل من ‪ 20‬سنة‬
‫و هنا وصلنا للبيت القصيد لدينا صفتان و ل نريد ان تقبل الكلس كل القيم المسندة لهذه الصفات عن طريق‬
‫‪instance‬‬
‫فنريد ان نحدد القيم و نعمل كما سمينا هذا اول الدرس ‪ customizing‬للكلس‬
‫كود المثال‬
‫‪class Client:‬‬
‫‪def __init__(self, name, age):‬‬
‫‪self.name=name‬‬
‫‪self.age=age‬‬

‫‪def __setattr__(self, att, val):‬‬


‫‪if att == "name":‬‬
‫‪if val.isalpha():‬‬
‫‪self.__dict__[ "_name" ] = val‬‬
‫‪else :‬‬
‫"‪print "Invalid name‬‬

‫‪elif att == "age":‬‬


‫‪if val >= 20:‬‬
‫‪self.__dict__[ "_age" ] = val‬‬
‫‪else :‬‬
‫" ‪print " sorry !! age must be > than 20‬‬

‫‪def __getattr__(self, att):‬‬


‫‪if att == "name":‬‬
‫‪return self._name‬‬
‫‪elif att == "age":‬‬
‫‪return self._age‬‬
‫‪def __str__(self):‬‬
‫)‪return " %s : %s " %(self._name, self._age‬‬
‫تقوم الميثود __‪ __setattr‬بإسناد قيمة للـ ‪ attribut‬خاص بـ ‪ object‬معين‬
‫الميثود تحتوي على ‪ argument 3‬ال ‪ referenc self‬و اسم الـ ‪ attribut‬و المعبر عنه بـ ‪ att‬و القيمة‬
‫التي ستسند له )‪ (val‬و بعدها نقوم بمقارنة اسم ‪attribut‬‬
‫‪:"if att == "name‬‬
‫إذا كان اسم الـ ‪ attribut‬مطابق لـ ‪ name‬و ‪:()if val.isalpha‬‬
‫إذا كانت القيمة التي ستسند لل ‪ attribut‬عبارة عن سلسلة حرفية بحثة اي ل تحتوي على ارقام او اشارات‬
‫خاصة اذا تحقق كل هذا‬
‫‪self.__dict__[ "_name" ] = val‬‬
‫سنسند هذه القيمة لل ‪attribut _name‬‬
‫و ذلك بالدخول لمفتاح هذا ال ‪ attribut‬بواسطة __‪ __dict‬و هنا ينتهي عمل __‪__setattr‬‬
‫طيب اذا لم تكن القيمة صحيحة و لم يتحقق الشرط ستظهر للمستخدم رسالة تنبؤه ان السن الذي ادخله غير‬
‫صحيح‬
‫فلو انشأنا ‪ instance‬كالتالي‬
‫)‪user=Client('chouaib', 19‬‬
‫مباشرتا سيطبع لنا االمفسر الرسالة التالية‬
‫‪sorry !! age must be > than 20‬‬
‫او اذا ادخلنا السم خاطئ‬
‫)‪user=Client('chouaib2008', 22‬‬
‫ستكون الرسالة ‪ Invalid name‬و هذه هي الفائدة المرجوة من الميثود الخاصة نحدد بها مسبقا اسنادات الـ‬
‫‪attribut‬‬
‫للتوضيح‬
‫تحتوي الميثود__‪ __dict‬على مجموعة ‪ attribut‬و القيمة التي اسندت لها‬
‫مثال‬
‫‪class A:‬‬
‫‪def __init__(self):‬‬
‫'‪self.a='aaaaaaa‬‬
‫'‪self.b='bbbbbbb‬‬

‫)(‪inst=A‬‬
‫__‪print inst.__dict‬‬
‫سيكون الناتج‬
‫}'‪{'a': 'aaaaaaa', 'b': 'bbbbbbb‬‬
‫__‪__getattr‬‬
‫‪def __getattr__(self, att):‬‬
‫‪if att == "name":‬‬
‫‪return self._name‬‬
‫‪elif att == "age":‬‬
‫‪return self._age‬‬
‫تعمل هذه الميثود عندما يطلب اوبجيكت او ‪ instance‬قيمة ‪ attribut‬معين‬
‫ففي المثال الذي لدينا نقوم اول بمقارنة اسم ال ‪ attribut‬فاذا تطابق مع المستدعي تقوم الميثود __‬
‫‪ __getattr‬بالبحث في __‪ __dict‬عن اسم ال ‪ attribut‬فان وجد سيعود هذا ال ‪ attribut‬على هذه القيمة‬
‫مثل‬
‫)‪user=Client('chouaib', 22‬‬
‫‪print user.name‬‬
‫هنا تقوم __‪ __getattr‬بالبحث عن هذا ‪ attribut‬داخل __‪ __dict‬فإن وجدته ستسند له القيمة الخاصة به‬
‫و هي في المثال " ‪"chouaib‬‬
‫طيب ان لم تجده في حالة مثل لو ادخلنا العمر خاطئ‬
‫)‪user=Client('chouaib', 2‬‬
‫‪print user.age‬‬
‫ستكون قيمته ‪None‬‬

‫هذا شرح لهم الميثود الخاصة و اكثرها استعمال نوعا ما مازال هناك عدد هائل منها يلزمنا كتاب لشرحها‬
‫كلها و لكن لمن اراد الستزادة سيجد مبتغاه في الرابط التالي‬
‫‪http://www.python.org/doc/2.3.5/ref/...te-access.html‬‬

‫تم بحمد ال‬

‫محور درسنا القادم بإذن ال سيكون حول الواجهات الرسومية ‪GUI‬‬


‫و نستعمل لهذا مكتبة ‪ QT‬لدى لكي تستطيع تتبع الدرس يجب ان تحمل ‪PyQt‬‬
‫من الموقع التالي‬

‫‪http://www.riverbankcomputing.co.uk/.../pyqt/download‬‬
‫هناك ‪ PyQt‬مخصص للويندوز و اللينيكس و الماك‬
‫لصحاب الويندوز عند التحميل نصبه على الجهاز و سينصب مباشرتا في مجلد ‪python25‬‬
‫)المجلد الذي يحوي مفسر البايثون(‬
‫لصحاب لينيكس يستطيع تحميل ‪ PyQt4‬من الموقع الذي وضعته الن‬
‫و من توزيعته قديمة كالـ ‪Debian Etch‬‬
‫ينصب ‪ qt4 designer‬و ينصب مكتبة ‪ qt‬الخاصة بالبايثون و اسمها‬
‫‪ python-qt4‬و ينصب ايضا ‪pyqt4-dev-tools‬‬
‫و كلها موجودة في مدير الحزم مسبقا و ل يحتاج لي تحميل‬
‫على كل حال لمن واجه صعوبة فليطرح سؤاله هنا‬
‫وفقكم ال‬
‫الدرس الرابع عشر ]‪:[PyQt‬‬
‫الخوة الفاضل السلم عليكم و رحمة ال و بركاته‬
‫ها نحن اليوم بعد هذه المسيرة الشيقة وصلنا للمحاور الخيرة من الدورة و قاربنا على نهايتها و بعد دراسة كل‬
‫الساسيات و بعد ان استوعبنا الـ ‪ OOP‬نكون قد جهزنا للواجهات الرسومية و بعد بحث و تفحص قررت ان‬
‫يكون درسنا حول مكتبة ‪ Qt‬و ذلك باستعمال ‪ PyQt‬لنه توجد العديد من المكاتب المخصصة للواجهات‬
‫الرسومية في لغة البايثون اشهرها‬
‫‪Thkinter, WxPython, PyQt, Gtk Pywm‬‬
‫و سنقتصر في هذه الدورة على ‪ PyQt‬فقط اسم المكتبة مكون من جزئين الجزء الول ‪ Py‬و تعني ‪Python‬‬
‫و الحزء الثاني ‪Qt‬‬
‫و لكي يكون تعريفنا لهذه المكتبة صحيح و واضح يجب ان نعرف مكتبة ‪ Qt‬اول‬
‫مكتبة ‪Qt‬‬
‫عبارة عن منصة كاملة للتطوير التطبيقات الرسومية ‪) Gui‬واجهات(‪ Graphical user interface‬و‬
‫الغير رسومية‬
‫كتبت هذه المنصة بلغة سي‪ ++‬تعمل منصة ‪ Qt‬على عدة انظمة تشغيل و هذا ما زادها شهرة و ساعد في‬
‫تربعها على العرش بسرعة و مما زادها شهرة و استعمال انها تعمل مع عدة لغاة برمجية و ذلك بواسطة‬
‫جافا‬ ‫مكاتب مخصصة كما سنستعملها نحن مع لغة البايثون و بالضافة للبايثون هناك السي و السي ‪++‬‬
‫باسكال سي شارب روبي بيرل ‪...‬و التالي بعض البرامج التي عملت بالـ ‪Qt‬‬
‫‪Adobe Photoshop Albums‬‬ ‫‪Doxygen‬‬ ‫‪Google Earth‬‬ ‫‪KDُE‬‬
‫‪Motorola A760 MythTV‬‬ ‫‪Opera‬‬ ‫‪Perforce‬‬ ‫‪Scribus‬‬ ‫‪Skype‬‬
‫‪VirtualBox‬‬ ‫‪VLC media player 12‬‬ ‫‪Pencil‬‬

‫لمن يريد المعرفة اكثر عن المنصة هذا الرابط الخاص بمنصة ‪Qt‬‬
‫‪http://fr.wikipedia.org/wiki/Qt‬‬

‫مكتبة ‪PyQt‬‬
‫كما قلنا من قبل يتكون اسم هذه المكتبة من جزئين ‪ Qt‬و ‪ Python‬و تستعمل هذه المكتبة لبرمجة الواجهات‬
‫الرسومية باستعمال لغة البايثون انطلقا من مكتبة ‪Qt‬‬
‫فهذه المكتبة عبارة عن خليط متناسق مكون من لغة البايثون و مكتبة ‪ Qt‬بحيث ان هذه المكتبة تحتوي على‬
‫‪ 300‬كلس و حوالي ‪ 6000‬دالة و كمكتبة ‪ Qt‬تماما تعمل ‪ PyQt‬على عدة منصات منها اللينيكس و‬
‫الويندوز و الماك‬

‫تتكون هذه المكاتب )‪ Qt‬و ‪ (PyQt‬من عدة وحدات )‪ (module‬و يلزمنا معرفة هذه الوحدات قبل النطلق‬
‫مع هذه المكتبة‬
‫القائمة التالية تظم الوحدات ‪ module‬التي تظمها مكتبة ‪PyQt‬‬
‫‪QtCore‬‬
‫‪QtGui‬‬
‫‪QtNetwork‬‬
‫‪QtOpenGL‬‬
‫‪QtSql‬‬
‫‪QtXml‬‬
‫‪QtSvg‬‬

‫‪QtCore‬‬
‫تستعمل هذه الوحدة للوظائف الغير واجهية أي انها ليست اجزاء خاصة بالواجهات الرسومية‬
‫كالتعامل مع الملفات و المجلدات او الساعة و التعاملت الخاصة مع الـ ‪string‬‬
‫كما ان هذه الوحدة تستكلف بالتصال بين مختلف اجزاء الواجهة ‪signal & slots‬‬
‫‪QtGui‬‬
‫تحتوي هذه الوحدة على كل العناصر الخاصة بالواجهات الرسومية كالزرار و النافذة القوائم القوائم‬
‫المتحركة ‪....‬الخ‬
‫‪QtNetwork‬‬
‫تحتوي هذه الوحدة على مجموعة الكلس الخاصة ببرمجة الشبكات و التعامل معها‬
‫‪QtOpenGL‬‬
‫تستعمل هذه الوحدة للتعامل مع البعاد الثنائية و الثلثية )‪ (2D & 3D‬و ذلك بالعتماد على مكتبة‬
‫‪ OpenGL‬فهذه الوحدة توفر لنا التحويل من الـ ‪ Qt‬الى مكتبة ‪ OpenGL‬فهي توفر لنا جسر بين المكتبتان‬
‫‪QtSql‬‬
‫توفر لنا هذه الوحدة عدة كلس للتعامل مع قواعد البيانات كربط الواجهة مع قاعدة بيانات و تبادل المعلومات‬
‫بين القاعدة و الواجهة ‪...‬‬
‫‪QtXml‬‬
‫توفر لنا هذه الوحدة ايضا عدة كلس للتعامل مع ملفات الـ ‪xml‬‬
‫‪QtSvg‬‬
‫وحدة توفر لنا كلس للظهار محتوى ملفات من نوع ‪SVG‬‬
‫‪Scalable Vector Graphics‬‬
‫و هي عبارة عن لغة لمعرفة البعاد الثنائية ‪ two-dimensional‬للرسومات المتحركة او للبرامج‬
‫الرسوميةالمنعمولة بـ ‪xml‬‬
‫كما نرى قوة هذه المكتبة فهي منصة كاملة للتطوري و تلبي كل رغبات المبرمج ‪.‬‬
‫سيكون درسنا مقسم الى جزئين‬

‫في الجزء الول سنتعلم استعمال ‪ PyQt‬و برمجة الواجهات الرسومية كتابيا‬ ‫الجزء الول ‪:‬‬
‫الجزء الثاني ‪:‬في هذا الجزء سنستعمل ‪ Qt Designer‬و هو عبارة عن مصمم واجهات كالفيجيوال تماما و‬
‫يغنينا هذا المصمم عن كتابة كود الواجهة لن هذا امر متعب جدا و قد يقول قائل لماذا ل ننطلق مع المصمم‬
‫مباشرتا و نكفي انفسنا العناء ‪.‬‬
‫لو كان هذا ممكنا لعتمدناه و لكنه غير ممكن لننا عندما نصمم واجهة رسومية و نضع عليها الزرار و‬
‫القوائم ‪ ..‬سنقوم بتحويل هذه الواجهة الى كود برمجي فلو لم ندرس الجزء الول لن تستطيع فهم كودالواجهة‬
‫و لن تعرف اين تضع كود برنامجك‬
‫ضف الى ذلك ان احسن طريقة للتعلم الواجهات الرسومية هي تعلمها كوديا )بكتابة الكواد( و تصميميا حتى ل‬
‫نقع في الفخ الذي وقع فيه اصحاب الفيجيوال ‪.‬‬
‫و بإذن ال سنرى الفرق الشاسع جدا جدا بين الواجهات بالـ ‪ Qt‬و الفيجيوال الخاص بالويندوز وسيلحظ هذا‬
‫الفرق كل من استعمل الفيجيوال لنه و ببساطة تعتبر منصة ‪ Qt‬من اقوى المكتابات الحالية في العالم‬
‫الخطوة الولى مع الواجهات‬

‫‪import sys‬‬
‫‪from PyQt4 import QtGui‬‬
‫)‪app=QtGui.QApplication(sys.argv‬‬
‫)‪button=QtGui.QPushButton("salam :)", None‬‬
‫)(‪button.show‬‬
‫))(_‪sys.exit(app.exec‬‬

‫‪import sys‬‬
‫‪from PyQt4 import QtGui‬‬

‫في السطرين الولين قمنا باستدعاء المكاتب اللزمة للبرنامج فقمنا باستدعاء مكتبة ‪sys‬‬
‫ثم من مكتبة ‪ PyQt‬قمنا باستدعاء الوحدة ‪ module QtGui‬و لقد عرفنا وحدات المكتبة فوق فاستدعيان‬
‫هذه الوحدة لننا سنتعامل مع واجهة رسومية نافذة ازرار قوائم و كلها محتواة في هذه الوحدة‬

‫)‪app=QtGui.QApplication(sys.argv‬‬

‫هذا السطر هو الهم في الكود كله و بدونه لن نستطيع التعامل مع واجهة البرنامج فكل مشروع او كود يتعامل‬
‫مع الوجهات يجب ان يحتوي على هذا السطر و معنى هذا السطر اننا قمنا بانشاء اوبجيكت ‪ object‬من‬
‫الكلس ‪QApplication‬‬
‫ف ‪ QApplication‬تعتبر هي الهيكل الكامل للبرنامج او الواجهة و ل يفهم من كلمي هذا انها هي النافذة‬
‫التي ستظهراو هي عبارة عن نافذة ل فالمعنى أكبر من هذا فالوبجيكت الذي انشئناه ‪ app‬عبارة عن الهيكل‬
‫الشامل للبرنامج و كل ما سيأتي سواء نوافذ او ازرار ‪..‬مبني عليه و حتى نفهم برمجة الواجهات اكثر نضرب‬
‫مثال‬
‫انت تريد ان تنشئ سيارة‬
‫اول تقوم بانشاء الهيكل الكامل للسيارة و بعدها تجهز هذا الهيكل فتنشئ النوافذ و العجلت و البواب و تعطي‬
‫الوانا لهذه الجزاء و كل جزء يحتوي على عمل معين فالنوافذ تنزل و تصلع و العجلت تدور و البواب تفتح‬
‫و تقفل ‪.‬‬
‫و هذه العمال ايضا مرتبطة ببعضها البعض ثفعند الضغط على الزر الفلني تصعد النافذة و عند الضغط على‬
‫المكابح تتوقف العجلت ‪...‬الخ‬
‫نفس الشيئ بالنسبة للواجهات تنشئ الوبجيكت الساسي الذي يلعب دور الهيكل ثم تقوم بتجهيز هذا الهيكل‬
‫بالزرار و و ‪....‬تعطيه لونا و عنوانا ثم تقوم بتقسيم العمال الفزر الفلني يفتح النافذة الفلنية و الزر الخر‬
‫يحفظ السطور الكتوبة في المكان الفلني ‪....‬الخ‬
‫‪sys.argv‬‬
‫عبارة عن باراميتر يحتوي على قائمة من ‪ arguments‬و التي تستغل من سطر الوامر للتعامل مع‬
‫البرنامج او المشروع و ذلك طبعا عند تشغيل البرنامج من سطر الوامر ****‪ l‬للصحاب اللينيكس مثل او‬
‫الـ ‪ Dos‬لصحاب الويندوز‬
‫فمثل نستطيع ان نحدد من سطر الوامر شكل الواجهة التي يشغل بها المشروع ****‪l‬‬
‫اول اعطي اسما للكود في العلى سمه مثل ‪first_pyqt.py‬‬
‫و من سطر الوامر شغله و ذلك بكتابة ‪ python‬ثم اسم الملف ‪python first_pyqt.py‬‬
‫الن لكي نعرف فائدة ‪ sys.arvg‬سنقوم بتحديد الـ ‪ style‬الذي ستشغل به الواجهة و ذلك بستعمال‬
‫‪ argument‬من القائمة اسمه ‪style‬‬
‫‪python fist_pyqt.py -style=Glider‬‬
‫لصحاب الويندوز يستطيع ان يختار اي اسم ثيم من الذين موجدين بالجهاز‬
‫اذا باختصار هذه هي الفائدة من –سيس ارقيمنت نستعملها خصاتا عن تشغيل سكريبت البرنامج من سطر‬
‫الوامر‬
‫)‪button=QtGui.QPushButton("salam :)", None‬‬
‫يعتبر ‪ button‬اوبجيكت انشئناه من الكلس ‪QPushButton‬‬
‫اول ‪ argument‬يعتبر التيكست ‪ text‬الذي سيظهر على الزر عند تشغيل البرنامج و نسمي الزر بالـ‬
‫‪ widget‬و نسمي ‪ widget‬كل عنصر محتوى داخل واجهة رسومية كالزرار و القوائم المتحركة ‪...‬الخ‬
‫ح التعبير نحن في هذه الحالة وضعناه ‪ None‬لن الزر هو‬
‫الـ ‪ argument‬الثاني يعبر عن تبعية الزر ان ص ّ‬
‫الـ ‪ widget‬الوحيد في الواجهة فل يملك ‪ parent‬فالزر هنا يعتلي القائمة او شجرة الـ ‪ widget‬التابعة‬
‫للواجهة‬
‫)(‪button.show‬‬

‫الويدقات بطبيعتها ل تظهر عند انشائها فتبقى مخفية و لهذا نستعمل ‪ ()show‬لظهار الزر عند تشغيل الواجهة‬

‫))(_‪sys.exit(app.exec‬‬

‫هنا ندخل في ‪ main loop‬او الحلقة الرئيسية للبرنامج‬


‫تستقبل هذه الحلقة الحداث من النظام ثم ترسل هذه الحداث الى نافذة البرنامج و‬
‫الـ ‪ widget‬التابعة لها و العكس هذا لن اصل كل الحكاية يبدئ من النظام سغس و ينفذ من النظام ايضا‬
‫فعندما تغلق انت النافذة تقوم بهذا عبر كليك من الماوس على المربع الحمر في النافذة لكن هذا المر سيترجم‬
‫في النظام بـ ‪()sys.exit‬‬
‫و هذه الخيرة تحرص على الغلق المن للنافذة و البرنامج ككل‬
‫اما ‪ app.exec‬فلتنفيذ الواجهة و الكل كما قلنا عبارة عن حلقة لتشغيل البرنامج او بعبارة اخرى الواجهة‬
‫الرسومية‬
‫طيب اذا اردنا ان تكتب الكود بطريقة اخرى اي ان تكتب مباشرتا اسم الكلس دون سبقها بـ ‪ QtGui‬ما عليك‬
‫ل استدعاء هذه الخيرة كلها بالسطر التالي‬
‫اّ‬
‫* ‪from PyQt4.QtGui import‬‬
‫فيكون الكود كالتالي‬
‫* ‪from PyQt4.QtGui import‬‬
‫‪import sys‬‬
‫)‪app=QApplication(sys.argv‬‬
‫)" )‪button=QPushButton("salam :‬‬
‫)(‪button.show‬‬
‫))(_‪sys.exit(app.exec‬‬
‫الن سنعيد كتابة نفس الكود لكن هذه سنستعمل كلس خاصة بالزر اي سنستعمل الـ ‪OOP‬‬
‫* ‪from PyQt4.QtGui import‬‬
‫‪import sys‬‬
‫‪class SalamButton(QPushButton):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QPushButton.__init__(self, parent‬‬
‫)" )‪self.setText("slam :‬‬

‫)‪app=QApplication(sys.argv‬‬
‫)(‪btn=SalamButton‬‬
‫)(‪btn.show‬‬
‫))(_‪sys.exit(app.exec‬‬

‫انشئنا كلس اسمها ‪ SalamButton‬ترث هذه الكلس من ‪ QPushButton‬و هي كما راينا كلس تابعة‬
‫للوحدة ‪ QtGui‬و لن و لهذا انشئنا ‪ 2‬ميثود __‪ __init‬لهذه الكلس‬
‫فالول خاص اي اننا استدعينا بنائين لهذه الكلس فالول خاص بالكلس التي انشئناها ‪ SalamButton‬و‬
‫الثاني خاص بالكلس التي ورثت منها و هي ‪QPushButton‬‬
‫في هذه الحالة قمنا بتحديد ال ‪ text‬الذي سيظهر في الزر بواسطة ‪ setText‬المهم بعد النتهاء من الكلس‬
‫نعمل انستنس اوبجيكت لـ ‪ QApplication‬و نشتق انستنس اخرى من كلس الزر بعد ذلك نستعمل ‪show‬‬
‫حتى يظهر الزر و في الخير الحلقة الرئيسية‬

‫في هذا المثال رأينا كيفية انشاء زر بواسطة ‪ QPushButton‬سنرى الن كيفية انشاء نافذة بواسطة‬
‫‪Qwidget‬‬
‫* ‪from PyQt4.QtGui import‬‬
‫‪import sys‬‬
‫)‪app=QApplication(sys.argv‬‬
‫)(‪window=QWidget‬‬
‫)' )‪window.setWindowTitle('salam :‬‬
‫)‪window.setGeometry(200,200,300,250‬‬
‫)(‪window.show‬‬
‫))(_‪sys.exit(app.exec‬‬
‫كما رأينا في الزر تماما اول نقوم بانشاء النافذة و ذلك باشتقاق اوبجيكت سميناه ‪ window‬من الكلس‬
‫‪Qwidget‬ثم وضعنا للنافذة عنوان بواسطة‬
‫‪setWindowTitle‬‬
‫ثم قمنا بوضع الحداثيات التي ستظهر فيها النافذة بواسطة‬
‫‪setGeometry‬‬
‫بحيث ان العددين الولين )‪ (200, 200‬يعبران عن الحداثيات التي ستظهر فيهم النافذة على الشاشة و الباقي‬
‫يعبر عن حجم النافذة و توجد طريقة اخرى لتحديد حجم النافذة فقط بواسطة‬
‫)‪resize(val,val‬‬

‫فنكتب‬
‫)‪window.resize(300,250‬‬
‫ثم نعمل لها ‪ show‬حتى تظهر عن التشغيل و اخيرا الحلقة الرئيسية‬
‫و لو اردنا ان نستعمل كلس خاصة بالنافذة لن يتغير الكثير سنتبع الخطوات التي رأيناها فوق‬
‫* ‪from PyQt4.QtGui import‬‬
‫‪import sys‬‬
‫‪class Window_salam(QWidget):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QWidget.__init__(self, parent‬‬
‫)')‪self.setWindowTitle('salam :‬‬
‫)‪self.setGeometry(200,200,300,250‬‬
‫)‪app=QApplication(sys.argv‬‬
‫)(‪window=Window_salam‬‬
‫)(‪window.show‬‬
‫))(_‪sys.exit(app.exec‬‬
‫اذا كالعادة لدينا كلس ترث من ‪ QWidget‬تحتوي على بنائين الول خاص بال ‪subclass‬‬
‫‪((Window_salam‬و الثاني خاص بالـ ‪( base class (Qwidget‬‬
‫قبل قليل رأينا كيفية انشاء زر و لكن الزر الذي استعملناه ل يقوم بأي شيئ عند الضغط عليه‬
‫سنرى الن كيف نعطي للزر عمل يقوم به‬
‫‪from PyQt4 import QtGui, QtCore‬‬
‫‪import sys‬‬
‫‪class Exit_button(QtGui.QPushButton):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QtGui.QPushButton.__init__(self, parent‬‬
‫)"‪self.setText("Exit‬‬

‫)‪app=QtGui.QApplication(sys.argv‬‬
‫)(‪btn=Exit_button‬‬
‫))')(‪app.connect(btn, QtCore.SIGNAL('clicked()'), QtCore.SLOT('quit‬‬
‫)(‪btn.show‬‬
‫))(_‪sys.exit(app.exec‬‬

‫بدايتا في الكلس ل جديد يذكر سوى اننا استدعينا ‪ QtCore‬لننا سنحتاج لهذه الوحدة لعمل التصال بين الزر‬
‫و البرنامج فلقد قلنا سابقا ان الوحدة ‪ QtGui‬خاصة بكل انواع ال ‪Widget‬‬
‫اما الوحدة ‪ QtCore‬فتخص معظم الوظائف الخرى كالتحكم في الساعة او ال ‪ Signal‬و ‪ slot‬استعمال ال‬
‫‪...string‬الخ‬
‫نعود للكود‬
‫الشيئ الجديد الذي طرء على الكود يكمن في السطر العاشر فلقد اصبح للزر عمل بفضل هذا السطر بحيث ان‬
‫الضغط على الزر سيغلق النافذة‬
‫))')(‪app.connect(btn, QtCore.SIGNAL('clicked()'), QtCore.SLOT('quit‬‬
‫تسمى العملية التي قمنا بها في هذا السطر بـ ‪signal and slot‬‬
‫و هي المعنية بتسير الحداث بين مجموعة الـ ‪ widget‬فنحن لّما نضغط على الزر سيرسل اشارة ‪signal‬‬
‫عبارة عن '‪ 'clicked‬او ضغطة و الذي سيستقبل هذه الشارة هي هو البرنامج طبعا ‪ application‬طيب‬
‫بعد استقبال الشارة سينتج عمل او حدث ‪ event‬هذا الحدث هنا في السطر عبارة عن '‪'quit‬‬
‫فعمل ‪ connect‬هو ربط التصال الخاص بمجموعة الوبجيكت و يكون هذا الربط بين الشارة ‪ signal‬و‬
‫الـ ‪slot‬‬
‫ففي مثالنا جرى التصال بين الزر و البرنامج ‪ app‬فـ ‪ connect‬تربط بين الشارة التي ستحدث عند الضغط‬
‫على الزر ‪ clicked‬و بين ‪ slot‬الذي هو عبارة في مثالنا عبارة عن ‪quit‬‬

‫مثال آخر لنفس البرنامج تقريبا و لكن بطريقة اكثر تنظيم و جمال‬
‫‪from PyQt4 import QtGui, QtCore‬‬
‫‪import sys‬‬

‫‪class Exit_button(QtGui.QWidget):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QtGui.QWidget.__init__(self, parent‬‬
‫)‪self.resize(250,150‬‬
‫‪self.setWindowTitle(" ex : SIGNAL & SLOT‬‬ ‫)"‬

‫)‪exit=QtGui.QPushButton('Exit', self‬‬
‫)‪exit.setGeometry(15,15,50, 45‬‬
‫(‪self.connect(exit, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT‬‬
‫))')(‪'quit‬‬
‫)‪app=QtGui.QApplication(sys.argv‬‬
‫)(‪btn=Exit_button‬‬
‫)(‪btn.show‬‬
‫))(_‪sys.exit(app.exec‬‬
‫اظن ان كل شيئ مفهوم و كل شيئ شرحناه سابقا فقط عندي ملحظة او مقارنة بسيطة‬
‫في المثال السابق كتبنا‬
‫))')(‪app.connect(btn, QtCore.SIGNAL('clicked()'), QtCore.SLOT('quit‬‬
‫لكن في هذا المثال كتب هذا السطر داخل الكلس لذلك استعملنا ‪---‬سيلف‬
‫')(‪self.connect(exit, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit‬‬
‫))‬
‫ابتدءنا باسم الزر )اسم المرسل( ثم الشارة التي سيرسلها ‪signal‬ثم المستقبل و الذي هو‬
‫‪QtGui.qApp‬‬
‫في المثال السابق ابتدءنا به ‪ app.connect‬لكن في هذه المرة كتب داخل القوس لننا كما قلت داخل الكلس‬
‫بعد المستقبل يأتي دور ‪slot‬‬

‫نتوقف هنا اليوم و ارجوا ان اكون قد وفقت في الشرح و سنتابع الدرس في المرة القادمة بإذن ال‬

‫تم بحمد ال‬


‫الدرس الخامس عشر‪:‬‬
‫نواصل ما ابتدءناه في الدرس الماضي و لقد حاولت في هذا الدرس جمع اكبر عدد ممكن من الـ ‪ widget‬و‬
‫طرق استعمالها و الدرس عبارة عن تعريف ثم مثال ثم شرح و الهدف من هذه الدروس هو تقريب فكرة‬
‫الواجهات الرسومية لك اخي القارء لن هذا المجال واسع جدا جدا و لن نستطيع ان نشمله كله و لكن ل عليك‬
‫بعد انتهائك من هذات المحور ستكون لديك القدرة على فهم ميكانيزمة عمل الواجهات و الهم من هذا انك‬
‫ستفهم بإذن اي كود يستعمل الواجهات و ستستطيع التعديل عليه امر مهم آخر انك لو قرءت مراجع اخرى‬
‫بالنجليزية سيكون الفهم سهل جدا لن هذا الدرس سيكون لديك بنية قاعدية تستطيع العتماد عليها‬
‫لدينا الن مثال نوضح فيه كيفية وضع اكثر من زر في ‪ widget‬واحدة و كيفية تنظيم مواضع هذه الزرار و‬
‫تسمى عملية تنظيم مواضع مجموعة الـ ‪ widget‬بـ ‪Layout managment‬‬
‫التنظيم بواسطة ‪Geometry‬‬
‫‪import sys‬‬
‫* ‪from PyQt4.QtGui import‬‬
‫* ‪from PyQt4.QtCore import‬‬
‫‪class Button_groups(QWidget):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QWidget.__init__(self, parent‬‬
‫)"‪self.setWindowTitle(" groups of buttons‬‬
‫‪self.resize(300, 150‬‬ ‫)‬
‫)‪btn_one=QPushButton("button 1", self‬‬
‫)‪btn_one.setGeometry(50,30,90,30‬‬
‫)‪btn_two=QPushButton("button 2", self‬‬
‫)‪btn_two.setGeometry(50,60,90,30‬‬
‫)‪btn_three=QPushButton("button 3", self‬‬
‫)‪btn_three.setGeometry(50,90,90,30‬‬
‫)‪exit=QPushButton("Exit",self‬‬
‫)‪exit.setGeometry(240,120,60,30‬‬
‫))')(‪self.connect(exit,SIGNAL('clicked()'),qApp,SLOT('quit‬‬

‫)‪app=QApplication(sys.argv‬‬
‫)(‪groups=Button_groups‬‬
‫)(‪groups.show‬‬
‫))(_‪sys.exit(app.exec‬‬
Geometry ‫فكما نلحظ ننشئ الزر ثم نعدل موضعه في النافذة و حجمه و ذلك بواسطة‬
QVBoxLayout ‫ و‬QHBoxLayout ‫التنظيم بواسطة‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Button_groups(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle(" groups of buttons")
self.resize(300, 150 )
btn_one=QPushButton("button 1", self)
btn_two=QPushButton("button 2", self)
btn_three=QPushButton("button 3", self)
exit=QPushButton("Exit", self)
self.connect(exit,SIGNAL('clicked()'),qApp,SLOT('quit()'))
layout=QHBoxLayout()
layout.addStretch(1)
layout.addWidget(btn_one)
layout.addWidget(btn_two)
layout.addWidget(btn_three)
layout.addWidget(exit)
self.setLayout(layout)

app=QApplication(sys.argv)
groups=Button_groups()
groups.show()
sys.exit(app.exec_())
‫ما قمنا به في هذا المثال هو اول انشاء الزرار اللزمة ثم قمنا بإنشاء صندوق ‪ Box‬افقي ‪ horizontal‬و‬
‫هذا ماتعنيه ‪ H‬يعني افقي و الـ ‪ B‬تعني صندوق ‪Box‬‬
‫بعد انشاء الصندوق و تحديد المساحة اللزمة لكل الزرار بواسطة ‪ Stretch‬قمنا باضافة الزرار الصندوق‬
‫المنشئ ولو اردنا ان يكون ترتيب الزرار عموديا نستعمل ‪ QVBoxLayout‬والـ ‪ V‬معناها ‪Vertical‬‬
‫)(‪layout=QVBoxLayout‬‬
‫)‪layout.addStretch(1‬‬
‫)‪layout.addWidget(btn_one‬‬
‫)‪layout.addWidget(btn_two‬‬
‫)‪layout.addWidget(btn_three‬‬
‫)‪layout.addWidget(exit‬‬
‫)‪self.setLayout(layout‬‬
‫طيب ولو استعملنا كلى البعدين معا ستظهر مجموعة الزرار اسفل الزاوية‬
‫مثال‬
‫)‪btn_one=QPushButton("button 1", self‬‬
‫)‪exit=QPushButton("Exit", self‬‬
‫))')(‪self.connect(exit,SIGNAL('clicked()'),qApp,SLOT('quit‬‬
‫)(‪hlayout=QHBoxLayout‬‬
‫)‪hlayout.addStretch(1‬‬
‫)‪hlayout.addWidget(btn_one‬‬
‫)‪hlayout.addWidget(exit‬‬
‫)(‪vlayout=QVBoxLayout‬‬
‫)‪vlayout.addStretch(1‬‬
‫)‪vlayout.addLayout(hlayout‬‬
‫)‪self.setLayout(vlayout‬‬

‫اول قمنا بإنشاء صندوق عمودي سميناه ‪ hlayout‬و اضفنا له الّزرين ثم انشأنا صندوق آخر عمودي سميناه‬
‫‪ vlayout‬و اضفنا الصندوق الفقي داخل الصندوق العمودي و لكن لحظوا عند الضافة لم نستعمل‬
‫‪ addWidget‬بل استعملنا ‪addLayout‬‬
‫التنظيم بواسطة ‪GridLayout‬‬
‫ايضا هذه الطريقة تعتبر اكثر تنظيم و اكثر سهولة لنها تمنحنا حرية كبيرة في تنظيم مواضع‬
‫الـ ‪ widget‬لنها تقسم المساحة الى صفوف و اعمدة مما يسهل علينا ترتيب المواضع كما انها تعتبر الطريقة‬
‫المثلى عند التعامل مع الـ ‪ Label‬و الـ ‪EditText‬‬
‫سنرى هذه الطريقة مع الزرار اول ثم نمر للمور الخرى‬
‫نبقى مع نفس المثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Button_groups(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle(" groups of buttons")
self.resize(300, 150 )
btn_one=QPushButton("button 1", self)
btn_two=QPushButton("button 2", self)
btn_three=QPushButton("button 3", self)
exit=QPushButton("Exit",self)
self.connect(exit,SIGNAL('clicked()'),qApp,SLOT('quit()'))
grid=QGridLayout()
grid.addWidget(btn_one,1,0)
grid.addWidget(btn_two,1,1)
grid.addWidget(btn_three,2,0)
grid.addWidget(exit,2,1)
self.setLayout(grid)

app=QApplication(sys.argv)
groups=Button_groups()
groups.show()
sys.exit(app.exec_())

QGridLayout ‫بنفس الطريقة عند النتهاء من انشاء الزرار نشتق اوبجيكت من الكلس‬
‫ثم نضيف كل زر مصحوبا باحداثيات موضعه‬
‫و لو اردنا ان تكون الزرار اسفل بعضها البعض و زر الخروج في الزاوية ما علينا سوى تغير الحداثيات‬
‫على النحو التالي‬
grid=QGridLayout()
grid.addWidget(btn_one,1,0)
grid.addWidget(btn_two,2,0)
grid.addWidget(btn_three,3,0)
grid.addWidget(exit,4,1)
self.setLayout(grid)
‫ استعمال‬widget ‫امثلة عن اشهر الـ‬
Label
‫عبارة عن مكان مخصص للكتابة داخل النافذة تستعمل للتوضيح العمل المطلوب من المستخدم او لتوضيح عمل‬
‫ او اسمها‬widget
QLabel ‫ يجب ان نشتق اوبجيكت من الكلس‬Label ‫لكي نستعمل الـ‬
‫مثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Label(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.resize(250,150)
self.setWindowTitle('Label ex')
label=QLabel('name :', self)
label.move(5,10)
label=QLabel('age :', self)
label.move(5,50)
label=QLabel('email :', self)
label.move(5,100)

app=QApplication(sys.argv)
l=Label()
l.show()
sys.exit(app.exec_())

‫ بحيث‬GridLayout ‫ و هذه الخيرة شبيهة ب‬move ‫ ثم نحدد احداثيتها بواسطة‬Label ‫كما نلحظ ننشئ الـ‬
‫ مع الزرار ايضا‬move ‫اننا نحدد رقم الصف ثم رقم العمود و نستطيع استعمال‬
‫ففي المثال السابق )الخاص بالزرار( كنا نستطيع ان نحدد مواضعها بالشكل التالي‬
btn_one.move(10,20)
btn_two.move(10,50)
btn_three.move(10,80)
exit.move(220,120)
TextEdit & Line Edit
QLineEdit ‫ من المستخدم و تشئ بواسطة‬text ‫ للستقبل‬Line Edit ‫تستعمل‬
‫مثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Line_Edit(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.resize(250,150)
self.setWindowTitle("Line Edit ex")
name=QLineEdit() #line edit name
l_name=QLabel('name', self) # label name
age=QLineEdit() # line edit age
l_age=QLabel('age ', self) # label age
grid=QGridLayout()
grid.addWidget(l_name,1, 0)
grid.addWidget(name,1, 1)
grid.addWidget(l_age,2,0)
grid.addWidget(age,2, 1)
self.setLayout(grid)

app=QApplication(sys.argv)
line=Line_Edit()
line.show()
sys.exit(app.exec_())

grid ‫ الخاصة بها ثم رتبنا مواضع كل منهما بواسطة‬label ‫ و الـ‬LineEdit ‫قمنا في هذا المثال بإنشاء‬
‫ و بواسطة‬QTextEdit ‫ الذي سيدخله المستخدم نستعمل‬text ‫و اذا كنا نحتاج لمساحة كبيرة مخصصة للـ‬
‫ نحدد احداثياته و حجمه‬grid
‫مثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Line_Edit(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.resize(350,250)
self.setWindowTitle("Text Edit ex")
title=QLineEdit()
l_title=QLabel('title ', self)
note=QTextEdit()
l_note=QLabel('note', self)
grid=QGridLayout()
grid.addWidget(l_title, 1, 0)
grid.addWidget(title ,1,1)
grid.addWidget(l_note,2, 0)
grid.addWidget(note, 2, 1, 3, 1)
self.setLayout(grid)

app=QApplication(sys.argv)
line=Line_Edit()
line.show()
sys.exit(app.exec_())
‫ و عند‬QTextEdit ‫ و التي سيستعملها المستخدم لدخال ملحظاته استعملنا معها‬note ‫ل حظوا استعملنا مع‬
‫ حددنا احدياثيات موضعها ثم حجمها‬grid ‫الوصول للـ‬
grid.addWidget(note, 2, 1, 3, 1)
‫دعونا الن نجرب ما رأيناه في مثال‬
text ‫ فيظهر الـ‬show ‫ ثم نضغط على الزر‬LineEdit ‫ في‬text ‫سنعمل برنامج بسيط جدا نقوم في بكتابة‬
‫ آخر‬TextEdit ‫الذي كتبناه في‬

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Simple_Ex(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.showText = QTextEdit()
self.lineentry = QLineEdit("Type your text here ")
self.shtext=QPushButton("Show Text")
layout = QVBoxLayout()
layout.addWidget(self.showText)
layout.addWidget(self.lineentry)
layout.addWidget(self.shtext)
self.setLayout(layout)
self.connect(self.shtext, SIGNAL("clicked()"),self.show_method)
self.setWindowTitle("Simple exemple ")
def show_method(self):
try:
text = unicode(self.lineentry.text())
self.showText.append("%s " % (text))
except Exception ,e:
self.showText.append("Error %s " % (e))

app = QApplication(sys.argv)
ex = Simple_Ex()
ex.show()
app.exec_()
‫اذا لدينا ‪ showtext‬و هي التي سيظهر التيكست فيها عند الضغط على الزر‬
‫و ايضا ‪ lineentry‬و فيها يدخل المستخدم التيكست بالضافة للـ ‪ shtext‬عبارة عن زر عندما يضغط عليه‬
‫المستخدم سيظهر التيكست المكتوب في ‪ lineentry‬على ‪ showtext‬ثم قمنا بإنشاء صندوق عمودي و‬
‫جمعنا فيه كل الـ ‪ widget‬السالف ذكرها‬
‫)‪self.connect(self.shtext, SIGNAL("clicked()"),self.show_method‬‬
‫في هذا السطر يكمن سر المثال ككل لدينا اتصال بين الزر و الشارة هي ضغطة الزر ‪ clicked‬عند ارسال‬
‫الزر لهذه الشارة يأتي دور ‪ show_method‬و هي عبارة عن ميثود انشأناها للقيام بعمل البرنامج‬
‫‪def show_method(self):‬‬
‫‪try:‬‬
‫))(‪text = unicode(self.lineentry.text‬‬
‫))‪self.showText.append("%s " % (text‬‬
‫‪except Exception ,e:‬‬
‫‪self.showText.append("Error‬‬ ‫))‪%s " % (e‬‬
‫لدينا ‪ text‬ستحجز السلسلة الحرفية التي ادخلت من خلل ‪ lineentry‬ثم نقوم بإظهار هذه السلسلة المحتوات‬
‫في المتغير ‪ text‬نقوم بإظهارها في ‪ showtext‬و ذلك بواسطة ‪append‬‬
‫ملحظة‬
‫الكتابة التي ستظهر في ‪ showtext‬ستكون مفتوحة اي انك تستطيع الكتابة في الطار ‪ showtext‬و لو‬
‫اردت اغلقه اي يصبح يظهر التيكست فقط و ل يقبل الكتابة‬
‫استعمل ‪ QTextBrowser‬بدل من ‪ QTextEdit‬بحيث نستبدل السطر التالي‬
‫)(‪self.showText = QtextEdit‬‬
‫بالسطر التالي‬
‫)(‪self.showText = QtextBrowser‬‬
‫لو اردنا ان نضيف زر آخر يقوم بمسح الكتابة الموجودة في ‪ showtext‬ما علينا سوى اتباع الخطوات التالية‬
‫اول ننشئ الزر‬
‫)"‪self.cleartext=QPushButton("Clear‬‬
‫ثم نضيفه للصندوق‬
‫)‪layout.addWidget(self.cleartext‬‬
‫ثم ننشئ التصال‬
‫)‪self.connect(self.cleartext, SIGNAL("clicked()"), self.clear_method‬‬
‫و الميثود ‪ clear_method‬تكون كالتالي‬
‫‪def clear_method(self):‬‬
‫‪try:‬‬
‫)(‪self.showText.clear‬‬
‫‪except Exception ,e:‬‬
‫))‪self.showText.append("Error %s " %(e‬‬

‫بحيث اننا نمسح التيكست بواسطة ‪clear‬‬


Checkbox & RadioButton
‫مثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class CheckB_Radio(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)

self.resize(300,250)
self.setWindowTitle('Checkbox & RadioButton')
self.checkbox=QCheckBox('350, 250')
self.radio=QRadioButton('Show Normal')
layout=QVBoxLayout()
layout.addWidget(self.checkbox)
layout.addWidget(self.radio)
self.setLayout(layout)
self.connect(self.radio, SIGNAL('clicked()'), self.showNormal)
self.connect(self.checkbox, SIGNAL('clicked()'), self.upScreen)

def upScreen(self):
self.resize(400,350)
def showNormal(self):
self.resize(300,250)

app =QApplication(sys.argv)
test= CheckB_Radio()
test.show()
sys.exit(app.exec_())
‫ و تعود على هيئتها الطبيعية عند‬CheckBox ‫في هذا المثال تكبر النافذة عندما يضغط المستخدم على‬
QCheckBox ‫ بواسطة‬CheckBox ‫ ننشئ‬RadioButton ‫الضغط على‬
self.checkbox=QCheckBox('350, 250')
‫ و مابين القوسين نضع العبارة التي ستظهر امامه و بنفس‬QCheckBox ‫حيث نشتق ميثود من الكلس‬
QradioButton ‫ من الكلس‬RadioButton ‫الطريقة ننشئ‬
self.radio=QRadioButton('Show Normal')
‫لدينا مثال آخر شبيه شبيه بهذا المثال يقوم المستخدم فيه بإدخال عبارة كتابية و عند الضغط على‬
‫ تصغر‬RadioButton ‫( و عند الضغط على‬Maj ‫ او‬caps ‫ ستكبر الحروف )تصبح‬CheckBox
‫الحروف‬
‫المثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class CheckB_Radio(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)

self.resize(300,250)
self.setWindowTitle('Checkbox & RadioButton')
self.checkbox=QCheckBox(' Capital letters ', self)
self.radio=QRadioButton('Small letters ',self)
self.textin=QLineEdit()
self.textshow=QTextBrowser()
self.labeltextin=QLabel("type your text here ")
self.labeltextshow=QLabel("result ")
grid=QGridLayout()
grid.addWidget(self.checkbox,1,0)
grid.addWidget(self.radio,2,0)
grid.addWidget(self.labeltextin,3,0)
grid.addWidget(self.textin,3,1)
grid.addWidget(self.labeltextshow,4,0)
grid.addWidget(self.textshow,4,1,2,1)
self.setLayout(grid)
self.connect(self.radio, SIGNAL('clicked()'), self.showTextNormal)
self.connect(self.checkbox, SIGNAL('clicked()'), self.upperText)

def upperText(self):
try:
tup=unicode(self.textin.text())
self.textshow.append("%s" %(tup.upper()))
except Exception, e:
self.textshow.append(" Error : %s" %(e))

def showTextNormal(self):
try:
tlow=unicode(self.textin.text())
self.textshow.append("%s" %(tlow.lower()))
except Exception, e:
self.textshow.append(" Error : %s" %(e))

app =QApplication(sys.argv)
test= CheckB_Radio()
test.show()
sys.exit(app.exec_())

‫نشرح المثال بسرعة‬


connect ‫ ثم الـ‬grid ‫ التي نحتاجها ثم نظمنا اماكن ظهورها على النافذة بواسطة‬Widget ‫اول انشئنا كل ال‬
self.connect(self.radio, SIGNAL('clicked()'), self.showTextNormal)
self.connect(self.checkbox, SIGNAL('clicked()'), self.upperText)
‫و في الخير نبرمج كل ميثود لكي تعطي لنا النتائج المرغوبة‬
def upperText(self):
try:
tup=unicode(self.textin.text())
self.textshow.append("%s" %(tup.upper()))
except Exception, e:
self.textshow.append(" Error : %s" %(e))
‫ ثم نفتح التيكست المخصص‬tup ‫ول شيئ نحجز التكيست المدخل من طرف المستعمل في متغير سميناه‬
‫ و ننسخ محتوى المتغير و الذي كبرنا حروفه بواسطة الدالة‬append ‫ بواسطة‬textshow ‫للعرض‬
()upper
Message Box
‫ عبارة عن نوافذ ترسل للمستخدم رسالة معينة و تأخذ منه حدث مبني‬MessageBox ‫كما يدل اسمها ال‬
Error ‫ و ايضار رسائل الخطاء‬question ‫على هذه الرسالة لها عدة انواع و اشكال اشهرها رسائل السئلة‬
information ‫و رسائل المعلومة‬
‫ بحيث يوكن شكلها الطبيعي كالتالي‬QMessageBox ‫ بواسطة‬MessageBox ‫ننشئ‬
message=QMessageBox.typeOfMessage(self,'title','message',QMessageBox.buttons)
‫ عند‬showtext ‫سنوضح هذا في نفس المثال السابق بحيث اننا سنضيف زر آخر يقوم هذا الزر بمحو محتوى‬
‫نساله هل يريد فعل محو المحتوى‬messageBox ‫الضغط عليه و لكن قبل محو المحتوى نرسل للمستخدم‬
‫في نفس المثال اول نضيف الزر‬
self.btnclear=QPushButton("Clear text")
‫ثم موضعه في النافذة‬
grid.addWidget(self.btnclear,5,0)
connect ‫ثم الـ‬
self.connect(self.btnclear,SIGNAL('clicked()'),self.clearText)
‫ ميثود‬cleartext ‫و الن الهم‬
def clearText(self):
mess=QMessageBox.question(self, 'Clear all text ?','Clear text ?',QMess
ageBox.Yes, QMessageBox.No)
if mess == QMessageBox.Yes:
self.textshow.clear()
message=QMessageBox.typeOfMessage(self,'title','message',QMessageBox.button
s)
else:
pass

‫ من نوع‬Message ‫ و سيكون ال‬QMessageBox ‫ و ذلك بواسطة‬MessageBox ‫اول ننشئ الـ‬


qhestion
‫داخل القوس نحدد عنوان النافذة التي ستظهر‬
'Clear all text ?'
‫ثم السؤال الذي سيظهر على الرسالة‬
‫'? ‪'Clear text‬‬
‫ثم الزرار التي ستظهر على النافذة‬
‫‪QMessageBox.Yes, QmessageBox.No‬‬
‫بعد ذلك نجري احتمال على حسب الحدث المرسل من نافذة السؤال فإذا كان الحدث عبارة عن ضغطة على‬
‫الزر ‪ Yes‬سنمحي الكتابة الموجودة على ‪ showtext‬بواسطة‬
‫)(‪self.textshow.clear‬‬
‫و إذا كان العكس لن يعمل البرنامج شيئ‬
‫‪else:‬‬
‫‪pass‬‬
‫لعمل ‪ MessageBox‬من نوع ‪Information‬‬
‫‪def clearText(self):‬‬
‫‪QMessageBox.information(self,"Information Box", "clear all text with bu‬‬
‫)"‪tton clear‬‬
‫)(‪self.textshow.clear‬‬
‫ولعمل ‪ MessageBox‬من نوع ‪ Error‬او ‪critical‬‬
‫‪def clearText(self):‬‬
‫)"‪QMessageBox.critical(None,"Error", "You can't clear the text‬‬
‫و لعمل ‪ MessageBox‬للتأكد عند الرغبة في اغلق النافذة ماعليك سوى وضع هذه الميثود في قلب الكود‬
‫‪def closeEvent(self, event):‬‬
‫‪answer = QMessageBox.question(self, 'Quit',"Are you sure to quit?",QMes‬‬
‫)‪sageBox.Yes, QMessageBox.No‬‬

‫‪if answer == QMessageBox.Yes:‬‬


‫)(‪event.accept‬‬
‫‪else:‬‬
‫)(‪event.ignore‬‬
‫بحيث ان ال ‪ MessageBox‬سيسال المستخدم ان كان متؤكد باغلق النافذة‬
‫فاذا كان حدث الجواب )‪ (event‬عبارة عن ‪ yes‬ستعود الميثود ‪ closEvent‬على ‪ ()ecept‬او بعبارة‬
‫اخرى سيقبل حدث الخروج اما اذا كان العكس سيتجاهل حدث الخروج‬

‫‪Slider‬‬
‫حاب له استعمالت كثيرة نستطيع ناشاء ‪---‬سليدر بواسطة الكلس ‪QSlider‬‬
‫عبارة عن س ّ‬
‫و هو نواعان الفقي و العمودي‬
‫مثال‬
‫ ستتحرك‬slider ‫ و عند تحريك ال‬label ‫ واحد افقي و الخر عمودي و لدينا‬Slider 2 ‫في المثال التالي لدينا‬
‫ معه‬label ‫ال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Slider_Ex(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setGeometry(300, 300, 400, 300)
self.setWindowTitle('Slider')
self.label=QLabel("movable label", self)
self.label.move(35,2)
self.hslid=QSlider(Qt.Horizontal, self)
self.vslid=QSlider(Qt.Vertical, self)
self.hslid.setGeometry(40,60,350,370)
self.vslid.setGeometry(10,30,40,250)
self.connect(self.hslid, SIGNAL('valueChanged(int)'), self.horizontalMo
ve)
self.connect(self.vslid, SIGNAL('valueChanged(int)'), self.verticalMove
)

def horizontalMove(self):
hpos=self.hslid.value()
self.label.move(hpos,2)

def verticalMove(self):
vpos=self.vslid.value()
self.label.move(35,vpos)

app =QApplication(sys.argv)
test= Slider_Ex()
test.show()
sys.exit(app.exec_())
Qslider ‫ بواسطة‬Slider ‫ننشئ‬
self.hslid=QSlider(Qt.Horizontal, self)
‫ عبارة‬SIGNAL ‫ سيكون الـ‬connect ‫ طبعا في‬Vertical ‫ او‬Horizontal ‫ثم نبين نوعه داخل القوس‬
‫عن‬
SIGNAL('valueChanged(int)')
‫ لنه كلما تحرك يعود على قيمة و هذا ما استغللناه في الميثود‬Slider ‫اي القيمة المتغيرة جراء تحريك الـ‬
label ‫الخاصة بتحريك ال‬
def horizontalMove(self):
hpos=self.hslid.value()
self.label.move(hpos,2)
Slider ‫ ستتحرك وفق القيمة التي يرسلها ال‬label ‫بحيث ان ال‬
ComboBox
‫ لكي نتيج للمستخدم عدة خيارات لشيئ معين فبواسطته نستطيع انشاء لئحة‬ComboBox ‫نستعمل ال‬
‫خيارات‬
‫في المثال التالي لدينا برنامج يقفوم بالتحويل من الكيلوميتر الى الميل و العكس بحيث ان المستخدم يدخل القيمة‬
‫ثم يختار من اللئحة الوحدة التي يريد التحويل اليها‬
‫المثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Combo_Box(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setGeometry(300, 250, 300, 200)
self.setWindowTitle('ComboBox ')
self.cmbbox=QComboBox()
self.cmbbox.addItems(['Km/Mile','Km','Mile'])
self.valtext=QLineEdit()
self.result=QTextBrowser()
grid=QGridLayout()
grid.addWidget(self.cmbbox,0,0)
grid.addWidget(QLabel("Value"),2,0)
grid.addWidget(self.valtext,2,1)
grid.addWidget(QLabel("result"),3,0)
grid.addWidget(self.result,3,1)
self.setLayout(grid)
self.connect(self.cmbbox, SIGNAL("currentIndexChanged(int)"), self.Conv
ert)

def Convert(self):
val=self.valtext.text()
i=unicode(self.cmbbox.currentText())
if i =='Km':
self.result.append("%f" %(int(val)*0.621))
elif i =='Mile':
self.result.append("%f" %(int(val)*1.6093))
‫)‪app =QApplication(sys.argv‬‬
‫)(‪test= Combo_Box‬‬
‫)(‪test.show‬‬
‫))(_‪sys.exit(app.exec‬‬

‫ننشئ ال ‪ ComboBox‬بواسطة الكلس ‪QComboBox‬و بعد النشاء نضيف عناصر القائمة التابعة له‬
‫بواسطة ‪addItems‬‬
‫لدينا‬
‫)‪self.connect(self.cmbbox, SIGNAL("currentIndexChanged(int)"), self.Convert‬‬
‫لدينا ‪ connect‬تنشئ اتصال بين اللئحة و الشارة عبارة عن تغير في صف اللئحة ‪IndexChanged‬‬
‫التابعة لل ‪ComboBox‬‬
‫‪def Convert(self):‬‬
‫)(‪val=self.valtext.text‬‬
‫))(‪i=unicode(self.cmbbox.currentText‬‬
‫‪if i =='Km':‬‬
‫))‪self.result.append("%f" %(int(val)*0.621‬‬
‫‪elif i =='Mile':‬‬
‫))‪self.result.append("%f" %(int(val)*1.6093‬‬
‫اول نأخذ القيمة التي ادخلها المستخدم ثم نجري التحويل حسب صف اللئحة فإذا كان ‪ Km‬نضرب القيمة التي‬
‫ادخلها المستخدم في ‪ 0.621‬و لحظو جيدا لقد حولنا القيمة التي ادخلها المستخدم الى ‪ int‬قبل التحويل لن‬
‫اصلها كان عبارة عن سلسلة حرفية ايضا الناتج سيكون من نوع ‪ float‬حتى تظهر الفاصلة في النتيجة‬

‫اغلى هنا ينتهي درسنا اليوم و كما ترون هو درس متواضع يعطي للقارء نظرة سريعة على اهم ال ‪widget‬‬
‫المستعملة مازالت هناك الكثير منها و لكن لن نستطيع ان ندرسها كلها لن هذا يتطلب دورة مستقلة خاصة‬
‫بمكتبة ال ‪ Qt‬و لكن عند الجزء الثاني من هذا المحور سندرس كيفية استعمال الـ ‪ Designer‬الذي سيسهل‬
‫علينا العمل كثيرا‬

‫درسنا القادم سيكون حول ال ‪Dialogs‬‬

‫تم بحمد ال‬


:‫الدرس السادس عشر‬
... ‫نستمر‬
Dialogs
‫ عنصر اساسي في الوجهات الرسومية و ل يكاد يخلو برنامج منها بحيث انها تلعب دور‬dialog ‫تعتبر الـ‬
‫الخ‬... ‫الوسيط او الناقل سواء بين المستخدم و البرنامج او بين مجموعة المستخدمين‬
‫و نقول عنها ناقل و وسيط لنها تستعمل بكثرة للتعديل على خيارات البرنامج او نقل البيانات من المستخدم الى‬
‫البرنامج او العكس‬
‫لها عدة انواع سنحاول في هذ الدرس شرح اكثرها استعمال‬
InputDialog
‫ لخذ معلومة من المستخدم فهي تلعب دور الوسيط بين المستخدم و البرنامج‬dialog ‫يستعمل هذا النوع من الـ‬
dialog ‫ و زر بحيث ان ضغط المستخدم على الزر ستظهر له‬TextBrowser ‫في التالي مثال يحتوي على‬
text ‫تطلب منه ادخال اسم المستعمل فيظهر هذا السم على الـ‬

‫المثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class InputDialog(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)

self.setWindowTitle('Input Dialog')
self.resize(250,200)
self.browser=QTextBrowser()
self.btn_showdialog=QPushButton('Input name', self)
vlayout=QVBoxLayout()
vlayout.addWidget(self.browser)
vlayout.addWidget(self.btn_showdialog)
self.setLayout(vlayout)
self.connect(self.btn_showdialog, SIGNAL('clicked()'), self.setUserName
)

def setUserName(self):
name, ok=QInputDialog.getText(self, 'new user', 'username :')
try:
if ok:
self.browser.append("%s" %(name))
except :
self.browser.append("Invali name")

app=QApplication(sys.argv)
test=InputDialog()
test.show()
sys.exit(app.exec_())
QInputDialog ‫ نعتمد على‬inputDialog ‫للنشاء‬
name, ok=QInputDialog.getText(self, 'new user', 'username :')
ok ‫ عبارة عن حدث الضغط على زر‬ok ‫ يعتبر المتغير الذي سيحجز اسم المستخدم و‬name ‫لدينا‬
‫ ثم السؤال او العبارة التي ستطرح على المستخدم‬dialog ‫داخل القوسين نحدد عنوان ال‬
ColorDialog
‫ تمكن المستخدم من اختيار اللون بسهولة‬dialog ‫عبارة عن‬
‫في المثال التالي لدينا اطار داخل النافذة و سيقوم المستخدم باختيار لون الطار‬
color dialog ‫و ذلك عبر‬

‫المثال‬
import sys
from PyQt4.QtGui import*
class ColorDialog(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setGeometry(300, 300, 350, 280)
self.setWindowTitle('Colors')
self.color=QColorDialog.getColor()
def paintEvent(self, event):
paint =QPainter()
paint.begin(self)
paint.setPen(self.color)
paint.setBrush(QColor(self.color))
paint.drawRect(25, 5, 300, 260)
paint.end()
app =QApplication(sys.argv)
dt = ColorDialog()
dt.show()
app.exec_()
‫في السطر التالي‬
self.color=QColorDialog.getColor()
‫ لهذا الخير تساعده على‬dialog ‫ سيحجز السم الكامل للون الذي اختاره المستخدم و ذلك بإظهار‬color ‫لدينا‬
‫ التي تأخذ‬getColor ‫ ثم‬QColorDialog ‫ نستعمل‬dialog-‫اختيار اللون و كما نرى للظهار ال‬
‫مواصفات اللون الذي اختاره المستخدم‬
def paintEvent(self, event):
paint =QPainter()
paint.begin(self)
paint.setPen(self.color)
paint.setBrush(QColor(self.color))
paint.drawRect(25, 5, 300, 260)
paint.end()
‫ و التي تستخدم‬QPainter ‫هذه الميثود مخصصة للرسم على النوافذ بحيث اننا ننشئ ميثود من الكلس‬
end ‫ الى غايت‬begin ‫ ميثود من‬paintEvent-‫بدورها للرسم و يبدء عمل ال‬
paint.setPen(self.color)
dialog ‫هنا اخترنا اللون للرسم و هو اللون الذي اختاره المستخدم من ال‬
((paint.setBrush(QColor(self.color
‫ و هو ايضا اللون الذي اختاره المستخدم‬brush ‫ثم وضعنا لون الفرشات‬
paint.drawRect(25, 5, 300, 260)
‫ و ننهي الميثود بـ‬-300,260- ‫ و حجم الطار‬-25,5- ‫بعد ذلك احداثيات اطار الرسم‬
()paint.end
Font Dialog
‫يستعمل هذا النوع في اختيار نوع الخط و حجمه‬
‫مثال‬
import sys
from PyQt4.QtGui import*
from PyQt4.QtCore import *
class FontDialog(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
hbox =QHBoxLayout()
self.setGeometry(300, 300, 250, 110)
self.setWindowTitle('FontDialog')
button = QPushButton('Dialog', self)
button.move(20, 20)
hbox.addWidget(button)
self.connect(button, SIGNAL('clicked()'), self.showDialog)
self.label = QLabel('The Font Dialog ', self)
self.label.move(130, 20)
hbox.addWidget(self.label, 1)
self.setLayout(hbox)
def showDialog(self):
font, ok = QFontDialog.getFont()
if ok:
self.label.setFont(font)
app =QApplication(sys.argv)
test= FontDialog()
test.show()
app.exec_()
QfontDialog ‫ بواسطة‬FontDialog ‫نستدعي الـ‬
font, ok = QfontDialog.getFont()
font ‫ في النافذة ستحجز لنا‬ok ‫عند ظهور النافذة سيختار المستخدم خصائص الخط و عند الضغط على زر‬
labe ‫كل الخصائص التي اختارها المستخدم بعد ذلك نمرر هذه الخصائص للخط الذي في ال‬
File Dialog
‫ للختيار ملف معين من الجهاز‬dialog ‫تستعمل هذه ال‬
‫مثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class FileDialog(QWidget):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setGeometry(300, 300, 350, 350)
self.setWindowTitle('File dialog')
self.textEdit =QTextEdit(self)
self.showdialog=QPushButton("Open",self)
self.clear=QPushButton("Clear", self)
self.clear.move(80,0)
self.textEdit.setGeometry(40,30,280,300)
self.connect(self.showdialog, SIGNAL('clicked()'), self.showDialog)
self.connect(self.clear, SIGNAL("clicked()"), self.clear_method)
def showDialog(self):
try:
fname = QFileDialog.getOpenFileName(self, 'Open file','/home')
if fname !='':
file=open(fname)
data = file.read()
self.textEdit.append(data)
else:
self.textEdit.append('pleas select a file name ')
except IOError, e:
self.textEdit.append('Warring : %s' %(e))
def clear_method(self):
self.textEdit.clear()
app =QApplication(sys.argv)
test = FileDialog()
test.show()
app.exec_()
‫عندما يضغط المستخدم على زر ‪ open‬ستفتح له ‪ dialog‬تساعده على اختيار الملف و ذلك عبر‬
‫)'‪fname = QFileDialog.getOpenFileName(self, 'Open file','/home‬‬
‫‪if fname !='':‬‬
‫)‪file=open(fname‬‬
‫)(‪data = file.read‬‬
‫)‪self.textBrowser.append(data‬‬
‫نظهر هذه ال ‪ dialog‬بواسطة ‪QfileDialog‬و المتغير ‪ fname‬سيحجز المسار الكامل للملف الذي اختاره‬
‫المستخدم ثم نفتح هذا الملف بواسطة ‪ open‬ثم نقرء محتواه بواسطة ‪ read‬و المتغير ‪ data‬يلعب دور ال‬
‫‪ tompon‬بحيث انه يحجز محتوى الملف مؤقتا و في الخير نظهر محتوى الملف في ‪ TextEdit‬بواسطة‬
‫‪append‬‬
‫‪Print Dialog‬‬
‫تستعمل هذه ال ‪ dialog‬لطباعة الملفات و نسخها نبقى مع المثال السابق و نضيف عليه زر لطباعة محتوى‬
‫الملف الذي فتحه المستخدم‬
‫اول ننشئ الزر‬
‫)‪self.printf=QPushButton("Print", self‬‬
‫ثم نعدل موضعه‬
‫)‪self.printf.move(150,0‬‬
‫ثم التصال‬
self.connect(self.printf, SIGNAL('clicked()'), self.print_method)
print_method ‫ثم الميثود‬
def print_method(self):
printer =QPrinter()
printer.setFullPage(True)
dialog = QPrintDialog(printer, self)
if dialog.exec_() == QDialog.Accepted:
self.textEdit.document().print_(printer)
‫ هنا ستظهر ال‬QprintDialog ‫ بواسطة‬dialog ‫ ثم من ال‬QPrinter ‫اول نشتق ميثود من الكلس‬
‫ للمستخدم‬dialog
()_if dialog.exec
‫ و هنا سينسخ الملف‬Accepted ‫ الموجود في النافذة سينشئ حدث‬print ‫فإن ضغط المستخدم على زر‬
‫بواسطة‬
self.textEdit.document().print_(printer)
.‫ العادية و لهاذا اضيف لها » _ « للتفريق بينهما‬print ‫_ هذه تختلف عن‬print ‫و جدير بالذكر ان‬
Main Window ‫النوافذ الرئيسية‬
‫ تعتبر النافذة الرئيسة للبرنامج و هي التي تضم كل وظائفه و تحتوي ال‬Main Dialog ‫اسمها يعبر عنها فال‬
‫ على‬Main window
Statusbar
Menubar
Toolbar
‫ التي رأيناها من قبل‬widget ‫بالضافة للمجموعة ال‬

Main Dialog ‫انشاء‬


import sys
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.resize(300, 250)
self.setWindowTitle('Main Window')
app = QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())
‫كما نلحظ لم يتغير اي شيئ سوى‬
class MainWindow(QMainWindow)

QMainWindow ‫ الن اصبحت‬base class ‫بحيث ان ال‬


StatusBar ‫اضافة‬
import sys
from PyQt4.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.resize(300, 250)
self.setWindowTitle('Main Window')
self.statusBar().showMessage('Main Window')
app = QApplication(sys.argv)
test = MainWindow()
test.show()
sys.exit(app.exec_())
‫ نستعمل الكلس‬window ‫ لل‬StatusBar ‫للضافة‬
statusBar()
‫ نستعملها لظهار الكتابة التي نريد اسفل النافذة الرئيسية‬showMessage ‫و‬

Menu Bar ‫اضافة‬


import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)

self.resize(250, 150)
self.setWindowTitle('menubar')
exit =QAction(QIcon("../../home/chouaib/icon/kget.png"), 'Exit', self)
exit.setShortcut('Ctrl+Q')
exit.setStatusTip('Exit application')
self.connect(exit, SIGNAL('triggered()'), SLOT('close()'))
self.statusBar()
menubar = self.menuBar()
file = menubar.addMenu('&File')
file.addAction(exit)

app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
‫ عبارة عن اللئحة الفرعية التي ستظهر في ال‬Action ‫ و هذه ال‬exit ‫ سميناها‬QAction ‫أول انشانا‬
.‫ و هي التي ستقوم بالعمل عند الضغط عليها‬menu
exit =QAction(QIcon("../../home/chouaib/icon/kget.png"), 'Exit', self)
‫ بعد ذلك وضعنا اسم‬, ‫ الذي نريده‬icon ‫ « المسار الكامل لل‬/../.. » ‫ بحيث اننا نكتب بعد‬icon ‫و اخترنا لها‬
setShortcut ‫ للئحة بواسطة‬shorcut ‫ و تستطيع انشاء‬exit ‫اللئحة الفرعية‬
exit.setShortcut('Ctrl+Q')
‫ للئحة الفرعية‬statusBar ‫و نستطيع ايضا انشاء‬
exit.setStatusTip('Exit application')
connect ‫ بواسطة‬exit ‫بعد ذلك انشأنا اتصال للئحة الفرعية‬
self.connect(exit, SIGNAL('triggered()'), SLOT('close()'))
‫ العامل للنافذة‬StatusBar ‫و يجب ان ننشئ‬
self.statusBar()
‫ الذي انشأناه للئحة الفرعية‬StatusTips ‫و لو لم ننشئه لن يظهر ال‬
‫الن وصلنا للهم‬
‫ العام للنافذة الرئيسية‬menuBar ‫اول ننشئ ال‬
menubar = self.menuBar()
‫ثم نضيف له لئحة رئيسية‬
file = menubar.addMenu('&File')
‫ و نضع علمة » & « قبل السم حتى يتمكن المستخدم من استعمال الكيبورد للدخول للئحة‬File ‫و سميناها‬
‫ ثم الحرف الول للنافذة و الن‬Alt ‫و ذلك بالضغط على‬
file.addAction(exit)
‫ يكون كالتالي‬menu ‫اكسيون التي انشأناها و التي هي عبارة عن لئحة فرعية اي ان تسلسل‬----‫نضيف ال‬
exit ‫ و تضم داخلها لئحة فرعية و هي‬File ‫اللئحة الرئيسة‬
Toolbar
‫ لن يتغير الكثير في الكود‬menubar ‫ بدل‬Toolbar ‫و بنفس الطريقة تماما لو ادرنا ان ننشئ‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.resize(250, 150)
self.setWindowTitle('toolbar')
self.exit = QAction(QIcon('"../../home/chouaib/icon/kget.png"'), 'Exit'
, self)
self.exit.setShortcut('Ctrl+Q')
self.connect(self.exit, SIGNAL('triggered()'), SLOT('close()'))
self.toolbar = self.addToolBar('Exit')
self.toolbar.addAction(self.exit)

app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
menubar ‫سنعيد الن المثال الذي رأيناه سابقا و لكن هذه المّرة بدل الزرار سنستعمل‬
‫المثال‬
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Full_Dialog(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setGeometry(300, 300, 350, 350)
self.setWindowTitle('File dialog')
self.textEdit =QTextEdit(self)
self.textEdit.setGeometry(40,30,280,300)
self.statusBar()
openf=QAction(QIcon('../../home/chouaib/icon/stock_open.svg'),'Open', s
elf)
printf=QAction(QIcon('../../home/chouaib/icon/stock_print.svg'), 'Print
',self)
clearf=QAction(QIcon('../../home/chouaib/icon/stock_undo.svg'), 'Clear'
, self)
exit=QAction(QIcon('../../home/chouaib/icon/stock_quit.svg'), 'Exit', s
elf)
openf.setShortcut('Ctrl+o')
openf.setStatusTip('Open file')
printf.setShortcut('Ctrl+p')
printf.setStatusTip('Print File')
clearf.setShortcut('Ctrl+l')
clearf.setStatusTip('Clear')
exit.setShortcut('Ctrl+q')
exit.setStatusTip('Exit')
self.connect(openf, SIGNAL('triggered()'), self.showDialog)
self.connect(clearf, SIGNAL('triggered()'), self.clear_method)
self.connect(printf, SIGNAL('triggered()'), self.print_method)
self.connect(exit, SIGNAL('triggered()'), SLOT('close()'))

menubar = self.menuBar()
file=menubar.addMenu('&File')
file.addAction(openf)
file.addAction(printf)
file.addAction(clearf)
file.addAction(exit)

def showDialog(self):
try:
fname = QFileDialog.getOpenFileName(self, 'Open file','/home')
if fname !='':
file=open(fname)
data = file.read()
self.textEdit.append(data)
else:
self.textEdit.append('pleas select a file name ')

except IOError, e:
self.textBrowser.append('Warring : %s' %(e))
def clear_method(self):
self.textEdit.clear()

def print_method(self):
printer =QPrinter()
printer.setFullPage(True)
dialog = QPrintDialog(printer, self)
if dialog.exec_() == QDialog.Accepted:
self.textEdit.document().print_(printer)

app =QApplication(sys.argv)
test = Full_Dialog()
test.show()
app.exec_()

toolbar ‫حاولو ان تعيدو نفس المثال بإستعمال‬

‫مازال درس أخير و ننهي الواجهات بإذن ال‬

‫تم بحمد ال‬


‫الدرس السابع عشر ]‪:[signals & slots‬‬
‫الخوة الفاضل‬
‫السلم عليكم و رحمة ال و بركاته‬
‫اليوم بحمد ال سنكمل الواجهات الرسومية و سنتحدث في هذا الدرس حول ‪ sgnal & slot‬بشيئ من‬
‫الختصار لننا رأيناه من قبل ثم نمر إلى استعمال المصمم في برامجنا‬
‫و بهذا نكون انهينا الجزء الخير من الدورة و نكون بجمد ال قد شملنا معظم أساسيات لغة البايثون‬
‫و يستطيع متتبع الدورة البدئ في انشاء برامج متكاملة و يبقى الحتراف او التقان فهذا ل استطيع ان اكتبه في‬
‫درس او حتى اخصص له الدورة لن التقان يأتي بالتجربة و دقة الملحظة و خصوبة الفكار‬
‫و أريد ان اطمئنكم فنحن لم ننهي الدورة بل الهدف الساسي من الدورة قد اقترب و ينتظرنا الجزء الثاني من‬
‫الدورة و الذي سنخصصه لبرمجة الشبكات و قواعد البيانات و ال ‪Theridng‬‬
‫و هذا بعد ثلث اسابيع من اليوم بإذن ال‬
‫أمثلة حول ‪Signals & Slots‬‬
‫المثال الول‬
‫‪import sys‬‬
‫* ‪from PyQt4.QtGui import‬‬
‫* ‪from PyQt4.QtCore import‬‬
‫‪class Signal_Slot(QDialog):‬‬
‫‪def __init__(self, parent=None):‬‬
‫)‪QDialog.__init__(self, parent‬‬
‫)(‪dial = QDial‬‬
‫)‪dial.setNotchesVisible(True‬‬
‫)(‪spinbox = QSpinBox‬‬
‫)(‪layout = QHBoxLayout‬‬
‫)‪layout.addWidget(dial‬‬
‫)‪layout.addWidget(spinbox‬‬
‫)‪self.setLayout(layout‬‬
‫)‪self.connect(dial, SIGNAL("valueChanged(int)"),spinbox.setValue‬‬
‫)‪self.connect(spinbox, SIGNAL("valueChanged(int)"),dial.setValue‬‬

‫)‪app =QApplication(sys.argv‬‬
‫)(‪test = Signal_Slot‬‬
‫)(‪test.show‬‬
‫)(_‪app.exec‬‬

‫لدينا ‪ spinbox‬و عداد ‪ dal‬مرتبطان ببعضهما البعض بواسطة ‪ connect‬ميثود بحيث ان كل واحد يأخذ‬
‫اتصال من الخر‬
‫)‪self.connect(dial, SIGNAL("valueChanged(int)"),spinbox.setValue‬‬
‫)‪self.connect(spinbox,SIGNAL("valueChanged(int)"),dial.setValue‬‬
‫ف ‪ dial‬يتحرك عند تغير ‪ value‬في ‪ spnbox‬و العكس‬
‫المثال الثاني‬

spinbox ‫ بدل‬slder ‫نفس المثال الول تقريبا و لكن في هذه المرة سنستعمل‬
dial ‫ بدل‬Lcd number ‫و سنستعمل‬
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Signal_Slot(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle('signal & slot')
lcd = QLCDNumber(self)
slider =QSlider(Qt.Horizontal, self)
vbox =QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(slider)
self.setLayout(vbox)
self.connect(slider, SIGNAL('valueChanged(int)'), lcd, SLOT('display(in
t)') )
self.resize(250, 150)
app =QApplication(sys.argv)
test= Signal_Slot()
test.show()
sys.exit(app.exec_())

emit signal
‫ سيجنال بيحث اننا ننشئ نوع جديد‬emiting « ‫ من » ارسال التصال‬emit ‫تمكننا ميثود خاصة تدعى ب‬
‫ معينة‬widget ‫ ان صح التعبير و نربطه بأدات‬signal ‫من ال‬
‫مثال‬
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class Emit_Sgl(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.label = QLabel(" ")
layout = QVBoxLayout()
layout.addWidget(self.label)
self.setLayout(layout)
self.connect(self, SIGNAL("showText"),self.update_label)
self.emit(SIGNAL("showText"), "important", "informationn ")

def update_label(self, value1, value2):


self.label.setText(value1 + " " + value2)

app = QApplication(sys.argv)
test = Emit_Sgl()
test.show()
sys.exit(app.exec_())
‫لحظو جيدا‬
widget ‫ لل‬connect ‫اول قمنا بإجراء التصال ب‬
self.connect(self, SIGNAL("showText"),self.update_label)
‫ في مكتبة‬sgnal ‫ طبعا ل يوجد هذا النوع من‬showtext ‫ الذي سينطلق عند ظهور النافذة هو‬signal ‫و ال‬
‫بل نحن من أنشأناه‬PyQt4
‫و هذا ما يبينه السطر التالي‬
self.emit(SIGNAL("showText"), "emit signal ", " :::>> label ")
‫و لدينا‬
def update_label(self, value1, value2):
self.label.setText(value1 + " " + value2)
emit ‫ تعبران عن العبارتان الموجودتان في الميثود‬alue2 ‫ و‬value1 ‫في هذه الميثود لدينا‬
‫ و الذي بدوره متصل بالميثود‬signal show text ‫ينتج ال‬widget ‫فعند تنفيد البرنامج و عند ظهور ال‬
updat_label
self.connect(self, SIGNAL("showText"),self.update_label)
emit ‫ ارسلناه بواسطة الميثود‬signal ‫ هو عبارة عن‬signal ‫طيب ما هو هذا‬
self.emit(SIGNAL("showText"), "emit signal ", " :::>> label ")
signal ‫على اسم الـ‬emit ‫و تحتوي الميثود‬
SIGNAL("showText")
‫و هذا اجباري‬
signal ‫المصحوبة بال‬arguments ‫بالضافة الى مجموعة‬
"emit signal ", " :::>> label ")
‫و اضافتها اختيارية‬
updat_label ‫و في الخير الميثود‬
def update_label(self, value1, value2):
self.label.setText(value1 + " " + value2)
‫ « المصحوبة بال‬arguments » ‫ و هما كما قنا سابقا العبارتان‬value 2 ‫ و‬vlaue1 ‫و التي تقوم بإظهار‬
emit sgnal

‫مثال آخر‬
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Emit(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle('emit')
self.resize(250, 150)
self.connect(self, SIGNAL('closeEmitApp()'), SLOT('close()') )
‫‪def mousePressEvent(self, event):‬‬
‫))')(‪self.emit(SIGNAL('closeEmitApp‬‬

‫)‪app = QApplication(sys.argv‬‬
‫)(‪test = Emit‬‬
‫)(‪test.show‬‬
‫))(_‪sys.exit(app.exec‬‬
‫كل شيئ يبدء كالعادة دون أي تغير حتى في الميثود ‪ connect‬لم يتغير شيئ سوى اسم ال ‪signal‬‬
‫فهذا السم من اختيارنا نحن كما في المثال السابق فل تظن ان هذا السم محجوز من طرف المكتبة و لو شئت‬
‫غير اسمه كما يحلو لك‬
‫) )')(‪elf.connect(self, SIGNAL('closeEmitApp()'), SLOT('close‬‬
‫لدينا التصال بين النافذة و السينيال ‪ closeEmitApp‬الذ سنراه الن و ‪ slot‬عبارة عن اغلق النافذة‬
‫‪()close‬‬
‫‪def mousePressEvent(self, event):‬‬
‫))')(‪self.emit(SIGNAL('closeEmitApp‬‬
‫هنا السيجنال ‪ closeEmitApp‬سيرسل عند الضغط بالفأرة على النافذة وهذا ما يعني اغلق النافذة لننا كما‬
‫رأينا في الميثود ‪ connect‬ال ‪ slot‬عبارة عن ‪()close‬‬
‫و لهذا نسمي الميثود ‪ emit‬بالمرسلة و مهمتها ارسال ال ‪ signal‬عند وقوع حدث معين ففي هذا المثال‬
‫الحدث اي ‪ event‬عبارة عن ضغطة الفأرة على النافذة عند وقوع هذا الحدث سيرسل الشارة‬
‫‪closeEmtApp‬‬
‫))')(‪self.emit(SIGNAL('closeEmitApp‬‬
‫و هذا ما يعني إغلق النافذة‬
‫) )')(‪SIGNAL('closeEmitApp()'), SLOT('close‬‬
‫سنكتفي بهذا القدر و سنعود للميثود ‪ emit‬بشيئ من التفصيل في الدروس المقبلة‬
‫الدرس الثامن عشر ]‪:[Qt Designer‬‬
‫من بين اهم مميزات مكتبة ‪ PyQt‬هو احتواؤها على مصمم ذو فعالية عالية و سهولة استعماله فكما رأينا في‬
‫الدروس السابقة نستطيع انشاء واجهة رسومية بواسطة الشيفرات فقط و لكن هذا العمل سيصبح متعب كلما‬
‫تعقدت الواجهة و من الصعب على المبرمج الجديد على الواجهات ان يستوعب كل الكلس و الميثود‬
‫المخصصة للواجهات و كيفية استعمال كل واحدة فهذا يتطلب وقت كبير و ممراسة‬
‫فالمصمم يتيح لنا الفرصة بتصميم الواجهة التي نريد و تعديلها ثم نقوم بتحويل هذه الواجهة الى كود و ذلك‬
‫بواسطة المر‬
‫‪pyui4‬‬
‫اول افتح ال ‪Designer‬‬
‫عند فتحه ستظهر لك نافذة للختيار نوع المشروع قم باختيار ‪widget‬‬

‫على يسارك ستجد مجموعة من ال ‪) widget‬ازرار ‪..checbox radobox TextEdit‬الخ( وتدعى بال‬
‫‪ widgetEdit‬اختر منها الزر ‪ button‬و قم بسحبه لل ‪widget‬‬
‫ثم اضغط على ‪ F4‬لتحديد ال ‪ signal‬و ال ‪slot‬‬
‫و تستطيع فعل ذلك من القائمة ‪ updat‬ثم اختر ‪edit signal & slot‬‬
‫اختر في القائمة الولى على ‪ ()clicked‬ثم اسحب الخط الحمر حتى يلمس سطح النافذة ثم اختر من القائمة‬
‫الخاصة بال ‪ slot‬اختر منها ‪()close‬‬
‫الخط الحمر يبين طرفين التصال و في حالتنا هذه الطرفان هما الزر و النافذة‬

‫قم بحفظ المشروع على اسم ‪ test‬ثم افتح سطر الوامر ‪terminal‬‬
‫اذهب للمسار الذي حفظت في المشروع و اكتب السطر التالي‬
‫‪pyuic4 test.ui>test.py‬‬
‫يقوم المر ‪ pyuic4‬بتحويل المشروع الذي انشأناه الى كود ‪ PyQt4‬كالذي اعتدنا كتابته‬
‫اذهب الى المفسر ‪ eclips‬او ‪ Pyscri pter‬و افتح الملف ‪test.py‬‬
‫و اضف له السطور التالية في نهايته‬
‫بعد الميثود ‪retranslateUi‬‬
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_Form()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = MyForm()
myapp.show()
sys.exit(app.exec_())
‫طبعا ستكتب الكلس عند اول السطر و احذر ان تترك فراغا‬
‫نفذ البرنامج و مبروك عليك اول مثال بالمصمم‬

‫اول مشروع‬
NOTPAD
MainWindow ‫كما فعلنا من قبل افتح المصمم و لكن اختر في هذه المرة‬
textEdit ‫ زرين و‬wndow ‫اضف ل‬

‫ و ذلك بالضغط على الزر كليك يمين ثم اختر‬button_open ‫غير اسم الزر الول الى‬
change objectName
‫ ثم اضغط كليك يمين على النافذة و غير‬editor_window ‫ الى‬testEdit ‫و بنفس الطريقة غير ايم ال‬
notepad ‫ الى‬MainWindow ‫اسمها هي الخرى من‬
‫ كما فعلنا في المثال‬close ‫ ثم قم بتعديل اتصال الزر‬close ‫و الزر الباقي اتركه كما و فقط غير اسمه الى‬
‫ لكن احذر يجب ان يلمس الخط الحمر النافذة فقط‬slot close ‫)( و ال‬signal cliced ‫الول‬
‫ و قم بتحويله بواسطة سطر الوامر‬editor ‫في الخير احفظ المشروع بإسم‬
pyuic4 editor.ui > editor.py
‫ و اضف له السطر التالي للتجربة‬editor.py- ‫قم بفتح الملف‬
class NotePad(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_notepad()
self.ui.setupUi(self)

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = NotePad()
myapp.show()
sys.exit(app.exec_())
‫بداية الطريق‬
‫ل التعديل عليه بكل حرية فلو اردنا مثل طبع جملة معينة‬
ّ ‫الن نحن نملك الكود الخاص بالمشروع و ماعلينا إ‬
‫ ما علينا سوى اتباع الخطوات التالية‬open ‫عند الضغط على زر‬
class NotePad(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_notepad()
self.ui.setupUi(self)
# here we connect signals with our slots
QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"),
self.file_dialog)
def file_dialog(self):
self.ui.editor_window.append('Open File :) ')

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = NotePad()
myapp.show()
sys.exit(app.exec_())
‫كما كنا نعمل في السابق تماما‬
connect method ‫اول‬
QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"), self.fil
e_dialog)
‫سنضطر لكتابة كامل التسلسل للستعمال مختلف الميثود لن المصمم ل يستدعي كل المكتبة‬
widget ‫ ثم اسم ال‬ui ‫ سنكتب‬widget ‫ايضا قبل اي‬
‫و بعدها الميثود التي ستقوم‬cliced ‫ عبارة عن‬signal ‫ و ال‬button_open ‫هنا لدينا اتصال بين الزر‬
file_dalog ‫ وهي في هذا المثال‬signal ‫بالعمل عند ارسال ال‬
‫فكما نلحظ لم يتغير شيئ كبير في الكود‬
def file_dialog(self):
self.ui.editor_window.append('Open File :) ')
‫ و الذي سميناه‬textEdit ‫ على‬Open file ‫كالعادة نقوم بتجهيز المكيثود و هي كما نرى تقوم باضافة الجملة‬
‫ عند انشاء المشروع‬editor
‫ عمله الصلي و هو فتح ملف حسب‬open_file ‫طيب الن سنعيد كتابة الكود من جديد و سنعطي للزر‬
editor ‫اختيار المستخدم و اظهاره على‬
class NotePad(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_notepad()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"),
self.file_dialog)
def file_dialog(self):
file_dialog = QtGui.QFileDialog(self)
tmp = open(file_dialog.getOpenFileName()).read()
self.ui.editor_window.append(tmp)

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = NotePad()
myapp.show()
sys.exit(app.exec_())
‫بعد التصال يأتي دور الميثود‬
‫ ثم ننشئ اوبجيكت يقوم بقراءة محتوى الملف و يحجزه لنا مؤقتا‬file_dialog ‫اول شتقق ميثود من الكلس‬
file_dialog = QtGui.QFileDialog(self)
tmp = open(file_dialog.getOpenFileName()).read()
‫و في الخير‬
self.ui.editor_window.append(tmp)
editor_wndow ‫ننسخ محتوى الملف في ال‬
‫منتهى البساطة‬
**** ‫يوجد خطئ و يجب الحذر و التصحيح‬
‫ للختيار الملف و اغلقناها دون اختيار الملف سيحدث خطئ و ل يجب حدوث‬dialog ‫لو ظهرت لنا ال‬
‫الخطئ هنا لنك قريب جدا من المستخدم‬
‫نستطيع حل هذا المشكل بكل بساطة بطريقتين‬
:(exceptdef file_dialog(self ‫الولى بواسطة‬
try:
file_dialog = QtGui.QFileDialog(self)
tmp = open(file_dialog.getOpenFileName()).read()
self.ui.editor_window.append(tmp)
except IOError :
self.ui.editor_window.append("no sush file or directory ")
‫ التي رأيناها من قبل في درس الملفات‬isfile ‫و الثانية اكثر امانا و احترافية بواسطة‬
def file_dialog(self):
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
tmp = open(self.filename).read()
self.ui.editor_window.append(tmp)
‫الن نريد ان نضيف زر آخر يقوم بحفظ الملف بعد التغير فيه‬
‫ و نغير‬save ‫اول نفتح نفس المشروع السابق و نضيف له زر ثالث نسميه‬
button_save ‫ الى‬objectName
‫نحفظ المشروع نعيد تحويله بواسطة سطر الوامر‬
pyuic4 edytor.ui > edytor.py
‫ ونضيف له السطور التالية‬editor.py ‫ثم نفتح ملف‬

class NotePad(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_notepad()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"),
self.file_dialog)
QtCore.QObject.connect(self.ui.button_save,QtCore.SIGNAL("clicked()"),
self.file_save)

def file_dialog(self):
fd = QtGui.QFileDialog(self)
self.filename = fd.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)

def file_save(self):
from os.path import isfile
if isfile(self.filename):
file = open(self.filename, 'w')
file.write(self.ui.editor_window.toPlainText())
file.close()

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = NotePad()
myapp.show()
sys.exit(app.exec_())
save ‫ما اضفناه هو الميثود الخاصة بعمل الزر‬
def file_save(self):
from os.path import isfile
if isfile(self.filename):
file = open(self.filename, 'w')
file.write(self.ui.editor_window.toPlainText())
file.close()
open ‫نقوم بفحص الملف المفتوح اصل ثم نفتحه بواسطة‬
file = open(self.filename, 'w')
editor_window ‫ثم نكتب داخله كل محتوى‬
file.write(self.ui.editor_window.toPlainText())
‫ معطل‬save ‫الن سنضيف تعديل آخر على المشروع بحيث ان المستخدم عندما يفتح الملف يكون زر‬
enable ‫للعمل‬save ‫ و عند التغير في محتوى الملف مباشرتا يعود زر‬Disable

‫ و ميثود اخرى سننشئها‬editor_window ‫ تربط بين ال‬connect ‫اول يجب ان نضيف ميثود‬
QtCore.QObject.connect(self.ui.editor_window,QtCore.SIGNAL("textChanged()"), se
lf.enable_save)
‫ اي عندما يتغير محتو التيكست سيرسل السينيال‬textChanged ‫ عبارة عن‬signal ‫لدينا ال‬
‫ سنضيف السطر التالي‬file_dialog ‫و في آخر سطر في الميثود‬
self.ui.button_save.setEnabled(False)
‫ معطل و نضيف الميثود التالية في كود المشروع‬save ‫اي انه عند فتح الملف سيكون الزر‬
def enable_save(self):
self.ui.button_save.setEnabled(True)
save ‫بتشغيل الزر‬enable_sae ‫ ستقوم الميثود‬connect ‫ من الميثود‬textChanged ‫فعند ارسال ال‬
‫الن سنغير على المشروع مرة أخرى‬
‫إذا فتح المستخدم ملف و غير في محتواه ثم اراد ان يفتح ملف آخر سيهمل البرنامج التغير الذي طرء على‬
‫الملف‬
‫ تساله ان كان‬dialog ‫ بحيث اذا فتح المستخدم ملف آخر ستظهر له‬file_dialog ‫لدى سنقوم بتغير الميثود‬
‫يريد حفظ الملف المتغير ام يهمل التغير و يفتح ملف جديد‬

def file_dialog(self):
if self.ui.button_save.isEnabled():
message=QtGui.QMessageBox.question(self, 'save file ?','save change
s ?',QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if message == QtGui.QMessageBox.Yes:
self.file_save()
self.ui.button_save.setEnabled(False)
elif message == QtGui.QMessageBox.No:
self.ui.button_save.setEnabled(False)
self.ui.editor_window.clear()
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)

else:
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)
self.ui.button_save.setEnabled(False)
‫ فإذا كان مشغل ل فهذا يعني انه يوجد ملف مفتوح و قد تغير محتواه هنا يأتي دور ال‬save ‫اول نختبر الزر‬
dialog
message=QtGui.QMessageBox.question(self, 'save file ?','save changes ?',QtGui.
QMessageBox.Yes, QtGui.QMessageBox.No)
if message == QtGui.QMessageBox.Yes:
Yes ‫اذا اختار المستخدم‬
self.file_save()
self.ui.button_save.setEnabled(False)
No ‫ اما اذا اختار‬save ‫ ثم يعطل زر‬save_file ‫سيحفظ الملف بواسطة الميثود‬
elif message == QtGui.QMessageBox.No:
self.ui.button_save.setEnabled(False)
self.ui.editor_window.clear()
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)
‫ لختيار الملف كالعادة‬dialog ‫ و ستظهر له ال‬window_editor ‫سيمحى محتوى ال‬
‫ اي ان انه ل يوجد ملف مفتوح سيبقى الكود كما هو دون تغير‬enabled ‫ لم يكن‬save ‫اما في حالة ان الزر‬
else:
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)
self.ui.button_save.setEnabled(False)
‫كود المشروع الكامل‬
import sys
from PyQt4 import QtCore, QtGui

class Ui_notepad(object):
def setupUi(self, notepad):
notepad.setObjectName("notepad")
notepad.resize(QtCore.QSize(QtCore.QRect(0,0,668,536).size()).expandedT
o(notepad.minimumSizeHint()))

self.centralwidget = QtGui.QWidget(notepad)
self.centralwidget.setObjectName("centralwidget")

self.button_open = QtGui.QPushButton(self.centralwidget)
self.button_open.setGeometry(QtCore.QRect(20,10,201,27))
self.button_open.setObjectName("button_open")

self.pushButton_2 = QtGui.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(440,10,201,27))
self.pushButton_2.setObjectName("pushButton_2")

self.editor_window = QtGui.QTextEdit(self.centralwidget)
self.editor_window.setGeometry(QtCore.QRect(23,50,611,431))
self.editor_window.setObjectName("editor_window")

self.button_save = QtGui.QPushButton(self.centralwidget)
self.button_save.setGeometry(QtCore.QRect(230,10,201,27))
self.button_save.setObjectName("button_save")
notepad.setCentralWidget(self.centralwidget)

self.menubar = QtGui.QMenuBar(notepad)
self.menubar.setGeometry(QtCore.QRect(0,0,668,25))
self.menubar.setObjectName("menubar")
notepad.setMenuBar(self.menubar)

self.statusbar = QtGui.QStatusBar(notepad)
self.statusbar.setObjectName("statusbar")
notepad.setStatusBar(self.statusbar)

self.retranslateUi(notepad)
QtCore.QObject.connect(self.pushButton_2,QtCore.SIGNAL("clicked()"),not
epad.close)
QtCore.QMetaObject.connectSlotsByName(notepad)

def retranslateUi(self, notepad):


notepad.setWindowTitle(QtGui.QApplication.translate("notepad", "MainWin
dow", None, QtGui.QApplication.UnicodeUTF8))
self.button_open.setText(QtGui.QApplication.translate("notepad", "Open"
, None, QtGui.QApplication.UnicodeUTF8))
self.pushButton_2.setText(QtGui.QApplication.translate("notepad", "Clos
e", None, QtGui.QApplication.UnicodeUTF8))
self.button_save.setText(QtGui.QApplication.translate("notepad", "save"
, None, QtGui.QApplication.UnicodeUTF8))

class NotePad(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_notepad()
self.ui.setupUi(self)
QtCore.QObject.connect(self.ui.button_open,QtCore.SIGNAL("clicked()"),
self.file_dialog)
QtCore.QObject.connect(self.ui.button_save,QtCore.SIGNAL("clicked()"),
self.file_save)
QtCore.QObject.connect(self.ui.editor_window,QtCore.SIGNAL("textChanged
()"), self.enable_save)
self.ui.button_save.setEnabled(False)

def file_dialog(self):
if self.ui.button_save.isEnabled():
message=QtGui.QMessageBox.question(self, 'save file ?','save change
s ?',QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if message == QtGui.QMessageBox.Yes:
self.file_save()
self.ui.button_save.setEnabled(False)
elif message == QtGui.QMessageBox.No:
self.ui.button_save.setEnabled(False)
self.ui.editor_window.clear()
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)

else:
file_dialog = QtGui.QFileDialog(self)
self.filename = file_dialog.getOpenFileName()
from os.path import isfile
if isfile(self.filename):
text = open(self.filename).read()
self.ui.editor_window.append(text)
self.ui.button_save.setEnabled(False)

def enable_save(self):
self.ui.button_save.setEnabled(True)

def file_save(self):
from os.path import isfile
if isfile(self.filename):
file = open(self.filename, 'w')
file.write(self.ui.editor_window.toPlainText())
file.close()

if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp = NotePad()
myapp.show()
sys.exit(app.exec_())

You might also like