لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 02/23/23 في كل الموقع
-
السلام عليكم و رحمة الله لديّ موقع انترنت عملته من خلال html , css js لشركة في دبي ، و لكن عندما رفعته أرى انه على الهواتف يكون بطيئاً نوعاً ما ، هل من ارشادات تجعل الموقع اكثر سرعة الموقع يوجد فيه العديد من الصور و ٤ فيديو و شكرا لكم2 نقاط
-
الإصدار 1.0.0
22116 تنزيل
كتاب إدفع لي وإلا هو كتاب مجاني لكاتبه Lior Frenkel مؤسس شريك في The nuSchool، مستقل ومطوّر ويب وهو الآن مستشار، مدوّن ومتحدث في الأنشطة حول العالم. قام Lior بكتابة هذا الكتاب في عام 2015 ليساعد المستقلين حول العالم في التعامل مع حالات امتناع العملاء عن الدفع بناءً على خبرته الممتدة لسنوات في العمل الحر.1 نقطة -
انا كنت عاوز اعمل برنامج لفكرة معينة بس قررت ان انا اللي اعمل البرنامج فا كنت عاوز اعرف اتعلم تصميم التطبيقات علي أي طريقة يعني اتعلم لغة جافا و اصمم به البرنامج ولا اتعلم لغة dart وانفذ البرنامج علي فلاتر وايه الافضل فيهم من حيث عاوز ادخل منتجات بعد تنفيذ البرنامج والتعديل عليه1 نقطة
-
السلام عليكم لديّ موقع صممته من خلال html , css , js يوجد قسم في موقعي أريد به من المستخدم وضع حسابه الemail و يضغط اشتراك حتى استطيع الحصول على العديد من الايميلات.. كما في جميع المواقع كيف استطيع من خلال javascript ان ارسل القيمة الذي ادخلها المستخدم الى ايميلي الخاص مثلا ، او حفظها بطريقةٍ ما في إحدى الأماكن1 نقطة
-
في حالة وجود margin-bottom سيوجد مسافة في النهاية خاصة بعنصر a الأخير وهو ما لا نريده، ففي الصورة المطلوبة يريد حذف المسافات بالكامل، الكود سليم ويمكن إصلاحه من خلال تعديل كود css بإضافة: .qlink:not(:last-child){ margin-bottom: 7px; } ويصبح كود CSS كالتالي: .box{ border-style:solid; display: inline-block ; } .qlink { display:block; text-align:center; color: white; width: 150px; padding:16px 0; text-decoration:none; font-size: 12px; font-weight: bold; background-color: #1F70C4; } .qlink:not(:last-child){ margin-bottom: 7px; } .qlink:hover {background: #2484E9;} .qlink:active {background: #155292;} وفي حال أراد السائل إبقاء الكود الخاص به كما هو، فيجب تعديله ليصبح بالشكل التالي: HTML <div class='container'> <a href="https://google.com/1"> <button class="qlink">Awards</button> </a> <a href="https://google.com/2"> <button class="qlink">Directory</button> </a> <a href="https://google.com/3"> <button class="qlink">Patent</button> </a> <a href="https://google.com/4"> <button class="qlink">Calendar</button> </a> <a href="https://google.com/5"> <button class="qlink">Leave Request Tool</button> </a> <a href="https://google.com/6"> <button class="qlink">Publications</button> </a> </div> CSS div { width: max-content; text-align: center; border-style:solid; margin: auto; } .qlink { border: none; background-color: #1F70C4; color: white; height: 35px; width: 150px; font-size: 12px; display: inline-block; font-weight: bold; } .qlink:hover {background: #2484E9;} .qlink:active {background: #155292;} فالمشكلة كانت في إزالة الـ margin الخاصة بالأزرار ثم ضبط عرض الـ div الأب الذي يحوي كافة العناصر ليصبح عرضه هو نفس عرض المحتوى بداخله من خلال width: max-content;1 نقطة
-
1 نقطة
-
1 نقطة
-
1 نقطة
-
الموضع سهل ولا يجب أن تيأس بسرعة هكذا. غير أن هذا الوسم مهم ويفضل أن تتعلم كيف تستخدمة. دعنا نستخدم الوسم Video ولكن هذه المرة سوف نستخدم فيديو من الأنترنت قم بتجربة هذا الكود. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <video src="http://techslides.com/demos/sample-videos/small.mp4" controls></video> </body> </html> و إذا أردت أن تضع فيديو من الجهاز الخاص بك, لتسهيل الأمر جرب أن تضع الفيديو في نفس مسار ملف ال HTML هكذا. يمكنك معرفة الكثير عن هذا الوسم من خلال موسوعة حسوب العنصر <video> - موسوعة حسوب (hsoub.com).1 نقطة
-
إذا أردت استضافة مجانية أو حتي بسعر معقول أنصحك بأستضافة Render. Render هو مزود خدمة استضافة الويب متخصص في تقديم حلول استضافة منخفضة التكلفة وسهلة الاستعمال. يوفر Render حلول استضافة مناسبة لمستخدمين المبتدئين والمتقدمين. يعرض Render أسعار مناسبة (حيث تبدأ من 19 دولار) . يوفر Render أيضا إمكانية التعامل مع التقنيات مثل البروتوكول SSL, SSH, MySQL, PostgreSQL, PHP, Python, Node.js والعديد من البرامج والتطبيقات الاخرى. ويمكنك معرفة كيفية رفع مشروع Next.js علي Render من هنا. وأسعار الاستضافة من هنا.1 نقطة
-
في البداية إذا أردت التحكم في جهازك عن بعد فقط، فيمكنك استخدام برامج مثل TeamViewer وتركها تعمل على الجهاز والدخول عليه بواسطة الـ IP وباستطاعتك تعيين كلمة سر. أما تحويل جهازك إلى سيرفر عام يمكن أن يتم باستخدام بعض البرامج المجانية التي تمكنك من إعداد خادم على جهازك الخاص وجعله متاحًا للوصول من أي جهاز آخر على شبكة الإنترنت. سأشرح لك الخطوات الأساسية اللازمة لتحقيق ذلك: 1- تثبيت برنامج خادم الويب: يمكن استخدام أي برنامج خادم ويب مثل XAMPP أو WAMP أو Apache أو laragon لإنشاء خادم ويب. يوفر هذا البرنامج خادم ويب وقاعدة بيانات و PHP. يمكنك تنزيل البرنامج من موقع الويب الرسمي وتثبيته على جهازك. 2- اختبار الويب سيرفر: يجب التأكد من أن الويب سيرفر يعمل بشكل صحيح على جهازك. يمكن القيام بذلك عن طريق فتح متصفح وزيارة localhost. 3- تعيين عنوان IP ثابت لجهازك: تعيين عنوان IP الثابت يعني تحديد عنوان الإنترنت الخاص بجهاز الكمبيوتر الخاص بك بشكل دائم، والذي يتم تعيينه يدويًا. يختلف هذا عن العنوان الديناميكي الذي يتم تعيينه تلقائيًا عند الاتصال بالإنترنت. بعد تثبيت برنامج الخادم الخاص بك، سيكون من الضروري تعيين عنوان IP الثابت لجهاز الكمبيوتر الخاص بك، حيث يمكن استخدام هذا العنوان للوصول إلى جهاز الكمبيوتر الخاص بك عبر الشبكة. ومن أجل ذلك يمكنك العثور على إعداد تعيين العنوان الثابت في قسم الشبكة في إعدادات جهاز الكمبيوتر الخاص بك. 4- إعداد المنافذ اللازمة: يجب فتح المنافذ الخاصة بالويب سيرفر على جدار الحماية الخاص بالجهاز، للسماح لأي شخص في الشبكة بالوصول إلى الويب سيرفر. يجب فتح المنافذ 80 لبرتوكول HTTP و 443 لبروتوكول HTTPS. سأشرح الخطوات اللازمة لفتح المنافذ على راوتر من نوع TP-Link Archer C7. تسجيل الدخول إلى لوحة التحكم الخاصة بالراوتر: افتح متصفح الويب الخاص بك واكتب عنوان IP الافتراضي الخاص بالراوتر في شريط العنوان (عادةً ما يكون 192.168.0.1 أو 192.168.1.1). سيطلب منك إدخال اسم مستخدم وكلمة مرور لتسجيل الدخول إلى لوحة التحكم. الوصول إلى قسم إعدادات المنافذ: بمجرد تسجيل الدخول إلى لوحة التحكم، انتقل إلى قسم "Advanced" (متقدم) ثم اختر "Port Forwarding" (توجيه المنافذ). إضافة إعدادات التوجيه: اختر "Add New" (إضافة جديدة) لإنشاء إعدادات التوجيه الجديدة. سيطلب منك تحديد اسم الجهاز (عادةً ما يكون اسم الخادم) وعنوان IP الخاص بالجهاز (عنوان IP الثابت الذي قمت بتعيينه سابقًا) ورقم المنفذ الداخلي والخارجي. حفظ الإعدادات: بعد إدخال جميع التفاصيل اللازمة، انقر على "Save" (حفظ) لحفظ الإعدادات الجديدة. ستحتاج إلى تكرار هذه الخطوات لإضافة إعدادات توجيه منفذ إضافية. التأكد من البورتات التي تم فتحها من خلال التوجه لموقع https://portchecker.co/checking وستجد أنه تعرف على الـ public IP الخاص بجهازك ما عليك سوى كتابة بورت 80 ثم اضغط على check وكرر نفس الأمر مع بورت 443 وتأكد من ظهور كلمة port x is open. من المهم ملاحظة أن إعدادات توجيه المنافذ يمكن أن تختلف قليلاً بين الراوترات المختلفة، ومن المهم أيضًا إتباع الإرشادات الخاصة بالراوتر الخاص بك للتأكد من تمكين توجيه المنافذ بطريقة صحيحة. 5- تفعيل خدمة DNS: بعد الانتهاء من إعداد إعدادات الراوتر وتحديد عنوان IP الخاص بالجهاز الخادم، يمكنك استخدام DNS لتسهيل عملية الوصول إلى الخادم. يمكنك استخدام خدمات DNS المجانية مثل No-IP أو DynDNS لتسجيل عنوان IP الخاص بالخادم الخاص بك وربطه بعنوان URL سهل الاستخدام. وسبب القيام بتلك الخطوة هو ربط الـ public IP باسم دومين أو عنوان URL يمكنك كتابته والدخول على جهازك عن بعد، فربما بعد إعادة تشغيل الراوتر قد يتغير الـ public IP، ويمكنك الحصول من مزود الخدمة على static IP. الخطوات لاستخدام DNS هي كالتالي: قم بإنشاء حساب على موقع خدمة DNS المختارة والأفضل No-IP لكونها مجانية. أدخل اسم النطاق الذي تريد استخدامه واتبع التعليمات لربط عنوان IP الخاص بالخادم بالاسم المستخدم في النطاق. تأكد من تحديث إعدادات الراوتر الخاص بك للسماح بمرور حركة المرور المرتبطة بـ DNS من الخارج إلى الجهاز الخادم. قم بتنزيل برنامج العميل الذي يقدمه موقع خدمة DNS المختارة وتثبيته على الجهاز الخادم. سيتم تشغيل هذا البرنامج في الخلفية وسيقوم بتحديث عنوان IP الخاص بالخادم بشكل دوري. يمكنك الآن الوصول إلى الخادم باستخدام عنوان URL المحدد لخدمة DNS المستخدمة.1 نقطة
-
هناك العديد من الخيارات المتاحة لاستضافة تطبيقات Next.js على الإنترنت، ويمكن الاختيار بين خيارات مثل: Vercel: هي منصة استضافة خاصة بـ Next.js وتوفر دعمًا متميزًا لهذه التقنية وتقدم خدمة الاستضافة بشكل مجاني ومدفوع، وتسمح لإضافة عدد غير محدود من النطاقات. namecheap: تدعم شركة Namecheap استضافة تطبيقات Next.js وتوفر خيارات متعددة للخوادم المشتركة والخوادم الخاصة بأسعار مناسبة. يمكنك اختيار خطة استضافة تناسب احتياجاتك وميزانيتك، مع توفير خيارات متعددة للدفع ودعم فني متاح على مدار الساعة. Heroku: هي خدمة استضافة تدعم تقنية Node.js وتتميز بأنها سهلة الاستخدام وتوفر خدمة مدفوعة ومجانية. DigitalOcean: هي خدمة استضافة توفر خيارات متعددة للاستضافة بدءًا من الخوادم الافتراضية حتى الخوادم الخاصة والاستضافة المدارة، وتوفر دعمًا لتقنية Node.js و Next.js، ويمكن إضافة عدد غير محدود من النطاقات. AWS Elastic Beanstalk: هي خدمة استضافة توفر دعمًا لتقنية Node.js و Next.js، وتسمح بإضافة عدد غير محدود من النطاقات، وتعتمد على سحابة Amazon Web Services (AWS)، وتوفر خيارات متعددة للتكوين والتوسع. Google Cloud Platform: هي خدمة استضافة توفر دعمًا لتقنية Node.js و Next.js، وتسمح بإضافة عدد غير محدود من النطاقات، وتتميز بأنها سهلة الاستخدام وتقدم خدمة مجانية ومدفوعة. Cloudflare Pages: يمكن لـ Cloudflare Pages دعم عدة نطاقات لتطبيق واحد، وتوفر خدمة CDN مدمجة لتحسين أداء التطبيقات، بالإضافة إلى أنها توفر عمليات نشر بسيطة وسهلة الاستخدام. وتوفر Cloudflare Pages خيارات دفع مختلفة مثل الاشتراك الشهري أو الدفع مقابل الاستخدام بأسعار تنافسية بالمقارنة مع خدمات الاستضافة الأخرى. Netlify: تعتبر Netlify مثالية للاستضافة السريعة والبسيطة لتطبيقات Next.js. توفر خططًا مجانية ومدفوعة ، ولكن يمكن أن تكون الخطط المدفوعة أكثر تكلفة. Linode: توفر Linode خدمة VPS مع خطط متعددة بأسعار مختلفة. تدعم Node.js ويمكن استخدامها لتشغيل تطبيقات Next.js. توجد العديد من الخيارات المتاحة لاستضافة تطبيقات Next.js، والخيار الأفضل يعتمد على ميزانيتك واحتياجاتك الفردية. من بين الخيارات التي تم ذكرها، Vercel هي الخيار الأكثر تخصصاً لاستضافة تطبيقات Next.js، وتقدم خدمة استضافة مدفوعة ومجانية مع دعم لإضافة عدد غير محدود من النطاقات.1 نقطة
-
ممتاز، تعلم HTML و CSS هو الخطوة الأولى لتصميم وتطوير صفحات الويب، ولكن هناك الكثير من التقنيات والأدوات المختلفة التي يجب أن تتعلمها لتكون مطور ويب محترف. HTML و CSS ليستا لغات برمجة، إنما هما لغتان تستخدمان لتطوير صفحات الويب. HTML هي لغة ترميز النصوص التي تستخدم لتحديد هيكل صفحات الويب، بينما تستخدم CSS لتحديد التنسيقات والأساليب الجمالية لعرض محتوى الصفحة. بينما لغة JavaScript تعتبر لغة برمجة مستخدمة بشكل شائع في تطوير صفحات الويب وتطبيقات الويب. يمكن استخدام JavaScript لتوفير العديد من المزايا لصفحات الويب، بما في ذلك تحديث المحتوى ديناميكيًا وتفعيل العناصر التفاعلية. لذلك، إذا كان الشخص يرغب في تطوير صفحات الويب التفاعلية والديناميكية، فسيحتاج بالتأكيد إلى تعلم JavaScript. ولكن إذا أردت أن تأسيس نفسك بشكل قوي في البرمجة ولديك وقتٍ كافي لذلك، فأنصحك بفعل ذلك وبشدة والإتجاه نحو تعلم لغة C++ قبل تعلم JavaScript. وإذا أردت تعلم مجال الويب، إليك مسارًا كاملاً لتصبح مطور Full-stack لتتمكن من إنشاء مشروع كاملاً بمفردك: JavaScript: هي لغة برمجة تستخدم عادة لتطوير وظائف تفاعلية في صفحات الويب، مثل التحقق من الإدخالات وإضافة تأثيرات متحركة. لتعلم JavaScript. Bootstrap: هي إطار عمل لتصميم صفحات الويب تستخدمه العديد من المواقع الكبيرة، والذي يسهل عليك عملية تصميم الصفحات وجعلها تستجيب بشكل جيد على جميع الأجهزة المختلفة. tailwindcss: يمكنك تعلم tailwindcss بدلاً من Bootstrap فهى توفر مرونة أكبر في تخصيص التصميم وإعادة استخدام الأكواد في العديد من المشاريع المختلفة، حيث يمكن للمطورين تعريف مخصصاتهم الخاصة واستخدامها في أي مكان داخل التطبيق. Sass: هي لغة تعتمد على CSS، وتستخدم لتبسيط عملية كتابة الأنماط والتنسيقات في CSS، وتحسين إمكانية إعادة استخدام الشفرة. Git: هو نظام للتحكم في الإصدارات يستخدم لتتبع التغييرات في الشفرة المصدرية وإدارة تعاون فريق العمل على المشاريع. تعلم إطارات العمل (Frameworks): تعتبر إطارات العمل مجموعة من الأدوات والمكتبات التي تساعد المطورين في إنشاء تطبيقات الويب بسهولة وسرعة. بعض الإطارات الشائعة هي React.js و Angular و Vue.js. إطارات العمل الخاصة بالـ Back-End: يمكن استخدام إطارات العمل الخاصة بالـ Back-End مثل Node.js وإطار العمل الخاص بها Express.js لبناء تطبيقات ويب ديناميكية وقابلة للتوسع. تتيح هذه الإطارات العديد من المزايا مثل: القدرة على التعامل مع البيانات وقواعد البيانات باستخدام لغة جافاسكريبت على الجانب الخادم. القدرة على بناء API للتفاعل مع التطبيقات الأخرى وتوفير خدمات ويب. 8 - قواعد البيانات: يجب تعلم قواعد البيانات الحديثة والشائعة مثل MySQL أو MongoDB أو PostgreSQL. لتعلم العمل مع إطارات العمل الخاصة بالـ Back-End، يمكن البدء بتعلم الأساسيات في لغة جافاسكريبت ومفاهيم البرمجة الأساسية. بعد ذلك يمكن التحول إلى تعلم إطار العمل Node.js و Express.js، والتعلم عن كيفية التعامل مع البيانات والاتصال بقاعدة البيانات. من المهم أيضًا التعلم عن كيفية بناء API وتصميمها بشكل صحيح لتوفير خدمات ويب عالية الجودة وآمنة. يجب أيضًا تعلم الأمان والحماية وكيفية التعامل مع الأخطاء والأخطار المحتملة في تطوير تطبيقات الويب.1 نقطة
-
كما أخبرك عمر في التعليق السابق فإنه يجب ان تقوم بالمقارنة بنفسك من خلال البحث عن الإستضافات التي تدعم nextjs ومن هذه الإستضافات AWS Amplify Digital Ocean Heroku Google Cloud Run Cloudflare Pages سيكون من الصعب ذكر حلول الاستضافة المتاحة لمشاريع Next.js دون ذكر Vercel حيث يعتبر من أفضل الحلول لإستضافة مواقع nextjs.1 نقطة
-
حتى تصبح مطور frontend محترف يجب عليك دراسة لغة javascript وليس java حيث هذه لغة تختلف عن الأخرى وعامة عند دراسة الويب يجب عليك دراسة لغة javascript حيث تعتبر اللغة الأساسية لتطوير مواقع الويب سواء ال frontend أو ال backend حيث تستعمل لإعطاء بعض عناصر الصفحة صفاتٍ تفاعلية، مثل شريط متحرك من الصور أو قوائم تظهر عند وقوع حدث معيّن ...إلخ. ويمكنك التعرف على مجال الويب والتقنيات واللغات المستخدمة من خلال المقالة التالية وقم بقراءة الإجابات على هذا السؤال للمزيد من المعلومات1 نقطة
-
تعرفنا في المقال السابق على مفهوم الدوال وكيف يمكن للمبرمج تعريف دوال مخصصة ولكن لا يحتاج المبرمج إلى تعريف كل الدوال بنفسه من الصفر بل توجد الكثير من الدوال المدمجة بالفعل في اللغة افتراضيًا تسمى Built-in Functions أي دوال مدمَجة، وأفضل الأمثلة عليها هي دالة الطباعة print الموجودة افتراضيًا في بايثون، وسنذكر في هذا الفصل أهم هذه الدوال وأمثلة على استخدامها. دوال التعامل مع الأوقات والأزمنة في بايثون يُتعامَل مع الأوقات والتواريخ في كثير من برامج الحاسوب بصورة ضرورية، فلا غنى عن التعامل مع التواريخ والأوقات في برمجة الكثير من التطبيقات، إذ تعتمد الكثير من التطبيقات عليها، فهاتفك مثلًا يحتوي على تطبيقات تستخدِمها يوميًا مثل تطبيق المنبه، والذي يعتمد بصورة أساسية على التعامل مع التواريخ والأوقات، كما توجد الكثير من المهام التي من الممكن استخدام دوال التعامل مع الأوقات فيها، فمثلًا قد نودّ متابعة وتسجيل عدد الثواني التي يستخدِمها الحاسوب في تنفيذ كتلة شيفرة معيّنة لقياس سرعة تنفيذ البرنامج. توجد في بايثون بعض الوحدات Modules التي تُستخدَم عند التعامل مع الأوقات والتواريخ، سنبدأ أولًا بوحدة الوقت التي تُدعى time وهي تحتوي على الكثير من الدوال المفيدة للتعامل مع الوقت وسنذكر بعضًا منها. ملاحظة: يُحسَب في بايثون وفي كثير من لغات البرمجة وقت الثانية الحالية حسب فترة بُعدها بالثواني عن الساعة 12 صباحًا يوم 1 من شهر 1 عام 1970م، وهو نظام متعارف عليه، إذ يُعَدّ ذلك التاريخ نقطة انطلاق ما يُدعى بوقت يونكس Unix أو Unix Epoch. دالة time يمكننا تحديد رقم الثانية الحالية باستخدام الدالة time الموجودة في الوحدة time، إذ سنطبع في المثال التالي الوقت الحالي كما يلي: import time print (time.time()) >> 1592952455.39395 ستلاحظ في كل مرة يُنفَّذ المثال أعلاه أن العدد يزيد بفرق عدد الثواني بين التنفيذ الثاني والتنفيذ الأول، والجدير بالذكر أنّ الثانية في تلك القاعدة يُطلق عليها بالإنجليزية لقب Tick، وحسب تلك القاعدة فإنه يعبَّر عن التاريخ حسب عدد الثواني، إذ يمثِّل العدد الموجب عدد ثواني المارة على تاريخ 1/1/1970؛ أما العدد السالب، فيُمثِّل عدد الثواني المطلوبة للوصول إلى وقت يونكس أي تاريخ 1 شهر 1 عام 1970م في حال تعاملنا مع تاريخ قديم، ولفهم ما نعنيه يمكن تخيُّل تاريخ وقت يونكس هو نقطة الصفر بحيث تمثِّل القيمة الموجبة ما بعد ذلك التاريخ؛ أما القيمة السالبة، فتمثِّل ما قبل ذلك التاريخ كما في الصورة التالية: إضافة: ستكون أيّ قيمة في وقتنا الحاضر وفي المستقبل قيمةً موجبةً، لكن مع ذلك فإنّ الأرقام الصحيحة التي تعبِّر عن عدد الثواني محدودةً في أنظمة التشغيل، وبالتالي توجد مشكلة تدعى مشكلة عام 2038، إذ أنه في تمام يوم الثلاثاء الموافق للتاسع عشر من شهر 1 من ذلك العام ستتوقف الأنظمة عن العمل بذلك النظام لأنه لن تستوعب العدد الكبير من الثواني آنذاك. دالة localtime يمكننا في بايثون معرفة التاريخ الحالي عبر دالة localtime وفي المثال الآتي نوضِّح كيفية استخدامها. import time print (time.localtime()); >> time.struct_time(tm_year=2020, tm_mon=6, tm_mday=24, tm_hour=23, tm_min=23, tm_sec=55, tm_wday=2, tm_yday=176, tm_isdst=0) نلاحظ أنّ الدالة تُنتج صنف time.struct_time، ويمكننا استخراج بيانات التاريخ وطباعتها من الدالة السابقة عبر معاملة الكائن الناتج عن الدالة كونه صنفًا، إذ يكون العنصر الأول هو العام، والعنصر الثاني هو رقم الشهر، والعنصر الثالث هو رقم اليوم، والعنصر الرابع هو الساعة، والعنصر الخامس هو الدقيقة، والعنصر السادس هو الثواني، والعنصر السابع هو رقم اليوم في الأسبوع، والعنصر الثامن هو رقم اليوم في السنة، ولطباعة العام يجب طباعة العنصر الأول كما يلي: print (time.localtime()[0]); >> 2020 ولطباعة الشهر مثلًا يجب طباعة العنصر الثاني كما يلي: print (time.localtime()[1]); >> 6 وهكذا. دالة asctime تكوّن هذه الدالة التاريخ بصورة مقروءة وتتطلب معاملًا واحدًا ومن الممكن أن يكون من نوع time.struct_time، لذلك نستطيع ببساطة تمرير ناتج دالة localtime على أساس معامِل في هذه الدالة، ففي المثال الآتي نطبع التاريخ والوقت الحاليين بصورة مقروءة باستخدام الدالتين السابقتين: import time print (time.asctime(time.localtime())); >> Wed Jun 24 23:41:30 2020 دالة sleep توقف الدالة sleep عمل البرنامج لبرهة من الزمن تُحدَّد بعدد من الثواني تُمرَّر على أساس معامِل وحيد في الدالة، ففي المثال التالي سيُطبَع الاسم Adam في بداية تشغيل البرنامج ثم سيتوقف البرنامج عشرة ثوانٍ ثم يطبع الاسم Noah: import time print ('Adam') time.sleep(10) print ('Noah') >> Adam >> Noah دوال التعامل مع التواريخ في بايثون سنتعرف على بعض الدوال البسيطة والمفيدة في التعامل مع التواريخ. دالة month تطبع التقويم الميلادي لشهر محدد في سنة محددة عبر المعامِلات التي تستقبلها الدالة، فالمعامل الأول المطلوب في الدالة هو العام؛ أما المعامل الثاني فهو رقم الشهر، إذ يمكننا عبر المثال التالي طباعة تقويم شهر 1 من عام 2019م: import calendar print (calendar.month(2019, 1)) >> January 2019 Mo Tu We Th Fr Sa Su 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 دالة today توجد في بايثون وحدة datetime والتي تحتوي على الكثير من الخصائص والدوال منها الدالة today. نستطيع استخدام الدالة today لطباعة تاريخ اليوم، ففي المثال الآتي نستورد الصنف date من الوحدة datetime ثم نستخدِم دالة today الموجودة بداخلها. from datetime import date print (date.today()) >> 2020-06-25 دالة isleap تتحقق هذه الدالة من كون السنة المحدَّدة في معاملها سنةً كبيسةً أم لا، إذ نتحقق في المثال التالي من سنة 2019: import calendar print (calendar.isleap(2019)) >> False الإجابة كما نرى في المثال هي خطأ False وبالتالي هي ليست سنةً كبيسةً، ومن المُمكن استخدام تلك الدالة في الجمل الشرطية، إذ تستطيع في تلك الحالة تنفيذ كتلة شيفرة معينة في السنة الكبيسة دونًا عن السنوات الأخرى أو العكس. دالة leapdays تحسب هذه الدالة عدد الأيام الكبيسة في نطاق عدد سنوات يُحدَّد عبر تمرير معاملين فيها بحيث يحتوي المعامِل الأول على عام بداية النطاق؛ أما المعامل الثاني فيحتوي على عام نهاية النطاق، فإذا أردنا مثلًا معرفة عدد الأيام الكبيسة منذ عام 1990م حتى عام 2019م، فسيكون كما في المثال التالي: import calendar print (calendar.leapdays(1990, 2019)) >> 7 توجد في كل من الوحدات time و calendar و datetime السالف ذكرها الكثير من الدوال والخصائص الأخرى التي لا يتسع الفصل لذكرها، ويمكنك الرجوع إلى توثيقها في موسوعة حسوب لمزيد من التفاصيل. دوال التعامل مع الملفات في بايثون تُعَدّ معرفة الدوال والأمور الخاصة بالتعامل مع الملفات في بايثون من الموضوعات الضرورية أيضًا، إذ يصبح من الضروري قراءة محتويات الملفات التي تحتوي على بيانات المشروع أثناء برمجة الكثير من المشاريع وأهمها مشاريع تعلم الآلة. ملاحظة: لا تُستخدَم دوال التعامل مع الملفات المدمجة غالبًا بصورة افتراضية في بايثون في مشاريع تعلُّم الآلة، وذلك لأن معظم ملفات تلك المشروعات هي ملفات بصيغة CSV أو ما شابه، وهي ملفات من الأفضل قراءة محتواها عبر مكتبات متخصصة لذلك النوع، ولكن مع ذلك فإنه من المُستحسن معرفة بعض تلك الدوال المدمجة وإمكاناتها، إذ أنها قد تكون مفيدةً في بعض البرامج. الدالة read قبل القراءة من ملف أو الكتابة فيه، يجب استخدام الدالة open الأساسية المستخدَمة في فتح الملفات، وهي دالة تطلب معاملَين اثنين، الأول هو مسار الملف، والثاني هو ما يُدعى بوضع الوصول Access Mode، وهو قيمة مكونة من رمز مأخوذ من مجموعة رموز محددة كل منها يعبِّر عن وضع وصول معيّن، إذ تحدِّد أوضاع الوصول ما يمكن فعله وما لا يمكن فعله عند فتحك ملفًا ما، فقد تتيح بعض لك أوضاع الوصول قراءة المحتويات فقط، وأخرى تتيح لك القراءة من والكتابة في الملف وأخرى تتيح لك كتابة محتوى فقط دون قراءة للمحتوى، إذ تختلف أوضاع الكتابة، فتكتب بعض الأوضاع المحتوى من أول الملف، في حين تكتب أوضاع أخرى المحتوى في نهاية الملف، بالإضافة إلى الكثير من التفاصيل الأخرى التي يعبِّر عنها كل رمز من الرموز. لنبدأ بمثال بسيط، يمكننا إنشاء ملف نصي بسيط بجوار الملف الرئيسي للبرنامج باسم file.txt، ولنكتب شيفرة مهمتها قراءة محتوى الملف وطباعته، ولتحقيق ذلك لا نحتاج إلى استيراد أية مكتبات لأن الدالة مدمجة بالفعل. file = open ('file.txt') print (file.read()) >> The file content استخدمنا في المثال السابق الدالة open لقراءة الملف دون تمرير معامل ثان لها وهو معامل الوصول بوضع القراءة افتراضيًا، وقد أنشأت بذلك كائنًا يحتوي على الكثير من الدوال، منها الدالة التي تتيح قراء المحتوى النصي وهي الدالة read. الدالة write كما يمكننا أيضًا كتابة محتوًى في الملف بتغيير رمز وضع الوصول إلى w، ثم استخدام الدالة write لإدخال نص وحفظه في الملف كما يلي: file = open ('file.txt', 'w') file.write('New file content') ستُحذَف جميع محتويات الملف النصي بعد تنفيذ ذلك البرنامج، ويُغيَّر بالمعامل الأول في دالة write، والجدير بالذكر أنّ الرمز w يتيح الكتابة في الملفات فقط ولا يتيح قراءة المحتويات. الدالة close من الأفضل إغلاق المتغير الذي يحتوي على الملف بعد إنهاء المهمات المُراد تنفيذها على الملفات لكي تُلغى أيّة تعديلات غير منتهية ومن ثم إغلاق الملف، إذ لن يكون التعديل على الملف متاحًا بعد إغلاقه إلا إذا استُخدِمت الدالة open مرةً أخرى لفتح الملف، ويمكن إغلاق الملف باستخدام الدالة close الموجودة في متغير الملف كما في المثال التالي: file.close() الدالتان remove و rename توجد دالتان مهمتان هما دالة حذف الملفات remove ودالة إعادة تسمية الملفات rename، لكنهما متاحتان فقط بوجود مكتبة مستقلة للتعامل مع أنظمة التشغيل، وهي مكتبة os المُسماة بذلك اختصارا لكلمة Operating System، إذ يكون المعامل الوحيد للدالة الأولى التي تتيح حذف الملفات هو اسم الملف أو مساره بداخل المجلد الموجود فيه البرنامج؛ أما الدالة الثانية التي تتيح إعادة تسمية الملفات، فستطلب معاملين هما اسم الملف الحالي المُراد تعديله واسم الملف الجديد، إذ سنعيد في المثال التالي تسمية ملف موجود بجوار البرنامج. import os os.rename ('file.txt', 'file_renamed.txt') سيتغير بذلك اسم الملف بجوار البرنامج من file.txt إلى file_renamed.txt بدون طباعة أيّ كلمة عند تشغيل البرنامج. ملاحظة: من الضروري دائمًا معاملة صيغة الملف على أساس جزء من الاسم عند التعامل مع الملفات في بايثون وفي معظم لغات البرمجة. يوضِّح المثال التالي حذف الملف من الحاسوب تمامًا: import os os.remove ('file_renamed.txt') دوال التعامل مع النصوص في بايثون النص أو السلسلة النصية string في لغة بايثون عبارة عن سلسلة متتالية من الأحرف الموضوعة ضمن علامتي اقتباس مفردتين أو مزدوجتين ومن أهم الدوال المستخدمة للتعامل مع السلاسل النصية في بايثون نذكر: دالة str السلسلة النصية كما ذكرنا ما هي إلا سلسلة من الأحرف المتتالية ويمكنك الوصول إلى كل حرف منها باستخدام الدالة str [n] حيث يعبر n هنا عن موضع أو فهرس الحرف الذي تريد الوصول له، علمًا بأن فهرسة السلاسل النصية في بايثون تبدأ بالصفر أي أن فهرس الحرف الأول في السلسلة النصية يساوي صفر. لنأخذ مثالًا لتوضيح الأمر، سننشئ متغير يعبر عن السلسلة Python String وسنصل للحرفين الأول والثاني من السلسلة من خلال كتابة str[0] و str[1] كما يلي str = "Python String" print(str[0]) # P print(str[1]) # y ملاحظة: إذا كنت مررت قيمة سالبة للفهرس فإن بايثون تبدأ العد من نهاية السلسلة وتعيد لك الحرف الموافق وتبدأ الفهرسة في هذه الحالة بالقيمة 1- كما هو موضح في المثال التالي: str = "Python String" print(str[-1]) # g print(str[-4]) # r ويمكن الحصول على سلسلة فرعية من سلسلة نصية ما من خلال تمرير مجال من القيم للدالة على سبيل المثال للحصول على أول 6 أحرف من السلسلة النصية "Python String" نكتب الكود التالي: str = "Python String" print (str[0:6]) #Python كما تلاحظ من المثال أعلاه ستتضمن السلسلة الفرعية الناتج عن الأحرف من الدليل رقم 0 لغاية الدليل 5 وتستبعد الحرف ذو الدليل 6. ويمكنك حذف قيمة فهرس البداية ليتم تعيينها افتراضيًا على الصفر أو حذف قيمة فهرس النهاية ليتم تعيينها افتراضيًا على طول السلسلة الكامل. str = "Python String" print (str[:6]) # Python print (str[7:]) # String دالة len تستعمل الدالة len للحصول على طول السلسلة النصية أي عدد حروفها، على سبيل المثال الشيفرة التالية تعيد القيمة 13 str = "Python String" str_len = len(str) print(str_len) دوال التعامل مع القوائم والمصفوفات في بايثون تعد كل من القوائم lists والمصفوفات arrays بنى بيانات في بايثون قادرة على تخزين عناصر متعددة في متغير واحد. والفرق الأساسي بين القوائم والمصفوفات هو أن القائمة تتكون من عناصر تنتمي إلى أنواع بيانات مختلفة في حين تتكون المصفوفة من عناصر تنتمي إلى نفس نوع البيانات. توفر بايثون الكثير من الدوال التي تتعامل مع القوائم والدوال وفيما يلي نتعرف على أهم هذه الدوال: دالة append تضيف الدالة append عنصرًا واحدًا إلى نهاية القائمة، يمكن أن يكون العنصر نفسه قائمة، لاحظ الأمثلة التالية fruits = ['apple', 'banana', 'cherry'] vegetables = ["cabbage", "tomato", "cucumber"] fruits.append("orange") print(fruits) #['apple', 'banana', 'cherry', 'orange'] fruits.append(vegetables) print(fruits) #['apple', 'banana', 'cherry', 'orange', ['cabbage', 'tomato', 'cucumber']] دالة clear الدالة clear دالة بسيطة لا تحتاج لأي وسطاء وتقوم بحذف كل العناصر من القائمة وتعيد قائمة فارغة. fruits = ["apple", "banana", "cherry"] fruits.clear() print(fruits) #[] دالة count تعيد الدالة count عدد المرات التي ورد فيها عنصر ما في القائمة، على سبيل المثال لإعادة عدد مرات ورود اسم معين في قائمة من الأسماء أو رقم محدد في سلسلة أرقام نكتب الكود التالي names = ['Ali','OLA','Ahmad','Ali','Mohammed','Ali',] num=names.count("Ali") print(num) #3 points = [1, 3, 2, 9, 7, 8, 9, 3, 1] x = points.count(3) print(x)#2 دالة extend تلحق الدالة extend قائمة جديدة أو أي بنية معطيات أخرى مكونة من عدة عناصر إلى نهاية القائمة الحالية fruits = ['apple', 'banana', 'cherry'] vegetables = ["cabbage", "tomato", "cucumber"] points = (1, 4, 5, 9) fruits.extend(vegetables) print(fruits) #['apple', 'banana', 'cherry', 'cabbage', 'tomato', 'cucumber'] دالة index تعيد الدالة index فهرس العنصر في القائمة كل ما عليك هو تمرير قيمة العنصر الذي تريد البحث عنه في السلسلة وستعيد لك الدالة دليل أو ظهور له ضمن القائمة، وتذكر أن فهرس أول عنصر في القائمة هو 0. لاحظ المثال التالي: names = ['Myriam ', 'Ali', 'Mohammed', 'Ahmad','Salah'] i=names.index('Ahmad') print(i) #3 دالة insert تقوم الدالة insert بإضافة عنصر إلى موضع محدد في القائمة على سبيل المثال إذا كان لدينا قائمة بأسماء وعلامات الطلاب ونسينا إضافة علامة الطالب الثاني في القائمة يمكن استخدام الدالة لإضافتها ببساطة كما يلي students = ['Ali', 90, 'Ahmad', 'Salah', 80] students.insert(3, 76) print(students) #['Ali', 90, 'Ahmad', 76, 'Salah', 80] دالة pop تحذف الدالة pop عنصر له فهرس محدد من القائمة ويمكن أن تعيد لنا العنصر المحذوف كما في المثال التالي fruits = ['apple', 'banana', 'cherry'] x = fruits.pop(1) print(fruits) #['apple', 'cherry'] print(x) #banana دالة remove تحذف الدالة عنصر له فيمة محددة من القائمة وفي حال تكررت القيمة أكثر من مرة في القائمة ستحذف الدالة أول ورود للقيمة وتترك القيم الباقية. names = ['Ali','OLA','Ahmad','Ali','Mohammed','Ali',] names.remove("Ali") print(names) #['OLA', 'Ahmad', 'Ali', 'Mohammed', 'Ali'] دالة reverse تعكس الدالة ترتيب عناصر القائمة numbers = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] numbers.reverse() print(numbers) #[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] دالة sort ترتب الدالة sort عناصر القائمة وفق التسلسل الأبجدي وهي تفرز العناصر تصاعديًا بشكل افتراضي كما يمكن تمرير وسيط اختياري reverse وإعطاؤه القيمة True لجعل الدالة تغير طريقة عملها وتفرز عناصر القائمة تنازليًا على سبيل المثال لترتيب مجموعة من الأسماء أبجديًا نكتب الشيفرة التالية names = ['OLA', 'Ahmad', 'Mohammed'] names.sort() print(names) # ['Ahmad', 'Mohammed', 'OLA'] names.sort(reverse=True) print(names) # ['OLA', 'Mohammed', 'Ahmad'] ويمكن كذلك تغيير طريقة الترتيب من خلال تمرير قيمة مفتاح key يحدد المعيار الذي تود فرز العناصر وفقه، على سبيل المثال لترتيب الأسماء حسب طولها أو عدد أحرفها من الأقل للأكثر سنعرف دالة تحسب طول السلسلة النصية ثم سنمررها كقيمة مفتاحية لدالة الترتيب كما يلي: def myFunc(e): return len(e) names = ['Ahmad', 'Ali', 'Mohammed'] names.sort(key=myFunc) print(names) #['Ali', 'Ahmad', 'Mohammed'] هذه كانت نبذة سريعة عن أهم الدوال الأساسية في الدوال المدمجة في لغة بايثون، ويمكنك التعرف على مزيد من التفاصيل حول الدوال المدمجة في لغة بايثون بالاطلاع على توثيق لغة بايثون باللغة العربية الذي وفرته لك موسوعة حسوب. اقرأ أيضًا المقال السابق: مفهوم الدوال Functions في البرمجة تعرف على الدوال (Functions) في بايثون الدوال الرياضية المضمنة في بايثون 3 كيفية تعريف الدوال في بايثون 31 نقطة
-
من خلال تجربتي فأفضل المواقع هي namecheap.com من ناحية الفلوس، حيث تدعم الاستضافة المشتركة الارخص لديهم رفع ثلاث مواقع وتدعم node js أي وبالتالي تدعم الـ next. وفي حال لم تكن مشاريعك بتلك الضخامة والشعبية يمكنك رفعها على vercel بشكل مجاني. بعد قول ذلك فأنصحك بالبحث عن الاستضافات التي تدعم next في 2023 وان تقوم بالمقارنة بنفسك حتى يصبح لديك خبرة اكبر عن مواقع الاستضافات.1 نقطة
-
تأكدت من المسار عشرات المرات ساتوقف عن المحاولة واترك هذا الالمنت شكرا على المساعدة1 نقطة
-
هناك أكثر من طريقة أحدها أن تبني التطبيق الخاص بك بحيث تكون الstate الرئيسية موجودة على ال component الرئيسي الحاوي لجميع الcomponents الفرعية أي البناء بشكل هرمي وتعرف في component الرئيسي دالة تعديل الstate والتي تمرره بمعية الstate الى كل component فرعي. المثال التالي يوضح الفكرة بشكل أفضل ... const SubComponentOne = (props)=> { // مكون فرعي const [state, setState]= useState(props.mainState) const changeName(event)=>{ // عند تغيير النص في صندوق الإدخال سيتم التغيير على حالة التخزين الرئيسية التي ستعكس التغيير على كافة الفروع const name= event.target.value props.setState({name}) // هنا يتم التغيير على حالة المكون الرئيسي } return( <div> <span>{state.name}</span> <input onChange={changeName} defaultValue={''} /> </div> ) } const App = ()=> { // مكون رئيسي const [mainState, setState]= useState({name:"Main"}) return( <> <SubComponentOne setState={setState} mainState={mainState}/> // مكون فرعي <SubComponentTwo setState={setState} mainState={mainState}/> // مكون فرعي أخر </> ) } ...1 نقطة
-
بعد أن تعرّفنا في الدّرس السابق على أساسيات البرمجة كائنية التوجّه، سنُكمل في هذا الجزء ما بدأناه وسنتعلّم بعض المبادئ المتقدّمة حول البرمجة كائنيّة التّوجه. تغيير قيمة متغير الصنف في الدّرس السّابق تعلّمنا كيفيّة تعريف مُتغيّر داخل صنف وكيفيّة الوصول إليه، في هذا الجزء من هذا الدّرس سنتعرّف على كيفيّة استخدام هذه المُتغيّرات بشكل أكثر واقعيّة، لنقل مثلا بأنّنا نمتلك صنفًا باسم Car (سيارة)، ونريد أن ننشئ كائنات من هذا الصّنف، بحيثُ يكون لكل كائن قيم مُختلفة لمُتغيّرات الصّنف، انظر ما يلي: class Car: name = None speed = 0 brand = None def specs(self): print '{} speed is {}Km/h and it\'s brand is {}'.format(self.name, self.speed, self.brand) أنشأنا أعلاه صنفا بسيطا باسم Car مع ثلاثة مُتغيّرات name لاسم السّيارة، speed لسرعة السّيارة و brand لاسم العلامة التّجاريّة، كلمة None تُشير إلى أنّ المُتغيّر مُعرّف لكنّه لا يحمل أية قيمة. بعدها عرّفنا تابعا specs (اختصار لـ specifications) لطباعة مواصفات السّيارة. لننشئ كائنات مُتعدّدة من الصّنف الذّي كتبناه للتو. # Toyota Corolla corolla = Car() corolla.name = 'Toyota Corolla' corolla.speed = 200 corolla.brand = 'Toyota' # Ford Focus focus = Car() focus.name = 'Ford Focus' focus.speed = 220 focus.brand = 'Ford' # Honda Civic civic = Car() civic.name = 'Honda Civic' civic.speed = 210 civic.brand = 'Honda' بعد أن أنشأنا الصّنف والكائنات المندرجة تحت هذا الصّنف، وقمنا بتعيين قيم المُتغيّرات التي تُعتبر مواصفات كلّ سيارة، يُمكننا أخيرا طباعة مواصفات كل سيارة (كائن) وذلك باستدعاء التابع specs. corolla.specs() focus.specs() civic.specs() وكما تتوقّع، المُخرج سيكون كالتّالي: Toyota Corolla speed is 200Km/h and it's brand is Toyota Ford Focus speed is 220Km/h and it's brand is Ford Honda Civic speed is 210Km/h and it's brand is Honda إرجاع الصنف داخل تابع يُمكنك أن تقوم بكتابة تابع داخل صنف، بحيث يقوم التابع بتنفيذ شيفرة ما ثمّ إعادة الصّنف نفسه (ما نُشير إليه بالكلمة self) وبهذا ستتمكّن من استدعاء التابع أكثر من مرّة في سطر واحد، تأمل ما يلي: class Car: def start(self): print 'Starting engine…' return self ما فعلناه في الشّيفرة أعلاه ليس بالشيء الكثير، أولا نقوم بتعريف الصّنف ثمّ بعد ذلك نُعرّف التّابع start المسؤول عن تشغيل السّيارة، وبعدها نطبع جملة تُفيد بأنّ مُحرّك السّيارة قيد التّشغيل، بعد تنفيذ الشيفرة سيُرجع التّابع الصّنف نفسه. ما سيُمكّننا من استدعاء التّابع أكثر من مرّة في سطر واحد كما يلي: corolla = Car() corolla.start().start().start() المُخرج سيكون كالتّالي: Starting engine… Starting engine… Starting engine… كما تُلاحظ لقد نُفّذت الشّيفرة الموجودة داخل التّابع start ثلاث مرّات. قد تتساءل عن أهميّة الأمر، وأتّفق معك في أنّ الأمر يُمكن أن لا يكون مُفيدا. لكنّه يكون مُفيدا إذا أردت أن تقوم بتنفيذ تابعين بشكل تسلسلي، لنقل بأنّ لدينا تابعا آخر باسم move ولنفرض بأنّه سيكون مسؤولا عن تحريك السّيارة، سيكون من الأفضل لو استطعنا أن نستدعي تابع الحركة مُباشرة بعد استدعاء تابع التّشغيل. بحيث يبدو الاستعمال كالتّالي: corolla.start().move() يُمكننا أن نقوم بالأمر ببساطة، وفي الحقيقة لن نحتاج إلا لإضافة التابع move لما كتبناه سابقا. class Car: def start(self): print 'Starting engine…' return self def move(self): print 'The car is moving…' بهذه الطّريقة سنتمكن من تنفيذ الشيفرة دون مشاكل: Car().start().move() المُخرج: Starting engine… Starting engine… The car is moving… لكن لاحظ هذه المرّة بأنّنا لم نُرجع كلمة self في التّابع move ما يعني بأنّنا لن نتمكن من القيام باستدعاء التابع أكثر من مرّة: Car().start().move().move() إذا حاولت أن تُنفّذ الأمر السّابق ستحصل على خطأ كالتّالي: AttributeError: 'NoneType' object has no attribute 'move' وهذا راجع لكوننا لم نُرجع الصنف في آخر التّابع move. الوراثة مفهوم الوراثة في البرمجة كائنيّة التوجه لا يختلف كثيرا عن مفهوم الوراثة في العالم الواقعي، الصّنف الابن يرث جميع المتغيرات والتوابع من الصّنف الأب، يُمكن التّفكير في الأمر على أنّه نسخ. أي أنّ الصّنف الابن مُجرّد نُسخة طبق الأصل من الصّنف الأصلي، الفرق هنا هو أنّك تستطيع أن تُضيف المزيد من الخصائص والتوابع للصّنف الابن. وطريقة إنشاء صنف يرث من صنف آخر هي بوضع الصّنف الأب بين قوسين عند إنشاء الصّنف الابن. انظُر المثال التّالي: class Parent: a = 1 b = 2 class Child(Parent): c = 3 في المثال أعلاه، قُمنا بإنشاء صنف باسم Parent مع مُتغيّرين a و b، وبعدها أنشأنا صنفا Child الذي يرث خصائص الصّنف السابق، وبالتّالي فسنتمكّن من الوصول إلى مُتغيّرات الصّنف Parent من خلال الصّنف Child، ما يعني بأنّ الشيفرة التّالية ستعمل دون مشاكل: child = Child() print child.a print child.b print child.c المُخرج: 1 2 3 كما تُلاحظ فإنّنا قد استطعنا الوصول إلى المتغيّرين a و b رغم أنّهما لم يُعرّفا مُباشرة داخل الصّنف Child. يُمكن أن نجعل صنفا يرث توابع من صنف آخر بنفس الطّريقة: class Person: name = 'Person' def say_hello(self): name = self.name print 'Hello my name is {}'.format(name) class Abdelhadi(Person): name = 'Abdelhadi' استدعاء التّابع say_hello من كائن من الصّنف Abdelhadi. me = Abdelhadi() me.say_hello() المُخرج: Hello my name is Abdelhadi في الشيفرة أعلاه، قُمنا أولا بتعريف صنف "شخص" باسم Person ثمّ عرّفنا المُتغيّر name داخل الصّنف، وأعطيناه قيمة افتراضيّة، بعدها عرّفنا التّابع say_hello ليطبع جُملة التّرحيب. متغيرات الصنف المبنية مسبقا توجد مُتغيّرات مبنية مُسبقا في لغة بايثون، وتُسمى هذه المُتغيّرات بمُتغيّرات الصّنف، وما نعنيه بأنّها مبنية مُسبقا هو أنّك لا تحتاج إلى تعريفها، وتمتاز هذه المُتغيّرات بأنّها مُحاطة بتسطيرين سُفليّين Underscores وإليك بعضا من هذه المُتغيّرات: __doc__ سلسلة توثيق الصنف (Documentation string) وهو ما يُكتب مُباشرة بعد تعريف الصنف، ويحتوي في الغالب معلومات حول وظيفة الصّنف. القيمة الافتراضية لهذا المتغير هي None ألق نظرة على الصّنف التالي: class Person: ''' This class does nothing ''' pass لاحظ بأنّ سلسلة التوثيق مُحاطة بثلاث علامات تنصيص إذا أردنا الوصول إلى هذا التوثيق فكلّ ما علينا فعله هو استخدام الصّفة __doc__: print Person.__doc__ المُخرج: This class does nothing __module__ الوحدة التي عُرّفَ فيها الصّنف، وقيمتها الافتراضية هي'__main__'. print Person.__module__ المخرج: __main__ __dict__ هذا المُتغيّر عبارة عن قاموس يحمل ما سبق كقيم بدئية، كما يحمل أسماء المتغيّرات التي تُنشؤها أنت وقيمها وكذلك أسماء التوابع، لاحظ المثال التالي (نفّذه مُباشرة على مُفسّر بايثون لتُلاحظ النّتيجة): >>> class Math: ... x = 1 ... y = 2 ... def x_plus_y(self): ... return self.x + self.y ... >>> Math.__dict__ {'y': 2, 'x': 1, '__module__': '__main__', '__doc__': None, 'x_plus_y': <function x_plus_y at 0x7f186e76a6e0>} كما تُلاحظ مُخرجات القاموس تحتوي على كل من قيم المُتغيرات الخاصّة بالصّنف سواء التي عرّفناها أو المبنية مُسبقا، لاحظ كذلك العنصر الأخير من القاموس: 'x_plus_y': <function x_plus_y at 0x7f186e76a6e0>} هذا العنصر يحمل مفتاحا باسم التابع x_plus_y الذي عرّفناه، وقيمة هذه المفتاح تُشير إلى أنّه دالة. __name__ اسم الصّنف، يُمكنك تطبيقه على أي صنف للحصول على اسمه، انظر المثال التالي: >>> a = Math >>> a.__name__ 'Math' كما تُلاحظ فقد حصلنا على اسم الصنف Math. الوصول إلى الصنف الخاص بكائن ما المُتغيّرات التي ذكرناها سابقا خاصّة بالصّنف فقط ولا يُمكن الوصول إليها من كائن من هذا الصّنف. تأمّل الصّنف التالي: class Person: name = 'Abdelhadi' لننشئ الآن كائنا من هذا الصّنف: me = Person() يُمكننا الآن الوصول إلى قيمة المُتغيّر name كالتالي: >>> me.name 'Abdelhadi' لكننّا لن نستطيع الوصول إلى مُتغيّرات الصّنف من الكائن، بل من الصّنف فقط: person_class = Person person_class.__name__ # الشيفرة صحيحة person_object = Person() person_object.__name__ # الشيفرة خاطئة لأنّنا نحاول الوصول إلى مُتغيّر غير مُعرّف داخل الكائن ستحصل على خطأ من نوع AttributeError عند تنفيذ السّطر الأخير: AttributeError: Person instance has no attribute '__name__' الحل الأمثل هو أن نصل إلى الصّنف انطلاقا من الكائن، وبعدها سنتمكّن من الوصول إلى مُتغيّرات/صفات الصّنف دون مشاكل، وطريقة الوصول إلى صنف كائن هي بإلحاقه بكلمة __class__، انظر المثال التّالي (سنعتمد على الصنف الذي أنشأناه أعلاه): person_object = Person() person_object_class = person_object.__class__ # إسناد صنف الكائن لمتغيّر print person_object_class.__name__ # اسم الصّنف print person_object_class.__dict__ # قاموس يحتوي على بيانات الصّنف بدأنا بإنشاء كائن person_object ثمّ استخدام جُملة __class__ للوصول إلى الصّنف. المُخرج: Person {'__module__': '__main__', 'name': 'Abdelhadi', '__doc__': None} يُمكنك كذلك القيام بالأمر داخل تابع في الصّنف: class Person: def say_hello(self): print 'Hi I am a {}'.format(self.__class__.__name__) person_obj = Person() person_obj.say_hello() لاحظ استخدام self.__class__.__name__ للوصول إلى اسم الصّنف في التّابع say_hello. المُخرج: Hi I am a Person التوابع الخاصة يُمكن استخدام بعض التّوابع الخاصّة لتنفيذ شيفرة عند القيام بإجراء معيّن، وإليك قائمة بأهم هذه التّوابع (لاحظ بأنّها مُحاطة بتسطيرين سُفليّين Underscores). التابع init: تُنفَّذُ الشيفرة التي بداخله عند إنشاء كائن من الصّنف، ويُسمّى أيضا بتابع البناء Contractor . التابع del: تُنفّذ شيفرته عند حذف كائن أو عند استدعاء دالة الخروج exit. التابع repr: تُنفّذ الشيفرة عند استدعاء الكائن، ويُستخدم هذا التابع لإرجاع معلومات حول الكائن في الوضع التّفاعلي (من مُفسّر لغة بايثون مُباشرة) مثال: # استدعاء __init__ person_obj = Person() # استدعاء __repr__ person_obj repr(person_obj) # حذف الكائن واستدعاء __del__ del(person_obj) التابع init هذا مثال بسيط على إنشاء واستدعاء هذا التّابع: class Person: def __init__(self): print 'A new object was created' me = Person() مُخرج البرنامج سيكون جُملة تُفيد بأنّ كائنا قد أنشئ، لاحظ أنّ الجملة A new object was created قد طُبعت رغم عدم استدعاء التّابع init بشكل صريح، ويُمكن الحصول على نفس المُخرج باستدعاء التّابع كالتّالي: me.__init__() حسنا تعلّمنا الآن بأنّنا نستطيع تنفيذ الشيفرة الموجودة بداخل التّابع __init__ بمُجرّد إنشاء كائن من الصّنف، ولكن ماذا عن المُعاملات؟ يُمكن تمرير المُعاملات للتّابع __init__ عند إنشاء صنف كالتّالي: me = Person('Abdelhadi') وفي التّابع سيكون الأمر كالتّالي: def __init__(self, name): name = self.name print 'Hello My name is {}'.format(name) الشيفرة الكاملة: class Person: def __init__(self, name): self.name = name print 'Hello My name is {}'.format(name) me = Person('Abdelhadi') المُخرج: Hello My name is Abdelhadi التابع repr يُستعمل هذا التّابع لإرجاع معلومات قابلة للطّباعة، ويُستخدم كثيرا في الوضع التّفاعلي (مُفسّر بايثون)، ويجب أن تكون القيمة المُرجعَةُ عبارة عن سلسلة نصيّة. وإليك مثالا لكيفيّة استخدامه: class Math: x = 1 y = 2 def __repr__(self): x = self.x y = self.y return 'x: {}, y: {}'.format(x, y) x_y = Math() print x_y المُخرج: x: 1, y: 2 يُمكننا الاستفادة من هذا التّابع للوصول إلى اسم الصنف عند الوراثة: # تعريف الصّنف الرّئيسي class Person: def __repr__(self): return 'Hi I am a {}'.format(self.__class__.__name__) # الوراثة class Writer(Person): pass class Student(Person): pass # إنشاء الكائنات omar = Student() abdelhadi = Writer() # طباعة قيّم التّابع repr print omar print abdelhadi المُخرج: Hi I am a Student Hi I am a Writer لاحظ بأنّ الصّنفين Writer و Student لا يحتويان على أية شيفرة، ومع ذلك فقد نُفّذ التّابع repr واستجاب بطريقة مُختلفة مع كلّ كائن. التابع del تُنَفّذُ الشّيفرة الموجودة بداخل هذا التّابع عند حذف كائن باستعمال الدّالة del وهي دالة تُستعمل لإنجاز ما يُسمى بعمليّة جمع القُمامة Garbage Collecting والهدف الرئيسي من هذه العمليّة هو تحرير الذاكرة، ولحذف كائن يكفي أن تقوم باستدعاء الدّالة del مع تمرير الكائن كمُعامل: class Math: x = 1 y = 2 numbers = Math() numbers.x # ==> 1 numbers.y # ==> 2 # حذف الكائن del(numbers) # خطأ numbers.x # ==> NameError: name 'numbers' is not defined بعد أن حذفنا الكائن numbers لم يعد بإمكاننا الوصول إلى قيمة المُتغيّر x، وأسفر الأمر عن خطأ من نوع NameError. يُستدعى التابع del مُباشرة بعد حذف الكائن، ما يعني بأنّنا نستطيع أن نطبع جملة تُفيد بأنّ الكائن قد حُذف: class Math: x = 1 y = 2 def __del__(self): print 'Object deleted!' numbers = Math() numbers.x # ==> 1 del(numbers) المُخرج: Object deleted! تُنفَّذ شيفرة __del__ كذلك عند استدعاء الدالة exit للخروج من البرنامج: class Math: x = 1 y = 2 def exit_program(self): exit() def __del__(self): print 'Object deleted!' numbers = Math() numbers.exit_program() مُخرَج البرنامج أعلاه سيكون نفس الشيء رغم عدم حذف الكائن. والسبب راجع لاستخدام الدّالة exit داخل التّابع exit_program. تمارين تمرين 1 عد إلى الدّروس السّابقة وحاول تحويل برنامج تسجيل الدّخول إلى برنامج سهل القراءة والاستخدام باستعمال البرمجة كائنية التوجه، فمثلا يُمكن أن يستعمل من قبل مُبرمجين آخرين بالطّريقة التّالية: user = User() user.signup('username', 'password', 'password_confirmation') user.login('username', 'password') user.say_hello() user.logout() تمرين 2 أنشئ برنامجا يطبع جميع التوابع والمُتغيّرات الموجودة داخل الصّنف الذي أنشأته كحل للتّمرين الأول.1 نقطة