المحتوى عن 'دليل تعلم بايثون'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
  • HTML
    • HTML5
  • CSS
  • SQL
  • سي شارب #C
    • منصة Xamarin
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • ASP.NET
    • ASP.NET Core
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 30 نتائج

  1. لا تخلو لغة برمجة من التعليمات الشرطية التي تُنفَّذ بناءً على تحقق شرط معين، وهي تعليمات برمجية يمكنها التحكم في تنفيذ شفرات معينة بحسب تحقق شرط ما من عدمه في وقت التنفيذ. تُنفّذ تعليمات برامج بايثون من الأعلى إلى الأسفل، مع تنفيذ كل سطر بحسب ترتيبه. باستخدام التعليمات الشرطية، يمكن للبرامج التحقق من استيفاء شروط معينة، ومن ثم تنفيذ الشيفرة المقابلة. هذه بعض الأمثلة التي سنستخدم فيها التعليمات الشرطية: إن حصلت الطالبة على أكثر من 65٪ في الامتحان، فأعلن عن نجاحها؛ وإلا، فأعلن عن رسوبها إذا كان لديه مال في حسابه، فاحسب الفائدة. وإلا، فاحسب غرامة إن اشتروا 10 برتقالات أو أكثر، فاحسب خصمًا بمقدار 5٪؛ وإلا فلا تفعل تقيِّم الشيفرة الشرطية شروطًا، ثم تُنفِّذ شيفرةً بناءً على ما إذا تحققت تلك الشروط أم لا. ستتعلم في هذا الدرس كيفية كتابة التعليمات الشرطية في بايثون. التعليمة if سنبدأ بالتعليمة ‎if‎، والتي تتحقق مما إذا تحقق شرط محدَّد أم لا، وفي حال تحقق الشرط، فستنفَّذ الشيفرة المقابلة له. لنبدأ بأمثلة عملية توضح ذلك. افتح ملفًا، واكتب الشيفرة التالية: grade = 70 if grade >= 65: print("درجة النجاح") أعطينا للمتغير ‎grade‎ القيمة ‎70‎. ثم استخدمنا التعليمة ‎if‎ لتقييم ما إذا كان المتغير grade أكبر من (‎>=‎) أو يساوي ‎65‎. وفي تلك الحالة، سيطبع البرنامج السلسلة النصية التالية: درجة النجاح. احفظ البرنامج بالاسم ‎grade.py‎، ثم نفّذه في بيئة البرمجة المحلية من نافذة الطرفية باستخدام الأمر ‎python grade.py‎. في هذه الحالة، الدرجة 70 تلبي الشرط، لأنّها أكبر من 65، لذلك ستحصل على المخرجات التالية عند تنفيذ البرنامج: درجة النجاح لنغيّر الآن نتيجة هذا البرنامج عبر تغيير قيمة المتغير ‎grade‎ إلى ‎60‎: grade = 60 if grade >= 65: print("درجة النجاح") بعد حفظ وتنفيذ الشيفرة، لن نحصل على أي مخرجات، لأنّ الشرط لم يتحقق، ولم نأمر البرنامج بتنفيذ تعليمة أخرى. كمثال آخر، دعنا نتحقق مما إذا كان رصيد الحساب المصرفي أقل من 0. لننشئ ملفا باسم ‎account.py‎، ونكتب البرنامج التالي: balance = -5 if balance < 0: print("الحساب فارغ، أضف مبلغا الآن، أو ستحصل على غرامة.") عند تنفيذ البرنامج باستخدام ‎python account.py‎، سنحصل على المخرجات التالية: الحساب فارغ، أضف مبلغًا الآن، أو ستحصل على غرامة. أعطينا للمتغير ‎balance‎ القيمة ‎-5‎، وهي أقل من 0 في البرنامج السابق. ولمَّا كان الرصيد مستوفيًا لشرط التعليمة ‎if‎ (أي ‎balance < 0‎)، فسنحصل على سلسلة نصية في المخرجات بمجرد حفظ الشيفرة وتنفيذها. مرة أخرى، لو غيرنا الرصيد إلى القيمة 0 أو إلى عدد موجب، فلن نحصل على أيّ مخرجات. التعليمة Else قد تريد من البرنامج أن يفعل شيئًا ما في حال عدم تحقق شرط التعليمة ‎if‎. في المثال أعلاه، نريد طباعة مخرجات في حال النجاح والرسوب. ولفعل ذلك، سنضيف التعليمة ‎else‎ إلى شرط الدرجة أعلاه وفق الصياغة التالية: grade = 60 if grade >= 65: print("درجة النجاح") else: print("درجة الرسوب") قيمة المتغير ‎‎grade‎‎ تساوي ‎60‎، لذلك فشرط التعليمة ‎if‎ غير متحقق، وبالتالي فإنّ البرنامج لن يطبع ‎درجة النجاح‎. تخبر التعليمة ‎else‎ البرنامجَ أنّ عليه طباعة السلسلة النصية "درجة الرسوب". عندما نحفظ البرنامج وننفّذه، سنحصل على المخرجات التالية: درجة الرسوب إذا عدّلنا البرنامج وأعطينا المتغيرَ grade القيمة ‎65‎ أو أعلى منها، فسنحصل بدلاً من ذلك على الناتج ‎درجة النجاح‎. لإضافة التعليمة ‎else‎ إلى مثال الحساب المصرفي، سنعيد كتابة الشيفرة كما يلي: balance = 522 if balance < 0: print("الحساب فارغ، أضف مبلغا الآن، أو ستحصل على غرامة.") else: print("رصيدك أكبر من 0.") سنحصل على المخرجات التالية: رصيدك أكبر من 0. هنا، غيّرنا قيمة المتغير ‎balance‎ إلى عدد موجب لكي تُنفَّذ الشيفرة المقابلة للتعليمة ‎else‎. إن أردت تنفيذ الشيفرة المقابلة للتعليمة ‎if‎، غيِّر القيمة إلى عدد سالب. من خلال دمج العبارتين ‎if‎ و ‎else‎، فأنت تنشئ تعليمة شرطية مزدوجة، والتي ستجعل الحاسوب ينفذ شيفرة برمجية معينة سواء تم استيفاء شرط ‎if‎ أم لا. التعليمة Else if حتى الآن، عملنا على تعليمات شرطية ثنائية، أي إن تحقق الشرط، فنفذ شيفرة ما، وإلا، فنفِّذ شيفرة أخرى فقط. لكن في بعض الحالات، قد تريد برنامجًا يتحقق من عدة حالات شرطية. ولأجل هذا، سوف نستخدم التعليمة Else if، والتي تُكتب في بايثون هكذا ‎elif‎. تشبه التعليمة ‎elif‎ - أو Else if - التعليمة ‎if‎، ومهمتها التحقق من شرط إضافي. في برنامج الحساب المصرفي، قد نرغب في الحصول على ثلاثة مخرجات مختلفة مقابلة لثلاث حالات مختلفة: الرصيد أقل من 0 الرصيد يساوي 0 الرصيد أعلى من 0 ستوضع التعليمة ‎elif‎ بين التعليمة ‎if‎ والتعليمة ‎else‎ كما يلي: . . . if balance < 0: print("الحساب فارغ، أضف مبلغا الآن، أو ستحصل على غرامة.") elif balance == 0: print("الرصيد يساوي 0، أضف مبلغًا قريبًا.") else: print("رصيدك أكبر من 0.") الآن، هناك ثلاثة مخرجات محتملة يمكن أن تُطبع عند تنفيذ البرنامج: إن كان المتغير ‎balance‎ يساوي ‎0‎، فسنحصل على المخرجات من التعليمة ‎elif‎ (أي ‎الرصيد يساوي 0، أضف مبلغًا قريبًا.‎). إذا ضُبِط المتغير ‎balance‎ عند عدد موجب، فسوف نحصل على المخرجات من التعليمة ‎else‎ (أي ‎رصيدك أكبر من 0.‎). إذا ضُبِط المتغير ‎balance‎ عند عدد سالب، فسنحصل على المخرجات من التعليمة ‎if‎ (أي ‎الحساب فارغ، أضف مبلغا الآن، أو ستحصل على غرامة‎). ماذا لو أردنا أن نأخذ بالحسبان أكثر من ثلاثة احتمالات؟ يمكننا كتابة عدة تعليمات ‎elif‎ في الشيفرة البرمجية. لنُعِد كتابة البرنامج ‎grade.py‎ بحيث يقابل كل نطاق من الدرجات علامة محددة: 90 أو أعلى تكافئ العلامة أ 80-89 تعادل العلامة ب 70-79 تعادل العلامة ج 65-69 تعادل العلامة د 64 أو أقل تكافئ العلامة ه سنحتاج لتنفيذ هذه الشيفرة إلى تعليمة ‎if‎ واحد، وثلاث تعليمات ‎elif‎، وتعليمة ‎else‎ تعالج جميع الحالات الأخرى. دعنا نعيد كتابة الشيفرة من المثال أعلاه لطباعة سلسلة نصية مقابلة لكل علامة. يمكننا الإبقاء على التعليمة ‎else‎ كما هي. . . . if grade >= 90: print("العلامة أ") elif grade >=80: print("العلامة ب") elif grade >=70: print("العلامة ج") elif grade >= 65: print("العلامة د") else: print("درجة الرسوب") تُنفّذ التعليمات ‎elif‎ بالترتيب. هذا البرنامج سيكمل الخطوات التالية: إذا كانت الدرجة أكبر من 90، فسيطبع البرنامجُ ‎العلامة أ‎، وإذا كانت الدرجة أقل من 90، فسيمرّ البرنامج إلى التعليمة التالية … إذا كانت الدرجة أكبر من أو تساوي 80، فسيطبع البرنامجُ ‎العلامة ب‎، إذا كانت الدرجة تساوي 79 أو أقل، فسيمرّ البرنامج إلى التعليمة التالية … إذا كانت الدرجة أكبر من أو تساوي 70، فسيطبعُ البرنامجُ ‎العلامة ج‎، إذا كانت الدرجة تساوي 69 أو أقل، فسيمرّ البرنامج إلى التعليمة التالية … إذا كانت الدرجة أكبر من أو تساوي 65، فسيطبع البرنامجُ ‎العلامة د‎، وإذا كانت الدرجة تساوي 64 أو أقل، فسيمرّ البرنامج إلى التعليمة التالية … سيطبع البرنامج ‎درجة الرسوب‎، لأنه لم يتم استيفاء أيِّ من الشروط المذكورة أعلاه. تعليمات if المتشعبة بعد أن تتعود على التعليمات ‎if‎ و ‎elif‎ و ‎else‎، يمكنك الانتقال إلى التعليمات الشرطية المتشعبة (nested conditional statements). يمكننا استخدام تعليمات ‎if‎ المتشعبة في الحالات التي نريد فيها التحقق من شرط ثانوي بعد التأكد من تحقق الشرط الرئيسي. لهذا، يمكننا حشر تعليمة if-else داخل تعليمة if-else أخرى. لنلقِ نظرة على صياغة ‎if‎ المتشعبة: if statement1: # الخارجية if تعليمة print("true") if nested_statement: # المتشعبة if تعليمة print("yes") else: # المتشعبة else تعليمة print("no") else: # الخارجية else تعليمة print("false") هناك عدة مخرجات محتملة لهذه الشيفرة: إذا كانت ‎statement1‎ صحيحة، فسيتحقق البرنامج مما إذا كانت ‎nested_statement‎ صحيحة أيضًا. إذا كانت كلتا الحالتين صحيحتان، فسنحصل على المخرجات التالية: true yes ولكن إن كانت ‎statement1‎ صحيحة، و ‎nested_statement‎ خاطئة، فسنحصل على المخرجات التالية: true no وإذا كانت ‎statement1‎ خاطئة، فلن تُنفّذ تعليمة if-else المتشعبة على أيّ حال، لذلك ستُنفّذ التعليمة ‎else‎ وحدها، والمخرجات ستكون: false يمكن أيضًا استخدام عدة تعليمات ‎if‎ متشعبة في الشيفرة: if statement1: # الخارجية if print("hello world") if nested_statement1: # المتشعبة الأولى if print("yes") elif nested_statement2: # المتشعبة الأولى elif print("maybe") else: #المتشعبة الأولى else print("no") elif statement2: # الخارجية elif print("hello galaxy") if nested_statement3: # المتشعبة الثانية if print("yes") elif nested_statement4: # المتشعبة الثانية elif print("maybe") else: # المتشعبة الثانية else print("no") else: # الخارجية else statement("مرحبا") في الشيفرة البرمجية أعلاه، هناك تعليمات ‎if‎ و ‎elif‎ متشعبة داخل كل تعليمات ‎if‎. هذا سيفسح المجال لمزيد من الخيارات في كل حالة. دعنا نلقي نظرة على مثال لتعليمات ‎if‎ متشعبة في البرنامج ‎grade.py‎. يمكننا التحقق أولًا مما إذا كان الطالب قد حقق درجة النجاح (أكبر من أو تساوي 65٪)، ثم نحدد العلامة المقابلة للدرجة. إذا لم يحقق الطالب درجة النجاح، فلا داعي للبحث عن العلامة المقابلة للدرجة، وبدلًا من ذلك، يمكن أن نجعل البرنامج يطبع سلسلة نصية فيها إعلان عن رسوب الطالب. ستبدو الشيفرة المعدلة كما يلي: . . . if grade >= 65: print("درجة النجاح:") if grade >= 90: print("أ") elif grade >=80: print("ب") elif grade >=70: print("ج") elif grade >= 65: print("د") else: print("درجة الرسوب") إذا أعطينا للمتغير ‎grade‎ القيمة ‎92‎، فسيُستوفى الشرط الأول، وسيَطبع البرنامجُ ‎درجة النجاح:‎. بعد ذلك، سيتحقق مما إذا كانت الدرجة أكبر من أو تساوي 90، وبما أنّ هذا الشرط مستوفًى أيضًا، فستُطبع ‎أ‎. أما إذا أعطينا للمتغير ‎grade‎ القيمة ‎60‎، فلن يتم استيفاء الشرط الأول، لذلك سيتخطى البرنامج تعليمات ‎if‎ المتشعبة، وينتقل إلى التعليمة ‎else‎، ويطبع ‎درجة الرسوب‎. يمكننا بالطبع إضافة المزيد من الخيارات، واستخدام طبقة ثانية من تعليمات if المتشعبة. ربما نود إضافة الدرجات التفصيلية أ+‎ و أ و أ-‎. يمكننا القيام بذلك عن طريق التحقق أولًا من اجتياز درجة النجاح، ثم التحقق مما إذا كانت الدرجة تساوي 90 أو أعلى، ثم التحقق مما إذا كانت الدرجة تتجاوز 96، وفي تلك الحالة ستقابل العلامة ‎أ+. إليك المثال التالي: . . . if grade >= 65: print("درجة النجاح:") if grade >= 90: if grade > 96: print("أ+") elif grade > 93 and grade <= 96: print("أ") elif grade >= 90: print("أ-") . . . في الشيفرة أعلاه، في حال تعيين المتغير ‎grade‎ عند القيمة ‎96‎، سيقوم البرنامج بما يلي: التحقق مما إذا كانت الدرجة أكبر من أو تساوي 65 (صحيح) طباعة ‎درجة النجاح:‎ التحقق مما إذا كانت الدرجة أكبر من أو تساوي 90 (صحيح) التحقق مما إذا كانت الدرجة أكبر من 96 (خطأ) التحقق مما إذا كانت الدرجة أكبر من 93، وأقل من أو تساوي 96 (صحيح) طباعة أ‎ تجاوز التعليمات الشرطية المتشعبة وتنفيذ باقي الشيفرة ستكون مخرجات البرنامج في حال كانت الدرجة تساوي 96 كالتالي: درجة النجاح: أ تساعد تعليمات ‎if‎ المتشعبة على إضافة عدة مستويات من الشروط الفرعية إلى الشيفرة. خلاصة ستتحكم باستخدام التعليمات الشرطية، مثل التعليمة ‎if‎، في مسار البرنامج أي تدفق تنفيذ الشيفرة. تطلب التعليمات الشرطية من البرنامج التحقق من استيفاء شرط معين من عدمه. وإذا تم استيفاء الشرط، فستُنفّذ شيفرة معينة، وإلا فسيستمر البرنامج وينتقل إلى الأسطر التالية. يمكنك الدمج بين التعليمات الشرطية والمعاملات المنطقية، بما فيها and و or، واستخدام التعليمات الشرطية مع الحلقات التكرارية. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Write Conditional Statements in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية إنشاء حلقات تكرار while في بايثون 3 المقالة السابقة: كيفية كتابة الوحدات في بايثون 3
  2. وحدات (modules) بايثون هي ملفات ‎.py‎ تحتوي شفرة بايثون، ويمكن التعامل مع أيّ ملف بايثون على أنه وحدة. تتوفر بعض الوحدات في مكتبة بايثون القياسية، والتي تُثبّت تلقائيًا مع بايثون. يمكن لبعضها الآخر أن يُثبّت عبر مدير الحزم pip. بالإضافة إلى ذلك، يمكنك إنشاء وحدات بايثون خاصة بك، لأنّ الوحدات هي مجرد ملفات ‎.py‎. سيرشدك هذا الدرس إلى كيفية كتابة وحدات بايثون لاستخدامها في ملفات البرمجة الأخرى. كتابة الوحدات واستيرادها كتابة الوحدات مشابه لكتابة أي ملف بايثون آخر. يمكن أن تحتوي الوحدات على تعريفات الدوال والأصناف والمتغيرات التي يمكن استخدامها بعد ذلك في برامج بايثون الأخرى. سنشئ من بيئة البرمجة الحالية الخاصة ببايثون 3 أو بيئة البرمجة المستندة إلى الخادم ملفًّا باسم ‎hello.py‎، والذي سنتستورده لاحقًا من ملف آخر. في البدء، سننشئ دالة تطبع العبارة مرحبا بالعالم!: # تعريف دالة def world(): print("مرحبا بالعالم!") إذا نفّذنا البرنامج في سطر الأوامر باستخدام ‎python hello.py‎، فلن يحدث شيء، لأننا لم نطلب من البرنامج فعل أي شيء. لننشئ ملفًا ثانيًا في نفس المجلد (أي بجانب الملف السابق) باسم ‎main_program.py‎ حتى نتمكن من استيراد الوحدة التي أنشأناها للتو، ومن ثم استدعاء الدالة. يجب أن يكون هذا الملف في نفس المجلد حتى تعرف بايثون موضع الوحدة، لأنها ليست وحدة مُضمّنة. # hello استيراد الوحدة import hello # استدعاء الدالة hello.world() نظرًا لأننا استوردنا الوحدة، نحتاج إلى استدعاء الدالة من خلال التأشير إلى اسم الوحدة بالصياغة النقطية (dot notation). يمكننا بدلًا من ذلك استيراد دالة محدَّدة من الوحدة بالتعليمة ‎from hello import world‎، واستدعاء تلك الدالة بالشكل ‎world()‎ كما تعلمنا ذلك من الدرس السابق. الآن، يمكننا تنفيذ البرنامج من سطر الأوامر: python main_program.py سنحصل على المخرجات التالية: مرحبا بالعالم! لنرى كيف يمكننا استخدام المتغيرات في الوحدات، دعنا نضيف تعريفًا لمتغير في الملف ‎hello.py‎: # تعريف دالة def world(): print("مرحبا بالعالم!") # تعريف المتغير shark = "Sammy" بعد ذلك، سنستدعي المتغير داخل الدالة ‎print()‎ في الملف ‎main_program.py‎: # hello استيراد الوحدة import hello # استدعاء الدالة hello.world() # طباعة المتغير print(hello.shark) بمجرد تنفيذ البرنامج، سنحصل على المخرجات التالية: مرحبا بالعالم! Sammy أخيرًا، دعنا نعرّف صنفًا في الملف ‎hello.py‎. سننشئ الصنف ‎Octopus‎، والذي يحتوي على الخاصيتين ‎name‎ و ‎color‎، إضافة إلى دالة تطبع الخاصيات عند استدعائها. # تعريف الدالة def world(): print("مرحبا بالعالم!") # تعريف المتغير shark = "Sammy" # تعريف الصنف class Octopus: def __init__(self, name, color): self.color = color self.name = name def tell_me_about_the_octopus(self): print("This octopus is " + self.color + ".") print(self.name + " is the octopus's name.") سنضيف الآن الصنفَ إلى نهاية الملف ‎main_program.py‎: # hello استيراد الوحدة import hello # استدعاء الدالة hello.world() # طباعة المتغير print(hello.shark) # استدعاء الصنف jesse = hello.Octopus("Jesse", "orange") jesse.tell_me_about_the_octopus() بمجرد استدعاء الصنف Octopus باستخدام ‎hello.Octopus()‎، يمكننا الوصول إلى دوال وخاصيات الصنف من فضاء الأسماء الخاص بالملف ‎main_program.py‎. يتيح لنا هذا كتابة ‎jesse.tell_me_about_the_octopus()‎ في السطر الأخير دون استدعاء ‎hello‎. يمكننا أيضًا، على سبيل المثال، استدعاء إحدى خاصيات الصنف، مثل ‎jesse.color‎، دون الرجوع إلى اسم الوحدة ‎hello‎. سنحصل عند تنفيذ البرنامج على المخرجات التالية: مرحبا بالعالم! Sammy This octopus is orange. Jesse is the octopus's name. من المهم أن تضع في الحسبان أنه على الرغم من أنّ الوحدات غالبًا ما تضم تعريفات، إلا أنها يمكن أيضًا أن تقدم شفرات برمجية. لتوضيح هذا، دعنا نعيد كتابة الملف ‎hello.py‎ لنجعله يقدم دالة ‎world()‎: # تعريف دالة def world(): print("مرحبا بالعالم!") # استدعاء الدالة داخل الوحدة world() لقد حذفنا أيضًا التعريفات الأخرى في الملف. الآن، في الملف ‎main_program.py‎، سنحذف كل الأسطر باستثناء عبارة الاستيراد: # hello استيراد الوحدة import hello عند تنفيذ ‎main_program.py‎، سنحصل على المخرجات التالية: مرحبا بالعالم! هذا لأنّ الوحدة ‎hello‎ قدمت الدالة ‎world()‎، والتي مُرِّرت بعد ذلك إلى ‎main_program.py‎ لتُنفّذ مع السكربت ‎main_program.py‎. الوحدة هي ملف بايثون مؤلف من تعريفات و شيفرات برمجية يمكن الاستفادة منها في ملفات بايثون الأخرى. الوصول إلى الوحدات من مجلد آخر قد تكون الوحدات مفيدة لأكثر من مشروع واحد، وفي هذه الحالة، لن يكون من الحكمة الاحتفاظ بالوحدة في مجلد مرتبط بمشروع خاص. إذا أردت استخدام وحدة من مجلد آخر غير المجلد الذي يحوي البرنامج الرئيسي، فأمامك عدة خيارات سنسردها فيما يلي. التعرف تلقائيًا على مسار الوحدة أحد الخيارات هو استدعاء مسار الوحدة من الملفات البرمجية التي تستخدم تلك الوحدة. يُعد هذا حلًّا مؤقتًا يمكن استخدامه أثناء عملية التطوير، لأنه لا يجعل الوحدة متاحة على مستوى النظام بأكمله. لإلحاق مسار وحدة بملف برمجي آخر، ستبدأ باستيراد الوحدة ‎sys‎، إلى جانب الوحدات الأخرى التي ترغب في استخدامها في ملف البرنامج الرئيسي. تعد الوحدة ‎sys‎ جزءًا من مكتبة بايثون القياسية، وتوفر معاملات ودوال نظامية يمكنك استخدامها في برنامجك لتعيين مسار الوحدة التي ترغب في تقديمها. على سبيل المثال، لنقل أننا نقلنا الملف ‎hello.py‎ إلى المسار ‎/usr/sammy/‎، بينما يوجد الملف ‎main_program.py‎ في مجلد آخر. في الملف ‎main_program.py‎، ما يزال بإمكاننا استيراد الوحدة ‎hello‎ عن طريق استيراد الوحدة ‎sys‎، ثم إضافة المسار ‎/usr/sammy/‎ إلى المسارات التي يبحث بايثون فيها عن الملفات. import sys sys.path.append('/usr/sammy/') import hello ... إن عيّنت مسار الملف ‎hello.py‎ بشكل صحيح، فسيكون بمقدورك تنفيذ الملف ‎main_program.py‎ دون أيّ أخطاء، وستحصل على نفس المخرجات التي حصلنا عليها أعلاه عندما كان ‎hello.py‎ في نفس المجلد. إضافة الوحدة إلى مسار بايثون الخيار الثاني هو إضافة الوحدة إلى المسار الذي يبحث فيه بايثون عن الوحدات والحزم. هذا حل أفضل وأدوم، لأنه يجعل الوحدة متاحة على نطاق البيئة، أو على مستوى النظام. لمعرفة المسار الذي يبحث فيه بايثون، شغِّل مترجم (interpreter) بايثون من بيئة البرمجة خاصتك: python بعد ذلك، استورد الوحدة ‎sys‎: import sys ثم اطلب من بايثون طباعة مسار النظام: print(sys.path) ستحصل على بعض المخرجات، وسيُطبع مسار نظام واحد على الأقل. إذا كنت تعمل في بيئة برمجة، فقد تتلقى العديد منها. سيكون عليك البحث عن المسارات الموجودة في البيئة التي تستخدمها حاليًا، ولكن قد ترغب أيضًا في إضافة الوحدة إلى مسار النظام الرئيسي لبايثون. النتيجة ستكون مشابهة لما يلي: '/usr/sammy/my_env/lib/python3.5/site-packages' يمكنك الآن نقل الملف ‎hello.py‎ إلى هذا المجلد. بعد ذلك، يمكنك استيراد الوحدة ‎hello‎ كالمعتاد: import hello ... عند تنفيذ البرنامج، يُفترض ألا يحدث أيّ خطأ. يضمن لك تعديل مسار الوحدة إمكانية الوصول إليها مهما كان المجلد الذي تعمل فيه. هذا مفيد خاصة في حال كنت تعمل على عدة مشاريع تشير إلى الوحدة نفسها. خلاصة إنّ كتابة وحدات بايثون لا يختلف عن كتابة أيّ ملف بايثون آخر. غطينا في هذه المقالة كيفية كتابة التعاريف في الوحدات، وكيفية استخدامها في ملف بايثون آخر، وعرضنا بعض الخيارات حول المواضِع التي يمكن أن تحفظ فيها الوحدة لتجعلها متاحة. يمكنك تعلم المزيد حول تثبيت الوحدات واستيرادها من الدرس السابق: [كيفية استيراد الوحدات في بايثون 3](). هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Write Modules in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية كتابة العبارات الشرطية في بايثون 3 المقالة السابقة: كيفية استيراد الوحدات في بايثون 3
  3. توفر لغة بايثون مجموعة متنوعة من الدوال المضمّنة مثل: print()‎‎: تطبع التعابير المُمرَّرة إليها في مجرى الخرج abs()‎‎: تُعيد القيمة المطلقة للعدد int()‎‎: تحوِّل نوع بيانات إلى عدد صحيح len()‎‎: تُعيد طول تسلسل أو مجموعة هذه الدوال المضمّنة وغيرها مفيدة، لكنها محدودة، لهذا يستخدم المطورون الوحدات (modules) لتطوير برامج أكثر تعقيدًا. الوحدات (Modules) هي ملفات بايثون ذات امتداد ‎.py، والتي تحوي شيفرات بايثون. يمكن التعامل مع أيّ ملف بايثون على أنه وحدة. مثلًا، إن كان هناك ملف بايثون يسمى hello.py، فسيكون اسم الوحدة المقابلة له hello، والذي يمكن استيراده في ملفات بايثون الأخرى، أو استخدامه في مترجم (interpreter) سطر أوامر بايثون. ستتعلم في المقالة التالية كيفية إنشاء الوحدات. يمكن للوحدات أن تعرِّف دوالًا وأصنافًا ومتغيرات يمكن الرجوع إليها من ملفات بايثون الأخرى، أو من مترجم سطر أوامر بايثون. في بايثون، يمكنك الوصول إلى الوحدات باستخدام العبارة import. عند فعل ذلك، ستُنفَّذ شيفرة الوحدة، مع الاحتفاظ بنطاقات (scopes) التعريفات حتى تكون متاحة في ملفك الحالي. عندما تستورد بايثون وحدةً باسم hello على سبيل المثال، فسيبحث المترجم أولًا عن وحدة مضمّنة باسم hello. فإن لم يجد، فسيبحث عن ملف يسمى hello.py في قائمة من المجلدات يحددها المتغير sys.path. سيرشدك هذا الدرس إلى كيفية البحث عن الوحدات وتثبيتها، واستيرادها، وإعادة تسميتها (aliasing). تثبيت الوحدات هناك عدد من الوحدات المضمنة في مكتبة بايثون القياسية التي تحتوي على العديد من الوحدات التي توفر الكثير من وظائف النظام، أو توفر حلولًا قياسية. مكتبة بايثون القياسية تأتي مع كل توزيعات بايثون. للتحقق من أنّ وحدات بايثون جاهزة للعمل، ادخل إلى بيئة برمجة بايثون 3 المحلية، أو بيئة البرمجة المستندة إلى الخادم، وشغّل مترجم بايثون في سطر الأوامر على النحو التالي: (my_env) sammy@ubuntu:~/environment$ python من داخل المترجم، يمكنك تنفيذ العبارة import مع اسم الوحدة للتأكد من أنّها جاهزة: import math لمّا كانت math وحدة مضمّنة، فينبغي أن يُكمل المترجم المهمة دون أي مشاكل، ثم يعود إلى المحث (prompt). هذا يعني أنك لست بحاجة إلى فعل أيّ شيء للبدء في استخدام الوحدة math. لننفِّذ الآن العبارة import مع وحدة قد لا تكون مُثبّتة عندك، مثل matplotlib، وهي مكتبة للرسم ثنائي الأبعاد: import matplotlib إذا لم تكن matplotlib مثبتة، فستتلقّى خطأً مثل هذا: ImportError: No module named 'matplotlib' يمكنك إيقاف مترجم بايثون بالضغط على CTRL + D، ثم تثبيت الوحدة matplotlib عبر pip بتنفيذ الأمر التالي: (my_env) sammy@ubuntu:~/environment$ pip install matplotlib بمجرد تثبيتها، يمكنك استيراد matplotlib من مترجم بايثون باستخدام import matplotlib، ولن يحدث أيّ خطأ. استيراد الوحدات للاستفادة من الدوال الموجودة في الوحدة، ستحتاج إلى استيراد الوحدة عبر التعليمة import. تتألف التعليمة import من الكلمة المفتاحية import معقوبة باسم الوحدة. يُصرَّح عن عملية استيراد الوحدات في أعلى ملفات بايثون، قبل الأسطر التوجيهية (shebang lines أي الأسطر التي تبدأ بـ ‎#!‎)، أو التعليقات العامة. لذلك، سنستورد في ملف برنامج بايثون my_rand_int.py الوحدة random لتوليد أعداد عشوائية على النحو التالي: import random عندما نستورد وحدة، فإننا نجعلها متاحة في برنامجنا الحالي كفضاء أسماء (namespace) منفصل. هذا يعني أنه سيتعيّن علينا الرجوع إلى الدالة باستخدام الصياغة النقطية (dot notation) على النحو التالي [module].[function]. عمليًا، باستخدام مثال الوحدة random، ستبدو الشفرة كما يلي: random.randint()‎‎‎: تستدعي الدالة لإعادة عدد صحيح عشوائي، أو random.randrange()‎‎: تستدعي الدالة لإعادة عنصر عشوائي من نطاق محدد. دعنا ننشئ حلقة for لتوضيح كيفية استدعاء دالة من الوحدة random ضمن البرنامج my_rand_int.py: import random for i in range(10): print(random.randint(1, 25)) يستورد هذا البرنامج الصغير الوحدة random في السطر الأول، ثم ينتقل إلى الحلقة for التي ستمر على 10 عناصر. داخل الحلقة، سيطبع البرنامج عددًا صحيحًا عشوائيًا من المجال 1 إلى 25 (مشمول). يُمرّّر العددان الصحيحان 1 و 25 إلى random.randint()‎‎ كمعاملين. عند تنفيذ البرنامج باستخدام الأمرpython my_rand_int.py، ستظهر 10 أعداد صحيحة عشوائية في المخرجات. نظرًا لأنّ هذه العناصر عشوائية، فستحصل على الأرجح على أعداد مختلفة في كل مرة تنفّذ فيها البرنامج، لكنها عمومًا ستبدو كما يلي: 6 9 1 14 3 22 10 1 15 9 الأعداد الصحيحة كلها محصورة بين 1 و 25. إذا كنت ترغب في استخدام دوال من أكثر من وحدة، يمكنك ذلك عن طريق إضافة عدة تعليمات استيراد: import random import math قد تصادف برامج تستورد عدة وحدات مفصولة بفواصل - مثل import random, math - ولكنّ هذا لا يتوافق مع دليل التنسيق PEP 8. للاستفادة من الوحدة الإضافية، يمكننا إضافة الثابت pi من الوحدة math إلى برنامجنا، وتقليل عدد الأعداد الصحيحة العشوائية المطبوعة: import random import math for i in range(5): print(random.randint(1, 25)) print(math.pi) الآن، عند تنفيذ البرنامج، سنحصل على مخرجات على الشكل التالي، مع تقريب للعدد pi في السطر الأخير: 18 10 7 13 10 3.141592653589793 تتيح لك التعليمة import استيراد وحدة واحدة أو أكثر إلى برامجك، وهذ يمكّنك من الاستفادة مما تحويها تلك الوحدات. استخدام الصياغة from ... import للإشارة إلى عناصر من وحدة مستوردة ضمن فضاء الأسماء، يمكنك استخدام التعليمة from ... import. عندما تستورد الوحدات بهذه الطريقة، سيكون بمقدورك الرجوع إلى الدوال بأسمائها فقط، بدلًا من استخدام الصياغة النقطية. في هذه الصياغة، يمكنك تحديد التعريفات التي تود الإشارة إليها مباشرة. في بعض البرامج، قد ترى العبارة * from ... import، إذ تشير العلامة * إلى جميع العناصر الموجودة في الوحدة، ولكنّ هذه الصياغة غير معتمدة في PEP 8. سنحاول في البداية استيراد دالة واحدة من الوحدة random، وهي randint()‎‎: from random import randint هنا، نستدعي أولًا الكلمة المفتاحية from، ثم random. بعد ذلك، نستخدم الكلمة المفتاحية import، ونستدعي الدالة المحددة التي نودّ استخدامها. الآن، عندما نرغب في استخدام هذه الدالة في برنامجنا، لن نستدعي الدالة وفق الصياغة النقطية، random.randint()‎‎، ولكن سنستدعيها باسمها مباشرةً، أي randint()‎‎: from random import randint for i in range(10): print(randint(1, 25)) عند تنفيذ البرنامج، ستتلقى مخرجات مشابهة لما تلقيته مسبقًا. يتيح لنا استخدام from ... import الرجوع إلى العناصر المعرّفة في الوحدة من فضاء الأسماء الخاص ببرنامجنا، مما يتيح لنا تجنب استخدام الصياغة النقطية الطويلة. الأسماء المستعارة في الوحدات يمكن تعديل أسماء الوحدات ودوالها داخل بايثون باستخدام الكلمة المفتاحية as. قد ترغب في تغيير اسم ما لأنك تستخدمه سلفًا في برنامجك، أو أنه مستخدم في وحدة أخرى مستوردة، أو قد ترغب في اختصار اسم طويل تستخدمه كثيرًا. يمكنك ذلك عبر الصياغة التالية: import [module] as [another_name] لنعدّل اسم الوحدة math في ملف البرنامج my_math.py. سنغيّر اسم الوحدة math إلى m من أجل اختصاره. سيبدو برنامجنا المعدل كالتالي: import math as m print(m.pi) print(m.e) سنشير داخل البرنامج إلى الثابت pi بالتعبير m.pi، بدلًا من math.pi. يشيع في بعض الوحدات استخدام أسماء مستعارة (aliases) محدَّدة. فمثلًا، يدعو التوثيق الرسمي للوحدة matplotlib.pyplot إلى استخدام الاسم المستعار plt: import matplotlib.pyplot as plt يسمح هذا للمبرمجين بإلحاق الكلمة القصيرة plt بأي دالة متاحة داخل الوحدة، كما هو الحال في plt.show()‎‎. خلاصة يسمح مفهوم الوحدات باستدعاء دوال غير مضمّنة في بايثون. فبعض الوحدات مُثبّتة كجزء من بايثون، وبعضها سنثبّتها عبر pip. يتيح لنا استخدام الوحدات توسيع برامجنا وتقويتها، لأنها تضع تحت تصرّفنا شفرات جاهزة للاستخدام. يمكننا أيضًا إنشاء وحدات خاصة بنا، لنستخدمها نحن، أو المبرمجون الآخرون وهذا ما سنتعرف عليه في المقال التالي. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Import Modules in Python 3 لصاحبته Lisa Tagliaferri. اقرأ أيضًا المقالة التالية: كيفية كتابة الوحدات في بايثون 3 المقالة السابقة: فهم القواميس في بايثون 3
  4. القاموس هو نوع مُضمَّن في بايثون. تربط القواميس مفاتيح بقيم على هيئة أزواج، وهذه الأزواج مفيدة لتخزين البيانات في بايثون. تستخدم القواميس عادةً لتخزين البيانات المترابطة، مثل المعلومات المرتبطة برقم تعريف، أو ملفات تعريف المستخدم، وتُنشأ باستخدام الأقواس المعقوصة {}. تبدو القواميس على الشكل التالي: sammy = {'username': 'sammy-shark', 'online': True, 'followers': 987} بالإضافة إلى القوسين المعقوصين، لاحظ وجود النقطتين الرأسيتين (:) في القاموس. الكلمات الموجودة على يسار النقطتين الرأسيتين هي المفاتيح التي قد تكون أيَّ نوع بيانات غير قابل للتغيير. المفاتيح في القاموس أعلاه هي: username online *followers المفاتيح في المثال أعلاه عبارة عن سلاسل نصية. تمثِّل الكلمات الموجودة على يمين النقطتين «القيم». يمكن أن تتألف القيم من أي نوع من البيانات. القيم في القاموس أعلاه هي: sammy-shark True *987 قيم القاموس أعلاه هي إمَّا سلاسل نصية أو قيم منطقية أو أعداد صحيحة. سنطبع الآن القاموس sammy: print(sammy) # {'username': 'sammy-shark', 'followers': 987, 'online': True} نلاحظ بالنظر إلى المخرجات تغير ترتيب الأزواج قيمة-مفتاح (key-value). في بايثون 3.5 وما قبله، إذ القواميس غير مرتبة. لكن ابتداءً من بايثون 3.6، صارت القواميس مرتبةً. بغض النظر عما إذا كان القاموس مرتبًا أم لا، ستظل الأزواج قيمة-مفتاح كما هي، وهذا سيمكّنك من الوصول إلى البيانات بناء على ترابطاتها. الوصول إلى عناصر القاموس يمكننا الوصول إلى قيم محدَّدة في القاموس بالرجوع إلى المفاتيح المرتبطة بها ويمكن أيضًا الاستعانة ببعض التوابع الجاهزة للوصول إلى القيم أو المفاتيح أو كليهما. الوصول إلى عناصر القاموس باستخدام المفاتيح إذا أردنا الحصول على اسم المستخدم في Sammy، فيمكننا ذلك عن طريق استدعاء sammy['username']‎. هذا مثال على ذلك: print(sammy['username']) # sammy-shark تتصرف القواميس كقواعد البيانات، فهي بدلًا من فهرسة العناصر بأعداد صحيحة، كما هو الحال في القوائم، فإنها تُفهرس العناصر (أو قيم القاموس) بمفاتيح، ويمكنك عبر تلك المفاتيح الحصول على القيم المقابلة لها. باستدعاء المفتاح username، سنحصل على القيمة المرتبطة به، وهي sammy-shark. وبالمِثل، يمكن استدعاء القيم الأخرى في القاموس sammy باستخدام نفس الصياغة: sammy['followers'] # 987 sammy['online'] # True استخدام التوابع للوصول إلى العناصر بالإضافة إلى استخدام المفاتيح للوصول إلى القيم، يمكننا أيضًا استخدام بعض التوابع المُضمّنة، مثل: dict.keys()‎‎: الحصول على المفاتيح dict.values()‎: الحصول على القيم dict.items()‎: الحصول على العناصر على هيئة قائمة من أزواج (key, value) لإعادة المفاتيح، نستخدم التابع dict.keys()‎، كما يوضح المثال التالي: print(sammy.keys()) # dict_keys(['followers', 'username', 'online']) تلقينا في المخرجات كائنَ عرض تكراري (iterable view object) من الصنف dict_keys يحوي المفاتيح ثم طُبِعت المفاتيح على هيئة قائمة. يمكن استخدام هذا التابع للاستعلام من القواميس. على سبيل المثال، يمكننا البحث عن المفاتيح المشتركة بين قاموسين: sammy = {'username': 'sammy-shark', 'online': True, 'followers': 987} jesse = {'username': 'JOctopus', 'online': False, 'points': 723} for common_key in sammy.keys() & jesse.keys(): print(sammy[common_key], jesse[common_key]) يحوي القاموسان sammy و jesse معلومات تعريف المستخدم. كما أنّ لهما مفاتيح مختلفة، لأنّ لدى Sammy ملف تعريف اجتماعي يضم مفتاحًا followers يمثل المتابعين على الشبكة الاجتماعية، أما Jesse فلها ملف تعريف للألعاب يضم مفتاحًا points يمثل النقاط. كلا القاموسين يشتركان في المفتاحين username و online، ويمكن العثور عليهما عند تنفيذ هذا البُريمج: # المخرجات sammy-shark JOctopus True False يمكننا بالتأكيد تحسين البرنامج لتسهيل قراءة المخرجات، ولكنّ الغرض هنا هو توضيح إمكانية استخدام dict.keys()‎ لرصد المفاتيح المشتركة بين عدة قواميس. هذا مفيد بشكل خاص عند العمل على القواميس الكبيرة. وبالمثل، يمكننا استخدام التابع dict.values()‎ للاستعلام عن القيم الموجودة في القاموس sammy على النحو التالي: sammy = {'username': 'sammy-shark', 'online': True, 'followers': 987} print(sammy.values()) # dict_values([True, 'sammy-shark', 987]) يُعيد كلا التابعان values()‎ و keys()‎‎ قوائم غير مرتبة تضم مفاتيح وقيم القاموس sammy على هيئة كائِني عرضٍ من الصنف dict_values و dict_keys على التوالي. إن أردت الحصول على الأزواج الموجودة في القاموس، فاستخدم التابع items()‎: print(sammy.items()) المخرجات ستكون: dict_items([('online', True), ('username', 'sammy-shark'), ('followers', 987)]) النتيجة المعادة ستكون على هيئة قائمة مكونة من أزواج (key, value) من الصنف dict_items. يمكننا التكرار (iterate) على القائمة المُعادة باستخدام الحلقة for. على سبيل المثال، يمكننا طباعة جميع مفاتيح وقيم القاموس المحدد، ثم جعلها أكثر مقروئية عبر إضافة سلسلة نصية توضيحية: for key, value in sammy.items(): print(key, 'is the key for the value', value) وسينتج لنا: online is the key for the value True followers is the key for the value 987 username is the key for the value sammy-shark كرَّرت الحلقة for على العناصر الموجودة في القاموس sammy، وطبعت المفاتيح والقيم سطرًا سطرًا، مع إضافة معلومات توضيحية. تعديل القواميس القواميس هي هياكل بيانات قابلة للتغيير (mutable)، أي يمكن تعديلها. في هذا القسم، سنتعلم كيفية إضافة عناصر إلى قاموس، وكيفية حذفها. إضافة وتغيير عناصر القاموس يمكنك إضافة أزواج قيمة-مفتاح إلى قاموس دون استخدام توابع أو دوال باستخدام الصياغة التالية: dict[key] = value في المثال التالي، سنضيف زوجًا مفتاح-قيمة إلى قاموس يُسمى usernames: usernames = {'Sammy': 'sammy-shark', 'Jamie': 'mantisshrimp54'} usernames['Drew'] = 'squidly' print(usernames) # {'Drew': 'squidly', 'Sammy': 'sammy-shark', 'Jamie': 'mantisshrimp54'} لاحظ أنّ القاموس قد تم تحديثه بالزوج 'Drew': 'squidly'. نظرًا لأنّ القواميس غير مرتبة، فيمكن أن يظهر الزوج المُضاف في أيّ مكان في مخرجات القاموس. إذا استخدمنا القاموس usernames لاحقًا، فسيظهر فيه الزوج المضاف حديثًا. يمكن استخدام هذه الصياغة لتعديل القيمة المرتبطة بمفتاح معيّن. في هذه الحالة، سنشير إلى مفتاح موجود سلفًا، ونمرر قيمة مختلفة إليه. سنعرِّف في المثال التالي قاموسًا باسم drew يمثِّل البيانات الخاصة بأحد المستخدمين على بعض الشبكات الاجتماعية. حصل هذا المستخدم على عدد من المتابعين الإضافيين اليوم، لذلك سنحدّث القيمة المرتبطة بالمفتاح followers ثم نستخدم التابع print()‎ للتحقق من أنّ القاموس قد عُدِّل. drew = {'username': 'squidly', 'online': True, 'followers': 305} drew['followers'] = 342 print(drew) # {'username': 'squidly', 'followers': 342, 'online': True} في المخرجات نرى أنّ عدد المتابعين قد قفز من 305 إلى 342. يمكننا استخدام هذه الطريقة لإضافة أزواج قيمة-مفتاح إلى القواميس عبر مدخلات المستخدم. سنكتب بريمجًا سريعًا، usernames.py، يعمل من سطر الأوامر ويسمح للمستخدم بإضافة الأسماء وأسماء المستخدمين المرتبطة بها: # تعريف القاموس الأصلي usernames = {'Sammy': 'sammy-shark', 'Jamie': 'mantisshrimp54'} # while إعداد الحلقة التكرارية while True: # اطلب من المستخدم إدخال اسم print('Enter a name:') # name تعيين المدخلات إلى المتغير name = input() # تحقق مما إذا كان الاسم موجودًا في القاموس ثم اطبع الرد if name in usernames: print(usernames[name] + ' is the username of ' + name) # إذا لم يكن الاسم في القاموس else: # اطبع الرد print('I don\'t have ' + name + '\'s username, what is it?') # خذ اسم مستخدم جديد لربطه بذلك الاسم username = input() # name عين قيمة اسم المستخدم إلى المفتاح usernames[name] = username # اطبع ردًا يبيّن أنّ البيانات قد حُدّثت print('Data updated.') سننفِّذ البرنامج من سطر الأوامر: python usernames.py عندما ننفّذ البرنامج، سنحصل على مخرجات مشابهة لما يلي: Enter a name: Sammy sammy-shark is the username of Sammy Enter a name: Jesse I don't have Jesse's username, what is it? JOctopus Data updated. Enter a name: عند الانتهاء من اختبار البرنامج، اضغط على CTRL + C للخروج من البرنامج. يمكنك تخصيص حرف لإنهاء البرنامج (مثل الحرف q)، وجعل البرنامج يُنصت له عبر العبارات الشرطية. يوضح هذا المثال كيف يمكنك تعديل القواميس بشكل تفاعلي. في هذا البرنامج، بمجرد خروجك باستخدام CTRL + C، ستفقد جميع بياناتك، إلا إن خزّنت البيانات في ملف. يمكننا أيضًا إضافة عناصر إلى القواميس وتعديلها باستخدام التابع dict.update()‎. هذا التابع مختلف عن التابع append()‎ الذي يُستخدم مع القوائم. سنضيف المفتاح followers في القاموس jesse أدناه، ونَمنحه قيمة عددية صحيحة بواسطة التابع jesse.update()‎. بعد ذلك، سنطبع القاموس المُحدّث. jesse = {'username': 'JOctopus', 'online': False, 'points': 723} jesse.update({'followers': 481}) print(jesse) # {'followers': 481, 'username': 'JOctopus', 'points': 723, 'online': False} من المخرجات، نتبيّن أننا نجحنا في إضافة الزوج ‎followers: 481 إلى القاموس jesse. يمكننا أيضًا استخدام التابع dict.update()‎ لتعديل زوج قيمة-مفتاح موجود سلفًا عن طريق استبدال قيمة مفتاح معيَّن. سنغيِّر القيمة المرتبطة بالمفتاح online في القاموس Sammy من True إلى False: sammy = {'username': 'sammy-shark', 'online': True, 'followers': 987} sammy.update({'online': False}) print(sammy) # {'username': 'sammy-shark', 'followers': 987, 'online': False} يغيّر السطر sammy.update({'online': False})‎ القيمة المرتبطة بالمفتاح 'online' من True إلى False. عند استدعاء التابع print()‎‎ على القاموس، يمكنك أن ترى في المخرجات أنّ التحديث قد تمّ. لإضافة عناصر إلى القواميس أو تعديل القيم، يمكن إمّا استخدام الصياغة dict[key] = value، أو التابع dict.update()‎. حذف عناصر من القاموس كما يمكنك إضافة أزواج قيمة-مفتاح إلى القاموس، أو تغيير قيمه، يمكنك أيضًا حذف العناصر الموجودة في القاموس. لتزيل زوج قيمة-مفتاح من القاموس، استخدم الصياغة التالية: del dict[key] لنأخذ القاموس jesse الذي يمثل أحد المستخدمين، ولنفترض أنّ jesse لم تعد تستخدم المنصة لأجل ممارسة الألعاب، لذلك سنزيل العنصر المرتبط بالمفتاح points. بعد ذلك، سنطبع القاموس لتأكيد حذف العنصر: jesse = {'username': 'JOctopus', 'online': False, 'points': 723, 'followers': 481} del jesse['points'] print(jesse) # {'online': False, 'username': 'JOctopus', 'followers': 481} يزيل السطر del jesse ['points']‎ الزوج 'points': 723 من القاموس jesse. إذا أردت محو جميع عناصر القاموس، فيمكنك ذلك باستخدام التابع dict.clear()‎. سيَبقى هذا القاموس في الذاكرة، وهذا مفيد في حال احتجنا إلى استخدامه لاحقًا في البرنامج، بيْد أنه سيُفرِّغ جميع العناصر من القاموس. دعنا نزيل كل عناصر القاموس jesse: jesse = {'username': 'JOctopus', 'online': False, 'points': 723, 'followers': 481} jesse.clear() print(jesse) # {} تُظهِر المخرجات أنّ القاموسًا صار فارغًا الآن. إذا لم تعد بحاجة إلى القاموس، فاستخدم del للتخلص منه بالكامل: del jesse print(jesse) إذا نفّذت الأمر print()‎ بعد حذف القاموس jesse، سوف تتلقى الخطأ التالي: NameError: name 'jesse' is not defined خلاصة ألقينا في هذه المقالة نظرة على القواميس في بايثون. تتألف القواميس من أزواج قيمة-مفتاح، وتوفر حلًّا ممتازًا لتخزين البيانات دون الحاجة إلى فهرستها. يتيح لنا ذلك استرداد القيم بناءً على معانيها وعلاقتها بأنواع البيانات الأخرى. يمكنك تعلم المزيد عن أنواع البيانات الأخرى من المقالة التالية: "فهم أنواع البيانات في بايثون 3". هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Dictionaries in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية استيراد الوحدات في بايثون 3 المقالة السابقة: فهم نوع البيانات Tuples في بايثون 3
  5. يبدو نوع البيانات tuple في بايثون كما يلي: coral = ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral') tuple (صف وتُجمَع إلى صفوف) هي بنية بيانات تُمثِّل سلسلة مرتبة من العناصر غير القابلة للتبديل، وبالتالي لا يمكن تعديل القيم الموجودة فيها. يستعمل نوع البيانات tuple لتجميع البيانات، فكل عنصر أو قيمة داخل tuple تُشكِّل جزءًا منه. توضع القيم داخل نوع البيانات tuple بين قوسين ( ) ويُفصَل بينها بفاصلة ,، وتبدو القيم الفارغة كما يلي coral = ()‎، لكن إذا احتوى نوع البيانات tuple على قيم –حتى لو كانت قيمةً واحدةً فقط– فيجب وضع فاصلة فيه مثل coral = ('blue coral',). إذا استخدمنا الدالة print()‎ على tuple، فسنحصل على الناتج الآتي الذي يُبيّن أنَّ القيمة الناتجة ستوضع بين قوسين: print(coral) ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral') عند التفكير بنوع tuple وغيره من بنى البيانات التي تُعبَر من أنوع «المجموعات» (collections)، فمن المفيد أن تضع ببالك مختلف المجموعات الموجودة في حاسوبك: تشكيلة الملفات الموجودة عندك، وقوائم التشغيل للموسيقى، والمفضلة الموجودة في متصفحك، ورسائل بريدك الإلكتروني، ومجموعة مقاطع الفيديو التي تستطيع الوصول إليها من التلفاز، والكثير. نوع tuple شبيه بالقوائم (lists)، لكن القيم الموجودة فيه لا يمكن تعديلها، وبسبب ذلك، فأنت تخبر الآخرين أنَّك لا تريد إجراء أيّة تعديلات على هذه السلسلة من القيم عندما تستعمل tuple في شيفرتك. إضافةً إلى ما سبق، ولعدم القدرة على تعديل القيم، فسيكون أداء برنامجك أفضل، حيث ستُنفَّذ الشيفرة بشكل أسرع إذا استعملتَ tuple بدلًا من القوائم (lists). فهرسة نوع البيانات tuple يمكن الوصول إلى كل عنصر من عناصر tuple بمفرده لأنَّه سلسلة مرتبة من العناصر، وذلك عبر الفهرسة. وكل عنصر يرتبط برقم فهرس، الذي هو عدد صحيح يبدأ من الفهرس 0. لمثال coral السابق، ستبدو الفهارس والقيم المرتبطة بها كالآتي: ‘blue coral’ ‘staghorn coral’ ‘pillar coral’ ‘elkhorn coral’ 0 1 2 3 العنصر الأول الذي يُمثِّل السلسلة النصية 'blue coral' تبدأ بالفهرس 0، وتنتهي القائمة بالفهرس رقم 3 المرتبط بالقيمة 'elkhorn coral'. ولأن كل عنصر من عناصر tuple له رقم فهرس مرتبط به، فسنتمكن من الوصول إلى عناصره فرادى. يمكننا الآن الوصول إلى عنصر معيّن في tuple عبر استخدام رقم الفهرس المرتبط به. print(coral[2]) pillar coral تتراوح قيم الفهارس في المتغير coral من 0 إلى 3 كما هو ظاهر في الجدول السابق، لذا يمكننا استدعاء العناصر الموجودة فيه فرادى كما يلي: coral[0] coral[1] coral[2] coral[3] إذا حاولنا استدعاء المتغير coral مع رقم فهرس أكبر من 3، فستظهر رسالة خطأ تشير إلى أنَّ الفهرس خارج المجال: print(coral[22]) IndexError: tuple index out of range إضافةً إلى أرقام الفهارس الموجبة، يمكننا أيضًا الوصول إلى الفهارس باستخدام رقم فهرس سالب، وذلك بالعد بدءًا من نهاية قائمة العناصر وسيرتبط آخر عنصر بالفهرس ‎-1، وهذا مفيدٌ جدًا إذا كان لديك متغير من النوع tuple وكان يحتوي عناصر كثيرة وأردتَ الوصول إلى أحد عناصره انطلاقًا من النهاية. ففي مثالنا السابق عن coral، إذا أردنا استخدام الفهارس السالبة فالناتج كالآتي: ‘elkhorn coral’ ‘pillar coral’ ‘staghorn coral’ ‘blue coral’ -1 -2 -3 -4 إذا أردنا طباعة العنصر 'blue coral' باستخدام الفهارس السالبة، فستبدو التعليمة كما يلي: print(coral[-4]) blue coral يمكننا إضافة العناصر النصية الموجودة في tuple إلى السلاسل النصية الأخرى باستخدام المعامل +: print('This reef is made up of ' + coral[1]) This reef is made up of staghorn coral استطعنا في المثال السابق إضافة عنصر موجود في الفهرس 1 مع السلسلة النصية 'This reef is made up of '، ويمكننا أيضًا استخدام المعامل + لإضافة بنيتَي tuple معًا. الخلاصة: يمكننا الوصول إلى كل عنصر من عناصر tuple على حدة باستخدام أرقام الفهارس (الموجبة أو السالبة) المرتبطة بها. تقطيع قيم tuple يمكننا استخدام الفهارس للوصول إلى عدِّة عناصر من tuple، أما التقطيع فيسمح لنا بالوصول إلى عدِّة قيم عبر إنشاء مجال من أرقام الفهارس المفصولة بنقطتين رأسيتين [x:y]. لنقل أننا نريد عرض العناصر الموجودة في وسط المتغير coral، يمكننا فعل ذلك بإنشاء قطعة جديدة: print(coral[1:3]) ('staghorn coral', 'pillar coral') عند إنشاء قطعة جديدة –كما في المثال السابق– فيمثِّل أوّل رقم مكان بدأ القطعة (متضمنةً هذا الفهرس)، ورقم الفهرس الثاني هو مكان نهاية القطعة (دون تضمين هذا الفهرس بالقطعة)، وهذا هو السبب وراء عرض المثال السابق للقيم المرتبطة بالعناصر الموجودة في الفهرسين 1 و 2. إذا أردتَ تضمين إحدى نهايتَي القائمة، فيمكنك حذف أحد الأرقام في التعبير tuple[x:y]، فمثلًا، لنقل أننا نريد عرض أوّل ثلاثة عناصر من coral، والتي هي 'blue coral' و 'staghorn coral' و 'pillar coral'، فيمكننا فعل ذلك كالآتي: print(coral[:3]) ('blue coral', 'staghorn coral', 'pillar coral') المثال السابق عرض العناصر من بداية القائمة وتوقف قبل العنصر ذي الفهرس 3. لتضمين كل العناصر الموجودة في نهاية tuple، فيمكننا عكس التعبير السابق: print(coral[1:]) ('staghorn coral', 'pillar coral', 'elkhorn coral') يمكننا استخدام الفهارس السالبة أيضًا عند التقطيع، كما فعلنا مع أرقام الفهارس الموجبة: print(coral[-3:-1]) print(coral[-2:]) ('staghorn coral', 'pillar coral') ('pillar coral', 'elkhorn coral') هنالك معاملٌ إضافيٌ يمكننا استعماله ويسمى «الخطوة»، ويُشير إلى عدد العناصر التي يجب تجاوزها بعد الحصول على أوّل عنصر من القائمة. حذفنا في جميع أمثلتنا السابقة معامل الخطوة، حيث القيمة الافتراضية له في بايثون هي 1، لذا سنحصل على جميع العناصر الموجودة بين الفهرسَين المذكورين. شكل هذا التعبير العام هو tuple[x:y:z]، إذ يُشير المعامل z إلى الخطوة. لنُنشِئ قائمةً أكبر، ثم نقسِّمها، ونعطيها القيمة 2 كخطوة: numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) print(numbers[1:11:2]) (1, 3, 5, 7, 9) التعبير numbers[1:11:2] سيطبع القيم الموجودة بين رقمين الفهرسين 1 (بما في ذلك العنصر المرتبط بالفهرس 1) و 11 (دون تضمين ذلك العنصر)، ومن ثم ستخبر قيمةُ الخطوة 2 البرنامجَ أنَّ يتخطى عنصرًا بين كل عنصرين. يمكننا حذف أوّل معاملين واستخدام معامل الخطوة بمفرده بتعبيرٍ برمجيٍ من الشكل tuple[::z]: print(numbers[::3]) (0, 3, 6, 9, 12) طبعنا في المثال السابق عناصر numbers بعد ضبط قيمة الخطوة إلى 3، وبالتالي سيتم تخطي عنصرين. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 الخلاصة: تقطيع tuples باستخدام أرقام الفهارس الموجبة والسالبة واستعمال معامل الخطوة يسمح لنا بالتحكم بالناتج الذي نريد عرضه. إضافة بنى tuple إلى بعضها يمكن أن نُضيف بنى tuple إلى بعضها أو أن «نضربها» (multiply)، تتم عملية الإضافة باستخدام المعامل +، أما عملية الضرب فباستخدام المعامل *. يمكن أن يُستخدَم المعامل + لإضافة بنيتَي tuple أو أكثر إلى بعضها بعضًا. يمكننا إسناد القيم الموجودة في بنيتَي tuple إلى بنية جديدة: coral = ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral') kelp = ('wakame', 'alaria', 'deep-sea tangle', 'macrocystis') coral_kelp = (coral + kelp) print(coral_kelp) الناتج: ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral', 'wakame', 'alaria', 'deep-sea tangle', 'macrocystis') وصحيحٌ أنَّ المعامل + يمكنه إضافة بنى tuple إلى بعضها، لكن يمكن أن يستعمل لإنشاء بنية tuple جديدة ناتجة عن جمع بنى أخرى، لكن لا يمكنه تعديل بنية tuple موجودة مسبقًا. أما المعامل * فيمكن استخدامه لضرب بنى tuple، فربما تريد إنشاء نسخ من الملفات الموجودة في أحد المجلدات إلى الخادوم أو مشاركة قائمة بالمقطوعات الموسيقية التي تحبها مع أصدقائك، ففي هذه الحالات سترغب بمضاعفة مجموعات من البيانات (أو «ضربها»). لنضرب البنية coral بالرقم 2 والبنية kelp بالرقم 3، ثم نسندها إلى بنى tuple جديدة: multiplied_coral = coral * 2 multiplied_kelp = kelp * 3 print(multiplied_coral) print(multiplied_kelp) الناتج: ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral', 'blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral') ('wakame', 'alaria', 'deep-sea tangle', 'macrocystis', 'wakame', 'alaria', 'deep-sea tangle', 'macrocystis', 'wakame', 'alaria', 'deep-sea tangle', 'macrocystis') يمكننا باستخدام المعامل * أن نُكرِّر (أو نُضاعِف) بنى tuple بأي عدد من المرات نشاء، مما سينُشِئ بنى tuple جديدة اعتمادًا على محتوى البنى الأصلية. الخلاصة هي أنَّ بنى tuple يمكن إضافتها إلى بعضها أو ضربها لتشكيل بنى tuple جديدة عبر استخدام المعاملَين + و *. دوال التعامل مع tuple هنالك دوال مُضمَّنة في لغة بايثون للتعامل مع بنى tuple، لننظر إلى بعضها. len()‎ وكما في السلاسل النصية والقوائم، يمكننا حساب طول (أو عدد عناصر) بنية tuple باستخدام الدالة len()‎ حيث نُمرِّر إليها بنية tuple كمعامل (parameter)، كما يلي: len(coral) هذه الدالة مفيدة إذا أردنا أن نَضمَن أنَّ لبنية tuple عدد عناصر معيّن، فمثلًا يمكننا الاستفادة من ذلك بمقارنة بنيتين مع بعضهما. إذا أردنا طباعة عدد عناصر kelp و numbers، فسيظهر الناتج الآتي: print(len(kelp)) print(len(numbers)) الناتج: 4 13 الناتج أعلاه يشير إلى أنَّ للبنية kelp أربعة عناصر: kelp = ('wakame', 'alaria', 'deep-sea tangle', 'macrocystis') أما البنية numbers فتملك ثلاثة عشر عنصرًا: numbers = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) وصحيحٌ أنَّ هذه الأمثلة عناصرها قليلة نسبيًا، إلا أنَّ الدالة len()‎ تستطيع أن تخبرنا بعدد عناصر بنى tuple الكبيرة. الدالتان max()‎ و min()‎ عندما نتعامل مع بنى tuple مكوَّنة من عناصر رقمية (بما فيها الأعداد الصحيحة والأرقام ذات الفاصلة العشرية)، فيمكننا استخدام الدالتين max()‎ و min()‎ للعثور على أكبر وأصغر قيمة موجودة في بنية tuple معيّنة. تسمح لنا هاتان الدالتان باستخراج معلومات تخص البيانات القابلة للإحصاء، مثل نتائج الامتحانات أو درجات الحرارة أو أسعار المنتجات …إلخ. لننظر إلى بنية tuple مكونة من أعداد عشرية: more_numbers = (11.13, 34.87, 95.59, 82.49, 42.73, 11.12, 95.57) للحصول على القيمة العظمى من بين القيم الآتية فعلينا تمرير بنية tuple إلى الدالة max()‎ كما في max(more_numbers)، وسنستخدم الدالة print()‎ لعرض الناتج: print(max(more_numbers)) 95.59 أعادت الدالة max()‎ أعلى قيمة في بنية more_numbers. وبشكلٍ شبيهٍ بما سبق نستخدم الدالة min()‎: print(min(more_numbers)) 11.12 أُعيدَ هنا أصغر رقم عشري موجودة في البنية. يمكن الاستفادة من الدالتين max()‎ و min()‎ كثيرًا للتعامل مع بنى tuple التي تحتوي الكثير من القيم. كيف تختلف بنى tuple عن القوائم (list) الفرق الرئيسي بين tuple و list هو عدم القدرة على تعديلها، وهذا يعني أنَّنا لا نستطيع إضافة أو حذف أو استبدال العناصر داخل بنية tuple. لكن يمكننا إضافة بنيتَي tuple أو أكثر إلى بعضها بعضًا لتشكيل بنية جديدة كما رأينا في أحد الأقسام السابقة. لتكن لدينا البنية coral الآتية: coral = ('blue coral', 'staghorn coral', 'pillar coral', 'elkhorn coral') لنقل أننا نريد استبدال العنصر 'blue coral' ووضع العنصر 'black coral' بدلًا منه. فلو حاولنا تغيير بنية tuple بنفس الطريقة التي نُعدِّل فيها القوائم بكتابة: coral[0] = 'black coral' فستظهر رسالة خطأ كالآتية: TypeError: 'tuple' object does not support item assignment وذلك بسبب عدم إمكانية تعديل بنى tuple. إذا أنشأنا بنية tuple ثم قررنا أنَّ ما نحتاج له هو بنية list، فيمكننا تحويلها إلى قائمة list، وذلك بالدالة list()‎: list(coral) أصبحت بنية coral قائمةً الآن: coral = ['blue coral', 'staghorn coral', 'pillar coral'] يمكننا أن نلاحظ أنَّ بنية tuple تحوَّلتَ إلى قائمة list لأنَّ الأقواس المحيطة بالقيم أصبح مربعة الشكل. وبشكلٍ شبيهٍ بما سبق، نستطيع تحويل القوائم من النوع list إلى tuple باستخدام الدالة tuple()‎. الخلاصة نوع البيانات tuple هو مجموعةٌ من البيانات المتسلسلة التي لا يمكن تعديلها، ويوفِّر تحسينًا في أداء برامجك لأنه أسرع معالجةً من القوائم في بايثون. وعندما يراجع الآخرون شيفرتك فسيعلمون من استخدامك لبنى tuple أنك لا تريد تعديل هذه القيم. شرحنا في هذا الدرس الميزات الأساسية لبنى tuple بما في ذلك الفهارس وتقطيعها وتجميعها، وعرضنا بعض الدوال المُضمَّنة المتوافرة لهذا النوع من البيانات. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة –وبتصرّف– للمقال Understanding Tuples in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم القواميس في بايثون 3 المقالة السابقة: فهم كيفية استعمال List Comprehensions في بايثون 3
  6. يتضمّن بايثون عددًا من هياكل البيانات، بما في ذلك القوائم. تمكّن هياكل البيانات من تنظيم البيانات وتخزينها عبر توابع خاصة مُضمّنة في بايثون. للاستفادة من محتويات هذه المقالة، ينبغي أن تكون على إلمام بأساسيات القوائم، وصياغتها وكيفية فهرستها. يمكنك تعلم ذلك من المقالة السابقة: القوائم في بايثون 3. سنتعرف على التوابع المُضمنة التي يمكن استخدامها مع القوائم. ونتعلم كيفية إضافة عناصر إلى القائمة وكيفية إزالتها، وتوسيع القوائم وترتيبها، وغير ذلك. القوائم أنواعٌ قابلةٌ للتغيير (mutable) على عكس السلاسل النصية التي لا يمكن تغييرها، فعندما تستخدم تابعًا على قائمة ما، ستؤثر في القائمة نفسها، وليس في نسخة منها. سنعمل في هذه المقالة على قائمة تمثل حوض سمك، إذ ستحوي القائمة أسماء أنواع الأسماك الموجودة في الحوض، وسنعدلها كلما أضفنا أسماكًا أو أزلناها من الحوض. التابع list.append()‎‎ يضيف التابع list.append(x)‎ عنصرًا (x) إلى نهاية القائمة. يُعرّف المثال التالي قائمةً تمثل الأسماك الموجودة في حوض السمك. fish = ['barracuda','cod','devil ray','eel'] تتألف هذه القائمة من 4 سلاسل نصية، وتتراوح فهارسها من 0 إلى 3. سنضيف سمكة جديدة إلى الحوض، ونود بالمقابل أن نضيف تلك السمكة إلى قائمتنا. سنمرّر السلسلة النصية flounder التي تمثل نوع السمكة الجديدة إلى التابع list.append()‎، ثم نطبع قائمتنا المعدلة لتأكيد إضافة العنصر. fish.append('flounder') print(fish) # ['barracuda', 'cod', 'devil ray', 'eel', 'flounder'] الآن، صارت لدينا قائمة من 5 عناصر، تنتهي بالعنصر الذي أضفناه للتو عبر التابع append()‎. التابع list.insert()‎ يأخذ التابع list.insert (i,x)‎ وسيطين: الأول i يمثِّل الفهرس الذي ترغب في إضافة العنصر عنده، و x يمثل العنصر نفسه. لقد أضفنا إلى حوض السمك سمكة جديدة من نوع anchovy. ربما لاحظت أنّ قائمة الأسماك مرتبة ترتيبًا أبجديًا حتى الآن. لهذا السبب لا نريد إفساد الترتيب، لذا لن نضيف السلسلة النصية anchovy إلى نهاية القائمة باستخدام الدالة list.append()‎. بدلًا من ذلك، سنستخدم التابع list.insert()‎ لإضافة anchovy إلى بداية القائمة، أي عند الفهرس 0: fish.insert(0,'anchovy') print(fish) # ['anchovy', 'barracuda', 'cod', 'devil ray', 'eel', 'flounder'] في هذه الحالة، أضفنا العنصر إلى بداية القائمة. ستتقدم فهارس العناصر التالية خطوةً واحدةً إلى الأمام. لذلك، سيصبح العنصر barracuda عند الفهرس 1، والعنصر cod عند الفهرس 2، والعنصر flounder - الأخير - عند الفهرس 5. سنحضر الآن سمكة من نوع damselfish إلى الحوض، ونرغب في الحفاظ على الترتيب الأبجدي لعناصر القائمة أعلاه، لذلك سنضع هذا العنصر عند الفهرس 3: fish.insert(3,'damselfish')‎. التابع list.extend()‎ إذا أردت أن توسّع قائمة بعناصر قائمة أخرى، فيمكنك استخدام التابع list.extend(L)‎، والذي يأخذ قائمة كمعامل. سنضع في الحوض أربعة أسماك جديدة. أنواع هذه الأسماك مجموعة معًا في القائمة more_fish: more_fish = ['goby','herring','ide','kissing gourami'] سنضيف الآن عناصر القائمة more_fish إلى قائمة الأسماك، ونطبع القائمة لنتأكد من أنّ عناصر القائمة الثانية قد ضُمّت إليها: fish.extend(more_fish) print(fish) ستطبع بايثون القائمة التالية: ['anchovy', 'barracuda', 'cod', 'devil ray', 'eel', 'flounder', 'goby', 'herring', 'ide', 'kissing gourami'] في هذه المرحلة، صارت القائمة fish تتألف من 10 عناصر. التابع list.remove()‎ لإزالة عنصر من قائمة، استخدم التابع list.remove(x)‎، والذي يزيل أول عنصر من القائمة له القيمة المُمرّرة x. جاءت مجموعة من العلماء المحليين لزيارة الحوض. سيجرون أبحاثًا عن النوع kissing gourami، وطلبوا استعارة السمكة kissing gourami، لذلك نود إزالة العنصر kissing gourami من القائمة لنعكس هذا التغيير: fish.remove('kissing gourami') print(fish) والمخرجات ستكون: ['anchovy', 'barracuda', 'cod', 'devil ray', 'eel', 'flounder', 'goby', 'herring', 'ide'] بعد استخدام التابع list.remove()‎، لم يعد العنصر kissing gourami موجودًا في القائمة. في حال مرّرت عنصرًا x غير موجود في القائمة إلى التابع list.remove()‎، فسيُطلق الخطأ التالي: ValueError: list.remove(x): x not in list التابع list.remove()‎ لن يزيل إلا أول عنصر تساوي قيمته قيمة العنصر المُمرّر إلى التابع، لذلك إن كانت لدينا سمكتان من النوع kissing gourami في الحوض، وأعرنا إحداهما فقط للعلماء، فإنّ التعبير fish.remove('kissing gourami')‎ لن يمحو إلا العنصر الأول المطابق فقط. التابع list.pop()‎ يعيد التابع list.pop ()‎ العنصر الموجود عند الفهرس المحدد من القائمة، ثم يزيل ذلك العنصر. تشير الأقواس المربعة حول i إلى أنّ هذا المعامل اختياري، لذا، إذا لم تحدد فهرسًا (كما في fish.pop()‎)، فسيُعاد العنصر الأخير ثم يُزال. لقد أصبح حجم السمكة devil ray كبيرًا جدًا، ولم يعد الحوض يسعها، ولحسن الحظ أنّ هناك حوض سمك في بلدة مجاورة يمكنه استيعابها. سنستخدم التابع ‎.‎pop()‎، ونمرر إليه العدد 3، الذي يساوي فهرس العنصر devil ray، بقصد إزالته من القائمة. بعد إعادة العنصر، سنتأكد من أننا أزلنا العنصر الصحيح. print(fish.pop(3)) # devil ray print(fish) # ['anchovy', 'barracuda', 'cod', 'eel', 'flounder', 'goby', 'herring', 'ide'] باستخدام التابع ‎.pop()‎ تمكّنا من إعادة وإزالة ray devil من قائمة الأسماك. إذا لم نمرر أيّ معامل إلى هذا التابع، ونفّذنا التعبير fish.pop()‎، فسيُعاد العنصر الأخير ide ثم يُزَال من القائمة. التابع list.index()‎ يصعب في القوائم الكبيرة تحديد فهارس العناصر التي تحمل قيمة معينة. لأجل ذلك، يمكننا استخدام التابع list.index(x)‎، حيث يمثل الوسيطx قيمة العنصر المبحوث عنه، والذي نريد إعادة فهرسه. إذا كان هناك أكثر من عنصر واحد يحمل القيمة x، فسيُعَاد فهرس العنصر الأول. print(fish) # ['anchovy', 'barracuda', 'cod', 'eel', 'flounder', 'goby', 'herring', 'ide'] print(fish.index('herring')) # 6 سوف يُطلق خطأ في حال مرّرنا قيمة غير موجودة في القائمة إلى التابع ‎.index()‎. التابع list.copy()‎ أحيانُا نرغب في تعديل عناصر قائمةٍ والتجريب عليها، مع الحفاظ على القائمة الأصلية دون تغيير؛ يمكننا في هذه الحالة استخدام التابع list.copy()‎ لإنشاء نسخة من القائمة الأصلية. في المثال التالي، سنمرّر القيمة المعادة من fish.copy()‎ إلى المتغير fish_2، ثم نطبع قيمة fish_2 للتأكد من أنها تحتوي على نفس عناصر القائمة fish. fish_2 = fish.copy() print(fish_2) # ['anchovy', 'barracuda', 'cod', 'eel', 'flounder', 'goby', 'herring', 'ide'] في هذه المرحلة، القائمتان fish و fish_2 متساويتان. التابع list.reverse()‎ يمكننا عكس ترتيب عناصر قائمة باستخدام التابع list.reverse()‎. في المثال التالي سنستخدم التابع ‎.reverse()‎ مع القائمة fish لعكس ترتيب عناصرها. fish.reverse() print(fish) # ['ide', 'herring', 'goby', 'flounder', 'eel', 'cod', 'barracuda', 'anchovy'] بعد استخدام التابع ‎.reverse()‎، صارت القائمة تبدأ بالعنصر ide، والذي كان في نهاية القائمة من قبل، كما ستنتهي القائمة بالعنصر anchovy، والذي كان في بداية القائمة من قبل. التابع list.count()‎ يعيد التابع list.count(x)‎ عدد مرات ظهور القيمة x في القائمة. هذا التابع مفيد في حال كنا نعمل على قائمة طويلة بها الكثير من القيم المتطابقة. إذا كان حوض السمك كبيرًا، على سبيل المثال، وكانت عندنا عدة أسماك من النوع neon tetra، فيمكننا استخدام التابع ‎.count()‎ لتحديد العدد الإجمالي لأسماك هذا النوع. في هذا المثال سنحسب عدد مرات ظهور العنصر goby: print(fish.count('goby')) # 1 تظهر السلسلة النصية goby مرةً واحدةً فقط في القائمة، لذا سيُعيد التابع ‎.count()‎ العدد 1. يمكننا استخدام هذا التابع أيضًا مع قائمة مكوَّنة من أعداد صحيحة. المثال التالي يوضح ذلك. يتتبع المشرفون على الحوض أعمار الأسماك الموجودة فيه للتأكد من أنّ وجباتها الغذائية مناسبة لأعمارها. هذه القائمة الثانية المُسماة fish_ages تتوافق مع أنواع السمك في القائمة fish. نظرًا لأنّ الأسماك التي لا يتجاوز عمرها عامًا واحدًا لها احتياجات غذائية خاصة، فسنحسب عدد الأسماك التي عمرها عامًا واحدًا: fish_ages = [1,2,4,3,2,1,1,2] print(fish_ages.count(1)) # 3 يظهر العدد الصحيح 1 في القائمة fish_ages ثلاث مرات، لذلك يعيد التابع ‎.count()‎ العدد 3. التابع list.sort()‎ يُستخدم التابع list.sort()‎ لترتيب عناصر القائمة التي استُدعِي معها . سنستخدم قائمة الأعداد الصحيحة fish_ages لتجريب التابع ‎.sort()‎: fish_ages.sort() print(fish_ages) # [1, 1, 1, 2, 2, 2, 3, 4] باستدعاء التابع ‎.sort()‎ مع القائمة fish_ages، ستُعاد قائمة الأعداد الصحيحة مرتبةً. التابع list.clear()‎ بعد الانتهاء من العمل على قائمة ما، يمكنك إزالة جميع القيم الموجودة فيها باستخدام التابع list.clear()‎. قررت الحكومة المحلية الاستيلاء على حوض السمك الخاص بنا، وجعله مساحة عامة يستمتع بها سكان مدينتنا. نظرًا لأننا لم نعد نعمل على الحوض، فلم نعد بحاجة إلى الاحتفاظ بقائمة الأسماك، لذلك سنزيل عناصر القائمة fish: fish.clear() print(fish) # [] نرى في المخرجات أقواسًا معقوفة نتيجة استدعاء التابع ‎.clear()‎ على القائمة fish، وهذا تأكيد على أنّ القائمة أصبحت خالية من جميع العناصر. خلاصة لمَّا كانت القوائم تسلسلات قابلة للتغيير (mutable)، فإنّها هياكلُ بيانات مرنة ومفيدة للغاية. كما تتيح لنا توابع القوائم إجراء العديد من العمليات على القوائم بسهولة، إذ يمكننا استخدام التوابع لتعديل القوائم وترتيبها ومعالجتها بفعالية. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Use List Methods in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم كيفية استعمال List Comprehensions في بايثون 3 المقالة السابقة: مدخل إلى القوائم في بايثون 3
  7. القائمة هي بنية بيانات في بايثون، وهي عبارة عن تسلسل مُرتّب من العناصر قابل للتغيير (mutable). table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } القوائم مناسبة لتجميع العناصر المترابطة، إذ تمكّنك من تجميع البيانات المتشابهة، أو التي تخدم غرضًا معيّنا معًا، وتكثيف الشيفرة البرمجية، وتنفيذ التوابع والعمليات على عدة قيم في وقت واحد. القوائم في بايثون وغيرها من هياكل البيانات المركبة تساعد على تمثيل المجموعات، مثل مجموعة الملفات في مجلد على حاسوبك، أو قوائم التشغيل، ورسائل البريد الإلكتروني، وغير ذلك. في المثال التالي، سننشئ قائمةً تحتوي على عناصر من نوع السلاسل النصية: sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis shrimp', 'anemone'] عندما نطبع القائمة، فإنّ المخرجات ستشبه القائمة التي أنشأناها: print(sea_creatures) # ['shark', 'cuttlefish', 'squid', 'mantis shrimp', 'anemone'] باعتبارها تسلسلًا مرتبًا من العناصر، يمكن استدعاء أيّ عنصر من القائمة عبر الفهرسة. القوائم هي بيانات مركبة تتألف من أجزاء أصغر، وتتميز بالمرونة، إذ يمكن إضافة عناصر إليها، وإزالتها، وتغييرها. عندما تحتاج إلى تخزين الكثير من القيم، أو التكرار (iterate) عليها، وتريد أن تكون قادرًا على تعديل تلك القيم بسهولة، فالقوائم هي خيارك الأفضل. سنتعرف في هذه المقالة على القوائم وتوابعها وكيفية استخدامها. فهرسة القوائم (Indexing Lists) كل عنصر في القائمة يقابله رقم يمثل فهرسَ ذلك العنصر، والذي هو عدد صحيح، فهرس العنصر الأول في القائمة هو 0. هذا تمثيل لفهارس القائمة sea_creatures: shark cuttlefish squid shrimp anemone 0 1 2 3 4 يبدأ العنصر الأول، أي السلسلة النصية shark، عند الفهرس 0، وتنتهي القائمة عند الفهرس 4 الذي يقابل العنصر anemone. نظرًا لأنّ كل عنصر في قوائم بايثون يقابله رقم فهرس، يمكننا الوصول إلى عناصر القوائم ومعالجتها كما نفعل مع أنواع البيانات المتسلسلة الأخرى. يمكننا الآن استدعاء عنصر من القائمة من خلال رقم فهرسه: print(sea_creatures[1]) # cuttlefish تتراوح أرقام الفهارس في هذه القائمة بين 0 و 4، كما هو موضح في الجدول أعلاه. المثال التالي يوضح ذلك: sea_creatures[0] = 'shark' sea_creatures[1] = 'cuttlefish' sea_creatures[2] = 'squid' sea_creatures[3] = 'mantis shrimp' sea_creatures[4] = 'anemone' إذا استدعينا القائمة sea_creatures برقم فهرس أكبر من 4، فسيكون الفهرس خارج النطاق، وسيُطلَق الخطأ IndexError: print(sea_creatures[18]) والمخرجات ستكون: IndexError: list index out of range يمكننا أيضًا الوصول إلى عناصر القائمة بفهارس سالبة، والتي تُحسَب من نهاية القائمة، بدءًا من ‎-1. هذا مفيد في حال كانت لدينا قائمة طويلة، وأردنا تحديد عنصر في نهايته. بالنسبة لقائمة sea_creatures، تبدو الفهارس السالبة كما يلي: shark cuttlefish squid shrimp anemone -5 -4 -3 -2 -1 في المثال التالي، سنطبع العنصر squid باستخدام فهرس سالب: print(sea_creatures[-3]) # squid يمكننا ضم (concatenate) عنصر يحتوي سلسلة نصية مع سلسلة نصبة أخرى باستخدام العامل +: print('Sammy is a ' + sea_creatures[0]) # Sammy is a shark لقد ضممنا السلسلة النصية Sammy is a مع العنصر ذي الفهرس 0. يمكننا أيضًا استخدام العامل + لضمّ قائمتين أو أكثر معًا (انظر الفقرة أدناه): تساعدنا الفهارس على الوصول إلى أيّ عنصر من عناصر القائمة والعمل عليه. تعديل عناصر القائمة يمكننا استخدام الفهرسة لتغيير عناصر القائمة، عن طريق إسناد قيمة إلى عُنصر مُفهرس من القائمة. هذا يجعل القوائم أكثر مرونة، ويسهّل تعديل وتحديث عناصرها. إذا أردنا تغيير قيمة السلسلة النصية للعنصر الموجود عند الفهرس 1، من القيمة cuttlefish إلى octopus، فيمكننا القيام بذلك على النحو التالي: sea_creatures[1] = 'octopus' الآن، عندما نطبع sea_creatures، ستكون النتيجة: print(sea_creatures) # ['shark', 'octopus', 'squid', 'mantis shrimp', 'anemone'] يمكننا أيضًا تغيير قيمة عنصر باستخدام فهرس سالب: sea_creatures[-3] = 'blobfish' print(sea_creatures) # ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone'] الآن استبدلنا بالسلسلة squid السلسلة النصية blobfish الموجودة عند الفهرس السالب ‎-3 (والذي يتوافق مع الفهرس الموجب 2). اقتطاع القوائم (Slicing Lists) يمكننا أيضا استدعاء عدة عناصر من القائمة. لنفترض أننا نرغب في طباعة العناصر الموجودة في وسط القائمة sea_creatures، يمكننا القيام بذلك عن طريق اقتطاع شريحة (جزء) من القائمة. يمكننا باستخدام الشرائح استدعاء عدة قيم عن طريق إنشاء مجال من الفهارس مفصولة بنقطتين [x: y]: print(sea_creatures[1:4]) # ['octopus', 'blobfish', 'mantis shrimp'] عند إنشاء شريحة، كما في [‎1: 4]، يبدأ الاقتطاع من العنصر ذي الفهرس الأول (مشمولًا)، وينتهي عند العنصر ذي الفهرس الثاني (غير مشمول)، لهذا طُبعَت في مثالنا أعلاه العناصر الموجودة في المواضع، 1، و 2، و 3. إذا أردنا تضمين أحد طرفي القائمة، فيمكننا حذف أحد الفهرسَين في التعبير [x: y]. على سبيل المثال، إذا أردنا طباعة العناصر الثلاثة الأولى من القائمة sea_creatures، يمكننا فعل ذلك عن طريق كتابة: print(sea_creatures[:3]) # ['shark', 'octopus', 'blobfish'] لقد تم طبع العناصر من بداية القائمة حتّى العنصرٍ ذي الفهرس 3. لتضمين جميع العناصر الموجودة في نهاية القائمة، سنعكس الصياغة: print(sea_creatures[2:]) # ['blobfish', 'mantis shrimp', 'anemone'] يمكننا أيضًا استخدام الفهارس السالبة عند اقتطاع القوائم، تمامًا كما هو الحال مع الفهارس الموجبة: print(sea_creatures[-4:-2]) # ['octopus', 'blobfish'] print(sea_creatures[-3:]) # ['blobfish', 'mantis shrimp', 'anemone'] هناك معامل آخر يمكننا استخدامه في الاقتطاع، ويشير إلى عدد العناصر التي يجب أن يتم القفز عليها (أو الخطوة) بعد استرداد العنصر الأول من القائمة. حتى الآن، لقد أغفلنا المعامل stride، وستعطيه بايثون القيمة الافتراضية 1، ما يعني أنه سيتم استرداد كل العناصر الموجودة بين الفهرسَين المحددين. ستكون لصياغة على الشكل التالي [x: y: z]، إذ يشير z إلى الخطوة (stride). في المثال التالي، سننشئ قائمة كبيرة، ثم نقتطعها، مع خطوة اقتطاع تساوي 2: numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] print(numbers[1:11:2]) # [1, 3, 5, 7, 9] سيطبع التعبير numbers[‎1: 11: 2]‎ القيم ذات الفهارس المحصورة بين 1 (مشمولة) و 11 (غير مشمولة)، وسيقفز البرنامج بخطوتين كل مرة، ويطبع العناصر المقابلة. يمكننا حذف المُعاملين الأوّليين، واستخدام الخطوة وحدها كمعامل وفق الصياغة التالية: [‎::z]: print(numbers[::3]) # [0, 3, 6, 9, 12] عند طباعة القائمة ‎numbers مع تعيين الخطوة عند القيمة 3، فلن تُطبع إلا العناصر التي فهارسها من مضاعفات 3: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 يجعل استخدام الفهارس الموجبة والسالبة ومعامل الخطوة في اقتطاع القوائم التحكم في القوائم ومعالجتها أسهل وأكثر مرونة. تعديل القوائم بالعوامل يمكن استخدام العوامل لإجراء تعديلات على القوائم. سننظر في استخدام العاملين + و * ومقابليهما المركبين ‎+=‎ و ‎*=‎‎. يمكن استخدام العامل + لضمّ (concatenate) قائمتين أو أكثر معًا: sea_creatures = ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone'] oceans = ['Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic'] print(sea_creatures + oceans) والمخرجات هي: ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic'] يمكن استخدام العامل + لإضافة عنصر (أو عدة عناصر) إلى نهاية القائمة. لكن تذكر أن تضع العنصر بين قوسين مربعين: sea_creatures = sea_creatures + ['yeti crab'] print (sea_creatures) # ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab'] يمكن استخدام العامل * لمضاعفة القوائم (multiply lists). ربما تحتاج إلى عمل نُسِخٍ لجميع الملفات الموجودة في مجلد على خادم، أو مشاركة قائمة أفلام مع الأصدقاء؛ ستحتاج في هذه الحالات إلى مضاعفة مجموعات البيانات. سنضاعف القائمة sea_creatures مرتين، والقائمة oceans ثلاث مرات: print(sea_creatures * 2) print(oceans * 3) والنتيجة ستكون: ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab', 'shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab'] ['Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic', 'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic', 'Pacific', 'Atlantic', 'Indian', 'Southern', 'Arctic'] يمكننا باستخدام العامل * نسخ القوائم عدة مرات. يمكننا أيضًا استخدام الشكلين المركبين للعاملين + و * مع عامل الإسناد =. يمكن استخدام العاملين المركبين ‎+=‎ و ‎*=‎ لملء القوائم بطريقة سريعة ومُؤتمتة. يمكنك استخدام هذين العاملين لملء القوائم بعناصر نائبة (placeholders) يمكنك تعديلها في وقت لاحق بالمدخلات المقدمة من المستخدم على سبيل المثال. في المثال التالي، سنضيف عنصرًا إلى القائمة sea_creatures. سيعمل هذا العنصر مثل عمل العنصر النائب، ونود إضافة هذا العنصر النائب عدة مرات. لفعل ذلك، سنستخدم ‎+=‎ العامل مع الحلقة for. for x in range(1,4): sea_creatures += ['fish'] print(sea_creatures) والمخرجات ستكون: ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab', 'fish'] ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab', 'fish', 'fish'] ['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab', 'fish', 'fish', 'fish'] سيُضاف لكل تكرار في الحلقة for عنصر fish إلى القائمة sea_creatures. العامل ‎*=‎ يتصرف بطريقة مماثلة: sharks = ['shark'] for x in range(1,4): sharks *= 2 print(sharks) الناتج سيكون: ['shark', 'shark'] ['shark', 'shark', 'shark', 'shark'] ['shark', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark'] إزالة عنصر من قائمة يمكن إزالة العناصر من القوائم باستخدام التعبير del. سيؤدي ذلك إلى حذف العنصر الموجود عند الفهرس المحدد. سنزيل من القائمة sea_creatures العنصر octopus. هذا العنصر موجود عند الفهرس 1. لإزالة هذا العنصر، سنستخدم العبارة del ثم نستدعي متغير القائمة وفهرس ذلك العنصر: sea_creatures =['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab'] del sea_creatures[1] print(sea_creatures) # ['shark', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab'] الآن، العنصر الموجود عند الفهرس 1، أي السلسلة النصية octopus، لم يعد موجودًا في قائمتنا. يمكننا أيضًا تحديد مجال مع العبارة del. لنقل أننا نريد إزالة العناصر octopus، و blobfish و mantis shrimp معًا. يمكننا فعل ذلك على النحو التالي: sea_creatures =['shark', 'octopus', 'blobfish', 'mantis shrimp', 'anemone', 'yeti crab'] del sea_creatures[1:4] print(sea_creatures) # ['shark', 'anemone', 'yeti crab'] باستخدام مجال مع العبارة del، تمكنا من إزالة العناصر الموجودة بين الفهرسَين 1 (مشمول) و 4 (غير مشمول)، والقائمة أضحت مكوّنة من 3 عناصر فقط بعد إزالة 3 عناصر منها. بناء قوائم من قوائم أخرى موجودة يمكن أن تتضمّن عناصر القوائم قوائم أخرى، مع إدراج كل قائمة بين قوسين معقوفين داخل الأقواس المعقوفة الخارجية التابعة لقائمة الأصلية: sea_names = [['shark', 'octopus', 'squid', 'mantis shrimp'],['Sammy', 'Jesse', 'Drew', 'Jamie']] تسمى القوائم المُتضمّنة داخل قوائم أخرى بالقوائم المتشعبة (nested lists). للوصول إلى عنصر ضمن هذه القائمة، سيتعيّن علينا استخدام فهارس متعددة: print(sea_names[1][0]) # Sammy print(sea_names[0][0]) # shark فهرس القائمة الأولى يساوي 0، والقائمة الثانية فهرسُها 1. ضمن كل قائمة متشعبة داخلية، سيكون هناك فهارس منفصلة، والتي سنسميها فهارس ثانوية: sea_names[0][0] = 'shark' sea_names[0][1] = 'octopus' sea_names[0][2] = 'squid' sea_names[0][3] = 'mantis shrimp' sea_names[1][0] = 'Sammy' sea_names[1][1] = 'Jesse' sea_names[1][2] = 'Drew' sea_names[1][3] = 'Jamie' عند العمل مع قوائم مؤلّفة من قوائم، من المهم أن تعي أنك ستحتاج إلى استخدام أكثر من فهرس واحد للوصول إلى عناصر القوائم المتشعبة. خلاصة القوائم هي نوع بيانات مرن يمكن تعديله بسهولة خلال أطوار البرنامج. غطينا في هذه المقالة الميزات والخصائص الأساسية لقوائم، بما في ذلك الفهرسة والاقتطاع والتعديل والضّم. يمكنك تعلم المزيد عن القوائم من هاتين المقالتين: كيفية استخدام توابع القوائم في بايثون 3 فهم كيفية استعمال List Comprehensions في بايثون 3 هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Lists in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية استخدام توابع القوائم في بايثون 3 المقالة السابقة: فهم العمليات المنطقية في بايثون 3
  8. هناك قيمتان فقط لنوع البيانات المنطقية، وهما True و False. تُستخدم الحسابات المنطقية في البرمجة لإجراء الموازنات، والتحكم في مسار البرنامج. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } تمثِّل القيم المنطقية قيم الحقيقة (truth values) في علم المنطق في الرياضيات. وتٌكتب القيمتان True و False دائمًا بالحرفين الكبيرين T و F على التوالي، لأنهما قيمتان خاصتان في بايثون. في هذه المقالة، سنتعرف على العمليات المنطقية في بايثون، بما في ذلك الموازنة المنطقية، والعوامل المنطقية، وجداول الحقيقة. عوامل الموازنة في البرمجة، تُستخدم عوامل الموازنة للموازنة بين القيم، وتعيد إحدى القيمتين المنطقتين True و False. يوضح الجدول أدناه عوامل الموازنة المنطقية. العامل الشرح == تساوي != تخالف < أصغر من > أكبر من <= أصغر من أو تساوي >= أكبر من أو تساوي لفهم كيفية عمل هذه العوامل، سنستخدم المتغيرين التاليين: x = 5 y = 8 في هذا المثال، لمّا كان x يساوي 5، فهو أصغر من y ذي القيمة 8. باستخدام هذين المتغيرين والقيم المرتبطة بهما، سنجرّب العوامل من الجدول أعلاه. سنطلب من بايثون أن تطبع ناتج عملية الموازنة، إما True أو False. لتوضيح المثال أكثر، سنطبع سلسلة نصية لتوضيح ما جرى تقييمه. x = 5 y = 8 print("x == y:", x == y) print("x != y:", x != y) print("x < y:", x < y) print("x > y:", x > y) print("x <= y:", x <= y) print("x >= y:", x >= y) والمخرجات هي: x == y: False x != y: True x < y: True x > y: False x <= y: True x >= y: False باتباع المنطق الرياضي، في كل من التعبيرات المذكورة أعلاه، هذه نتيجة الموازنات: 5 (x) تساوي 8 (y)؟ خطأ 5 تخالف 8؟ صح 5 أصغر من 8؟ صح 5 أكبر من 8؟ خطأ 5 أصغر من أو يساوي 8؟ صح 5 ليس أصغر من أو يساوي 8؟ خطأ رغم أننا استخدمنا الأعداد الصحيحة هنا، إلا أنه بإمكاننا استبدال الأعداد العشرية بها. يمكن أيضًا استخدام السلاسل النصية مع العوامل المنطقية. وهي حساسة لحالة الأحرف، ما لم تستخدم تابعًا إضافيًا للسلاسل النصية. المثال التالي يوضح كيفية موازنة السلاسل النصية: Sammy = "Sammy" sammy = "sammy" print("Sammy == sammy: ", Sammy == sammy) # Sammy == sammy: False السلسلة "Sammy" أعلاه لا تساوي السلسلة النصية "sammy"، لأنهما ليستا متماثلتين تمامًا؛ فإحداهما تبدأ بحرف كبير S، والأخرى بحرف صغير s. ولكن لو أضفنا متغيرًا آخر قيمته "Sammy"، فستكونان متساويتين: Sammy = "Sammy" sammy = "sammy" also_Sammy = "Sammy" print("Sammy == sammy: ", Sammy == sammy) # Sammy == sammy: False print("Sammy == also_Sammy", Sammy == also_Sammy) # Sammy == also_Sammy: True يمكنك أيضًا استخدام عوامل الموازنة الأخرى، بما في ذلك > و < لموازنة سلسلتين نصيتين. ستوازن بايثون هذه السلاسل النصية بحسب الترتيب المعجمي في نظام محارف ASCII. يمكننا أيضًا تقييم القيم المنطقية باستخدام عوامل الموازنة: t = True f = False print("t != f: ", t != f) # t != f: True تبيّن الشيفرة البرمجية أعلاه أنّ True لا تساوي False. لاحظ الفرق بين العاملين = و ==. x = y # x إلى y إسناد قيمة x == y # متساويين x و y تتحقق مما إذا كان الأول =، هو عامل الإسناد (assignment operator)، والذي سيحدد قيمة أحد المتغيرين، ويجعلها مساوية لقيمة الآخر. الثاني ==، وهو عامل الموازنة الذي سيحدد ما إذا كانت القيمتان متساويتان. العوامل المنطقية هناك ثلاثة عوامل منطقية تُستخدم لموازنة القيم. وتعيد إما True أو False. هذه العوامل هي، and (و)، و or (أو)، و not (النفي)، وقد عرّفناها في الجدول أدناه. العامل الشرح الصياغة and إن كان كلا التعبيرين صحيحين True x and y or إن كان أحد التعبيرين على الأقل صحيحًا True x or y not إن كان التعبير خطأ True not x عادةً ما تُستخدم العوامل المنطقية لتقييم ما إذا كان تعبيران منطقيان صحيحان أم لا. على سبيل المثال، يمكن استخدامها لتحديد ما إذا كان الطالب قد نجح، وأنه مُسجل في الفصل، وإذا كانت كلتا الحالتان صحيحتان، فسيتم إدخال الطالب إلى النظام. مثال آخر هو تحديد ما إذا كان المستخدم عميلًا نشطًا لمتجر إلكتروني استنادًا إلى ما إذا كان لديه رصيد في المتجر، أو أنه اشترى خلال الأشهر الستة الماضية. لفهم كيفية عمل العوامل المنطقية، دعنا نقيّم التعبيرات الثلاث التالية: print((9 > 7) and (2 < 4)) # كلا التعبيرين صحيحان print((8 == 8) or (6 != 6)) # أحد التعبيرين صحيح print(not(3 <= 1)) # التعبير الأصلي خاطئ والمخرجات هي: True True True في الحالة الأولى، ((9> 7) و (2 <4))print، كلا التعبيرين ‎9> 7 و ‎2 <4 ينبغي أن يكونا صحيحين لأنّ العامل and مُستخدَم. في الحالة الثانية، print((8 == 8) or (6 != 6))‎بما أنّ قيمة 8 == 8 تم تقييمها بـ True، فإنّ نتيجة تقييم ‎6 != 6‎لا تهم. لكن لو استخدمنا العامل and، لتمّ تقييم العبارة المنطقية بالقيمة False. في الحالة الثالثة، print(not(3 <= 1))‎، العامل not ينفي القيمة False التي تعيدها العملية المنطقية 3 <= 1. في المثال التالي سنستبدل بالأعداد العشرية أعدادًا صحيحة: print((-0.2 > 1.4) and (0.8 < 3.1)) # أحد التعبيرين خاطئ print((7.5 == 8.9) or (9.2 != 9.2)) # كلا التعبيرين خاطئان print(not(-5.7 <= 0.3)) # التعبير الأصلي صحيح في المثال أعلاه: and: يجب أن يكون واحد على الأقل من التعبيرين خاطئًا لتعيد القيمة False، or: يجب أن يكون كلا التعبيرين خاطئين لتعيد القيمة False، not: يجب أن يكون التعبير المرافق لها صحيحًا حتى تعيد القيمة False. إذا لم تكن النتائج أعلاه واضحة لك، فسنعرض بعض جداول الحقيقة أدناه لتفهم الأمر بشكل أفضل. يمكنك أيضًا كتابة عبارات مركبة باستخدام and, و or, و not: not((-0.2 > 1.4) and ((0.8 < 3.1) or (0.1 == 0.1))) التعبير الداخلي: (0.8 <3.1) أو (0.1 == 0.1). يعيد القيمة True، لأنّ كلا العبارتين الرياضيتين تعيدان True. الآن، نأخذ القيمة المُعادة True ونجمعها مع التعبير المنطقي التالي: (‎-0.2> 1.4) and (True). هذا المثال يعيد False، لأنّ العبارة ‎-0.2> 1.4 تعيد القيمة False، و ‎(False) and (True)‎ تعيد False. أخيرًا، يعيد التعبير الخارجي: not (False)‎ القيمة True، وبالتالي ستكون القيمة النهائية المعادة هي: True جداول الحقيقة (Truth Tables) المنطق مجال واسع، وسنكتفي في هذه المقالة ببعض الأفكار المهمة التي يمكن أن تساعدك على تحسين طريقة تفكيرك وخوارزمياتك. فيما يلي جداول الحقيقة لعامل الموازنة ==، والعوامل المنطقية and, و or, و not. من المفيد أن تحفظ كيفية عملها، فذلك سيجعلك أسرع في اتخاذ القرارات أثناء كتابة الشيفرات البرمجية. جدول الحقيقة الخاص بالعامل == x == y القيمة المُعادة True == True True True == False False False == True False False == False True جدول الحقيقة الخاص بالعامل AND x and y القيمة المُعادة True and True True True and False False False and True False False and False False جدول الحقيقة الخاص بالعامل OR x or y القيمة المُعادة True or True True True or False True False or True True False and False False جدول الحقيقة الخاص بالعامل NOT not x القيمة المُعادة not True False not False True تُستخدم جداول الحقيقة في المنطق الرياضياتي كثيرًا، وهي مفيدة، ويجب حفظها ووضعها في الحسبان عند إنشاء الخوارزميات البرمجية. استخدام العوامل المنطقية للتحكم في مسار البرنامج للتحكم في مسار ونتائج البرنامج عبر العبارات الشرطية (flow control statements)، يمكننا استخدام شرط (condition) متبوعًا بعبارة برمجية (clause). يتم تقييم الشرط بإحدى القيمتين True أو False، تلك القيمة تُستخدم لاتخاذ قرار في البرنامج. أما العبارة (clause) فهي الكتلة البرمجية التي تعقب الشرط وتحدِّد نتيجة البرنامج وما ينبغي فعله في حال تحقق الشرط. تُظهر الشيفرة أدناه مثالًا على عوامل الموازنة التي تعمل مع العبارات الشرطية للتحكم في مسار البرنامج: if grade >= 65: # شرط print("Passing grade") # بند else: print("Failing grade") سيحدد هذا البرنامج ما إذا كان الطالب سينجح أم يرسب. في حال كانت الدرجة التي حصل عليها الطالب تساوي 83 مثلًا، فتقييم العبارة الأولى سيكون True، وسيُطبَع النص "Passing grade. أما إن كانت درجة الطالب هي 59، فتقييم العبارة الأولى سيكون False، وبالتالي سينتقل البرنامج لتنفيذ العبارة المرتبطة بالتعبير else، أي سيطبع Failing grade. يمكن تقييم كل كائنات بايثون بإحدى القيمتين True أو False، لذلك يوصي الدليل PEP 8 بعدم موازنة كائن بإحدى القيمتين True أو False، لأنّ ذلك قد يؤدي إلى إعادة قيم منطقية غير متوقعة. على سبيل المثال، عليك تجنب استخدام مثل هذه العبارة sammy == True في برامجك. تساعد العوامل المنطقية على صياغة شروط يمكن استخدامها لتحديد النتيجة النهائية للبرنامج من خلال التحكم في مسار التنفيذ. خلاصة ألقينا في هذه المقالة نظرة على الموازنات والعوامل المنطقية، بالإضافة إلى جداول الحقيقة، وكيفية استخدام القيم المنطقية للتحكم في مسار البرنامج. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Boolean Logic in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: مدخل إلى القوائم المقالة السابقة: الدوال الرياضية المضمّنة في بايثون 3
  9. تتضمّن بايثون 3 العديد من الدوال التي يمكنك استخدامها بسهولة في أي برنامج. تتيح لك بعض تلك الدوال تحويل أنواع البيانات، والبعض الآخر خاص بنوع معين، مثل السلاسل النصية. سنستعرض في هذه المقالة بعض الدوال الرياضية المُضمّنة التي يمكن استخدامها مع أنواع البيانات العددية في بايثون 3. سنلقي نظرة على الدوال التالية: abs()‎: للحصول على القيمة المطلقة divmod()‎: للحصول على الحاصل والباقي في وقت واحد pow()‎: لرفع عدد لقوة معينة round()‎: لتقريب عدد بمنازل عشرية محددة sum()‎: لحساب مجموع العناصر في كائن قابلٍ للتكرار (iterable) فهم هذه التوابع سيمنحك مرونة أكبر في البرمجة، ويساعدك على اتخاذ قرارات مدروسة عند تحديد العوامل والدوال التي عليك استخدامها. سنتطرق إلى بعض هذه الدوال في هذه المقالة، مع تقديم بعض الأمثلة. القيمة المطلقة تعيد الدالة المضمّنة abs()‎ القيمة المطلقة للعدد الذي يُمرر إليها. في الرياضيات، تشير القيمة المطلقة إلى العدد نفسه إن كانت القيمة موجبة، أو القيمة المعاكسة إن كانت القيمة سالبة. مثلًا، القيمة المطلقة للعدد 15 هي 15، والقيمة المطلقة للعدد ‎-74 هي 74، والقيمة المطلقة للعدد 0 هي 0. القيمة المطلقة مفهوم مهم في الحساب والتحليل، كما أنّها مفيدة كذلك في المواقف اليومية، مثل حساب المسافة المقطوعة. على سبيل المثال، إذا كنت تحاول الوصول إلى مكان يبعد 58 ميلًا، ولكنك تجاوزت ذلك المكان، وسافرت 93 فرسخًا. فإن حسبت عدد الفراسخ التي ينبغي أن تقطعها الآن للوصول إلى الوجهة المقصودة، فسوف ينتهي بك المطاف بعدد سالب، لكن لا يمكنك السفر عددًا سالبًا من الفراسخ! سنستخدم الدالة abs()‎ لحل هذه المشكلة: miles_from_origin = 58 # عدد الفراسخ التي تفصلنا عن الوجهة انطلاقًا من المُنطلق miles_travelled = 93 # الفراسخ المقطوعة من المُنطَلق إلى الوجهة # حساب عدد الفراسخ من الموقع الحالي miles_to_go = miles_from_origin - miles_travelled print(miles_to_go) # طباعة عدد الفراسخ المتبقية - عدد سالب print(abs(miles_to_go)) # حساب القيمة المطلقة للعدد السالب المخرجات ستكون: -35 35 لولا استخدام الدالة abs()‎، لحصلنا على عدد سالب، أي ‎-35. ورغم أنّ miles_travelled أصغر من miles_from_origin، فإنّ الدالة abs()‎ تحل إشكالية العدد السالب. عندما نمرّر لها عددًا سالبًا، ستعيد الدالة abs()‎ عددًا موجبًا، لأنّ القيمة المطلقة دائمًا تعيد أعدادًا موجبة أو معدومة. في المثال التالي، سنمرر للدالة abs()‎ عددًا موجبًا، وكذلك الصفر: print(abs(89.9)) # 89.9 print(abs(0)) # 0 العثور على الحاصل والباقي بدالة واحدة القسمة التحتية (floor division، التي تُعيد حاصل القسمة [quotient])، وقسمة الباقي (modulo division، التي تعيد باقي القسمة [remainder])، مرتبطان ارتباطًا وثيقًا، وقد يكون من المفيد استخدام دالة تجمع بين العمليتين معًا. تجمع الدالة المضمّنة divmod()‎ بين العمليتين، إذ تعيد أولًا حاصل عملية القسمة التحتية، ثم الباقي. ينبغي تمرير عددين إلى الدالة divmod()‎، على النحو التالي: divmod(a,b) تكافئ هذه الدالة العمليتين التاليتين: a // b a & b لنفترض أننا كتبنا كتابًا يحتوي 80 ألف كلمة. يريد الناشر أن تحتوي كل صفحة من الكتاب ما بين 300 و 250 كلمة، ونود أن نعرف عدد الصفحات التي ستشكل الكتاب بحسب عدد كلمات الصفحة الذي اخترناه. باستخدام الدالة divmod()‎، يمكننا أن نعرف على الفور عدد الصفحات في الكتاب، وعدد الكلمات المتبقية التي ستُنقل إلى صفحة إضافية. words = 80000 # كم عدد الكلمات في كتابنا per_page_A = 300 # 300 عدد كلمات الصفحة هو :A الخيار per_page_B = 250 # عدد كلمات الصفحة هو 250 :B الخيار print(divmod(words,per_page_A)) # A حساب الخيار print(divmod(words,per_page_B)) # B حساب الخيار وسينتج عن هذه الشيفرة: (266, 200) (320, 0) في الخيار A، سنحصل على 266 صفحة مليئة بالكلمات، و 200 كلمة متبقية (ثلثا صفحة)، والمجموع هو 267 صفحة، وفي الخيار B، سنحصل على كتاب من 320 صفحة. إن أردنا الحفاظ على البيئة، فالخيار A قد يكون أفضل، ولكن إذا أردنا تصميمًا جذابًا، أو الكتابة بحجم خط كبير، فقد نختار الخيار "B". تقبل الدالة divmod()‎ االأعداد الصحيحة والأعداد العشرية، في المثال التالي سنمرر عددًا عشريًّا إلى الدالة divmod()‎: a = 985.5 b = 115.25 print(divmod(a,b)) # (8.0, 63.5) في هذا المثال، العدد 8.0 هو حاصل القسمة التحتية للعدد 985.5 مقسومًا على 115.25، و 63.5 هو الباقي. يمكنك استخدام عامل القسمة التحتية // و عامل الباقي% للتحقق من نتيجة divmod()‎: print(a//b) # 8.0 print(a%b) # 63.5 القوة (Power) في بايثون، يمكنك استخدام عامل القوة ** (أو الأس) لرفع عدد إلى قوة معينة، أو يمكنك استخدام الدالة pow()‎ المضمّنة التي تأخذ عددين وتجري العملية نفسها. لتوضيح كيفية عمل الدالة pow()‎، لنقل أننا نجري أبحاثًا على البكتيريا، ونريد أن نقدّر عدد البكتيريا التي سنحصل عليها في نهاية اليوم إذا بدأنا ببكتيريا واحدة. تتضاعف البكتيريا التي نعمل عليها في كل ساعة، لذلك النتيجة النهائية ستكون 2 قوة العدد الكلي لعدد الساعات التي مرت (24 في حالتنا). hours = 24 total_bacteria = pow(2,hours) print(total_bacteria) # 16777216 لقد مرّرنا عددين صحيحين للدالة pow()‎، والنتيجة التي حصلنا عليها، والتي تمثِّل عدد البكتيريا بحلول نهاية اليوم، هي أكثر من 16 مليون بكتيريا. في الرياضيات، نكتب "3 أسّ 3" بشكل عام على النحو التالي: 3³ والتي تكافئ 3 × 3 × 3، أي 27. ولحساب 3³ في بايثون، نكتب pow(3,3)‎. تقبل الدالة pow()‎ الأعداد الصحيحة والأعداد العشرية، وتوفّر بديلًا لعامل الأس **. تقريب الأعداد تقريب الأعداد (Rounding Numbers) ضروري عند العمل مع الأعداد العشرية التي تحتوي على الكثير من المنازل (الأجزاء) العشرية. تقبل الدالة المضمنة round()‎ عددين: أحدها يمثِّل العدد المراد تقريبه والآخر يحدّد عدد المنازل العشرية المراد الإبقاء عليها (أي قيمة التقريب). سنستخدم هذه الدالة لتقريب عدد عشري له أكثر من 10 منازل عشرية والحصول على عدد بأربعة منازل عشرية فقط: i = 17.34989436516001 print(round(i,4)) # 17.3499 في المثال أعلاه، تم تقريب العدد 17.34989436516001 إلى 17.3499 لأننا حددنا عدد المنازل العشرية التي ينبغي الاقتصار عليها بأربعة. لاحظ أيضًا أنّ الدالة round()‎ تقرّب الأعداد إلى الأعلى، لذا بدلًا من إعادة 17.3498، فقد أعادت 17.3499، لأنّ الرقم الذي يلي المنزل العشري 8 هو الرقم 9. وسيتم تقريب أي عدد متبوع بالعدد 5 أو أكبر إلى العدد الصحيح التالي. في الحياة اليومية، نُقرِّب الأعداد لأسباب كثيرة، وخاصة في التعاملات المالية؛ فلا يمكننا تقسيم فلس واحد بالتساوي بين عدة أصدقاء مثلًا. سنكتب في المثال التالي برنامجًا بسيطًا يمكنه حساب البقشيش. في هذا المثال سنحدد قيم المتغيرات، ولكن يمكنك إعادة كتابة البرنامج لجعل المستخدمين يدخلون القيم. في هذا المثال، ذهب 3 أصدقاء إلى مطعم، وأرادوا تقسيم الفاتورة، والتي تبلغ 87.93 دولارًا بالتساوي، بالإضافة إلى إكرامية (بقشيش) بنسبة 20٪. bill = 87.93 # إجمالي الفاتورة tip = 0.2 # ٪ 20 بقشيش split = 3 # عدد الناس الذين سيتشاركون الفاتورة total = bill + (bill * tip) # حساب الفاتورة الإجمالية each_pay = total / split # حساب ما ينبغي أن يدفعه كل شخص print(each_pay) # ما ينبغي أن يدفعه كل شخص قبل التقريب print(round(each_pay,2)) # تقريب العدد - لا يمكننا تقسيم الفلسات والمخرجات ستكون: 35.172000000000004 35.17 في هذا البرنامج، نطلب أولًا إخراج العدد بعد حساب إجمالي الفاتورة والإكراميات مقسومًا على 3، النتيجة ستكون عددًا يتضمّن الكثير من المنازل العشرية: 35.172000000000004. نظرًا لأنّ هذا العدد ليس له معنى كمبلغ مالي، فإننا نستخدم الدالة round()‎، ونقصر المنازل العشرية على 2، حتى نتمكن من توفير ناتج يمكن للأصدقاء الثلاثة أن يدفعوه: 35.17. إذا كنت تفضل التقريب إلى عدد بلا منازل عشرية، يمكنك تمرير 0 كمعامل ثان إلى الدالة round()‎: round(345.9874590348545304636,0) القيمة الناتجة ستكون 346.0. يمكنك أيضًا تمرير الأعداد الصحيحة إلى round()‎ دون الخوف من تلقي خطأ، وهذا مفيد في حال تلقيت من المستخدم عددًا صحيحًا بدلًا من عدد عشري. وفي هذه الحالة، سيُعاد عدد صحيح. حساب المجموع تُستخدم الدالة sum()‎ لحساب مجاميع أنواع البيانات العددية المركبة (numeric compound data types)، بما في ذلك القوائم، والصفوف، والقواميس. يمكننا تمرير قائمة إلى الدالة sum()‎ لجمع كل عناصرها بالترتيب من اليسار إلى اليمين: some_floats = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9] print(sum(some_floats)) # 49.5 نفس النتيجة سنحصل عليها إن استخدمنا الصفوف والقواميس: print(sum((8,16,64,512))) # حساب مجموع الأعداد في الصف print(sum({-10: 'x', -20: 'y', -30: 'z'})) # حساب مجموع الأعداد في القاموس المخرجات: 60 -60 يمكن أن تأخذ الدالة sum()‎ وسيطين، الوسيط الثاني سيُضاف إلى المجموع الناتج: some_floats = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9] print(sum(some_floats, 0.5)) # 50.0 print(sum({-10: 'x', -20: 'y', -30: 'z'},60)) # 0 القيمة الافتراضية للوسيط الثاني هي 0. خلاصة غطينا في هذه المقالة بعض التوابع المضمّنة التي يمكنك استخدامها مع أنواع البيانات العددية في بايثون. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Built-in Python 3 Functions for Working with Numbers لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم العمليات المنطقية في بايثون 3 المقالة السابقة: كيفية إجراء العمليات الحسابية في بايثون 3
  10. الأعداد شائعةٌ جدًا في البرمجة، إذ تُستخدم لتمثيل مختلف القيم، مثل أبعاد حجم الشاشة، والمواقع الجغرافية، والمبالغ المالية، ومقدار الوقت الذي مر منذ بداية فيديو، والألوان وغير ذلك. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } تعد القدرة على تنفيذ العمليات الرياضية بفعالية في البرمجة مهارة مهمة، لأنّك ستعمل على الأعداد كثيرًا. الفهم الجيد للرياضيات يمكن أن يساعدك على أن تصبح مبرمجًا أفضل، إلا أنه ليس شرطًا أساسيًا. فالرياضيات أداة لتحقيق ما ترغب في تحقيقه، وطريقة لتحسين خططك. سنعمل مع أكثر نوعي البيانات استخدامًا في بايثون، وهما الأعداد الصحيحة والأعداد العشرية: الأعداد الصحيحة هي أعداد كاملة يمكن أن تكون موجبة أو سالبة أو معدومة (...، ‎-1، 0، 1، ...). الأعداد العشرية هي أعداد حقيقية تحتوي على فاصلة عشرية (كما في 9.0 أو ‎-2.25). سنلقي في هذه المقالة نظرة على العوامل (operators) التي يمكن استخدامها مع أنواع البيانات العددية في بايثون. العوامل العامل (operator) هو رمز أو دالة تمثل عملية حسابية. على سبيل المثال، في الرياضيات، علامة الجمع أو + هي العامل الذي يشير إلى عملية الجمع. في بايثون، سنرى بعض العوامل المألوفة، والتي استُعيرَت من الرياضيات، لكن هناك عوامل أخرى خاصة بمجال البرمجة. الجدول التالي مرجعٌ سريعٌ للعوامل الحسابية في بايثون. سنغطي جميع هذه العمليات في مقالتنا هذه. العملية الناتج x + y مجموع x مع y x - y طرح x من y ‎-x تغيير إشارة x ‎+x قيمة x نفسها x * y ضرب x بـ y x / y قسمة x على y x // y حاصل القسمة التحتية لـ x على y x % y باقي قسمة x على y x ** y قيمة x مرفوعةً للقوة y سنتحدث أيضًا عن عوامل الإسناد المركبة (compound assignment operators)، بما في ذلك ‎+=‎ و ‎*=‎، التي تجمع عاملًا حسابيًا مع العامل =. الجمع والطرح في بايثون، يعمل عاملا الجمع والطرح كما هو معروف في الرياضيات. في الواقع، يمكنك استخدام لغة بايثون آلةً حاسبةً. لنلقِ نظرة على بعض الأمثلة، بدءًا من الأعداد الصحيحة: print(1 + 5) والناتج: 6 بدلًا من تمرير أعداد صحيحة مباشرة إلى الدالة print، يمكننا تهيئة المتغيرات بأعداد صحيحة: a = 88 b = 103 print(a + b) وسينتج لنا: 191 الأعداد الصحيحة يمكن أن تكون موجبة أو سالبة (أو معدومة أيضًا)، لذلك يمكننا إضافة عدد سالب إلى عدد موجب: c = -36 d = 25 print(c + d) # -11 الجمع سيكون مشابهًا مع الأعداد العشرية: e = 5.5 f = 2.5 print(e + f) # 8.0 إذا جمعنا عددين عشريين معًا، ستعيد بايثون عددًا عشريًّا. صياغة الطرح تشبه صياغة الجمع، ما عدا أنك ستستبدل بعامل الطرح (-) عامل الجمع (+): g = 75.67 h = 32 print(g - h) # 43.67 هنا، طرحنا عددًا صحيحًا من عدد عشري. ستعيد بايثون عددًا عشريًّا إذا كان أحد الأعداد المتضمنة في المعادلة عشريًّا. العمليات الحسابية الأحادية يتكون التعبير الرياضي الأحادي (unary mathematical expression) من مكوّن أو عنصر واحد فقط، ويمكن في بايثون استخدام العلامتين + و - بمفردهما عبر اقترانهما بقيمة لإعادة القيمة نفسها (+)، أو تغيير إشارة القيمة (-) . رغم أنها لا تُستخدم كثيرًا، تشير علامة الجمع إلى هوية القيمة (identity of the value)، أي تعيد القيمة نفسها. يمكننا استخدام علامة الجمع مع القيم الموجبة: i = 3.3 print(+i) # 3.3 عندما نستخدم علامة الجمع مع قيمة سالبة، فستُعيد القيمة نفسها، وفي هذه الحالة ستكون قيمة سالبة: j = -19 print(+j) # -19 عند استخدامها مع قيمة سالبة، ستعيد علامة الجمع القيمة السالبة نفسها. علامة الطرح، على خلاف علامة الجمع، تغيّر إشارة القيمة. لذلك، عندما نضعها مع قيمة موجبة، ستُعاد القيمة السالبة منها: i = 3.3 print(-i) # -3.3 بالمقابل، عندما نستخدم عامل الطرح الأحادي (minus sign unary operator) مع قيمة سالبة، فستُعاد القيمة الموجبة منها: j = -19 print(-j) # 19 ستُعيِد العمليتان الحسابيتان الأحاديتان + و - إمَّا هوية القيمة المعطاة، أو القيمة المعاكسة في الإشارة للقيمة المعطاة على التوالي. الضرب والقسمة مثل الجمع والطرح، الضرب والقسمة في بايثون مشابهان لما هو معروف في الرياضيات. علامة الضرب في بايثون هي *، وعلامة القسمة هي /. فيما يلي مثال على ضرب عددين عشريين في بايثون: k = 100.1 l = 10.1 print(k * l) # 1011.0099999999999 عندما تُجري عملية القسمة في بايثون 3، فسيكون العدد المُعاد دائمًا عشريًّا، حتى لو استخدمت عددين صحيحين: m = 80 n = 5 print(m / n) # 16.0 هذا أحد الاختلافات الرئيسية بين بايثون 2 و بايثون 3. الإجابة في بايثون 3 تكون كسرية، فعند استخدام / لتقسيم 11 على 2 مثلًا، فستُعاد القيمة 5.5. أمَّا في بايثون 2، فحاصل التعبير 11/2 هو 5. يُجرِي العامل / في بايثون 2 قسمة تحتية (floor division)، إذ أنّه إن كان حاصل القسمة يساوي x، فسيكون ناتج عملية القسمة في بايثون 2 أكبر عدد من الأعداد الصحيحة الأصغر من أو تساوي x. إذا نفَّذت المثال print(80 / 5)‎ أعلاه في بايثون 2 بدلًا من بايثون 3، فسيكون الناتج هو 16، وبدون الجزء العشري. في بايثون 3، يمكنك استخدام العامل // لإجراء القسمة التحتية. التعبير ‎100 // 40‎ سيعيد القيمة 2. القسمة التحتية مفيدة في حال كنت تريد أن يكون حاصل القسمة عددًا صحيحًا. معامل باقي القسمة (Modulo) العامل % هو عامل الباقي (modulo)، والذي يُرجع باقي عملية القسمة. هذا مفيد للعثور على الأعداد التي هي مضاعفات لنفس العدد، على سبيل المثال. المثال التالي يوضح كيفية استخدام عامل الباقي: o = 85 p = 15 print(o % p) # 10 حاصل قسمة 85 على 15 هو 5، والباقي 10. القيمة 10 هي التي ستُعاد هنا لأنَّ عامل الباقي يعيد باقي عملية القسمة. إذا استخدمنا عددين عشريين مع عامل الباقي، فسيُعاد عدد عشري: q = 36.0 r = 6.0 print(o % p) # 0.0 في حال قسمة 36.0 على 6.0، فلن يكون هناك باقٍ، لذلك تعاد القيمة 0.0. القوة (Power) يُستخدم عامل القوة ** (يقال له أحيًانًا «الأس») في بايثون لرفع العدد على اليسار لقوة الأس على اليمين. وهذا يعني أنه في التعبير 5 ** 3، العدد 5 سيُرفع إلى القوة 3. في الرياضيات، غالبًا ما نرى هذا التعبير يُكتب على الشكل 5³، حيث يُضرب العدد 5 في نفسه 3 مرات. في بايثون، التعبيران 5 ** 3 و 5 * 5 * 5 سيعطيان النتيجة نفسها. سنستخدم في المثال التالي المتغيرات: s = 52.25 t = 7 print(s ** t) # 1063173305051.292 رفع العدد العشري 52.25 إلى القوة 7 عبر عامل الأسّ ** سينتج عنه عدد عشري كبير. أسبقية العوامل في بايثون، كما هو الحال في الرياضيات، علينا أن نضع في حساباتنا أنَّ العوامل ستُقيَّم وفقًا لنظام الأسبقية، وليس من اليسار إلى اليمين، أو من اليمين إلى اليسار. إذا نظرنا إلى التعبير التالي: u = 10 + 10 * 5 قد نقرأه من اليسار إلى اليمين، ولكن تذكّر أنّ عملية الضرب ستُجرى أولًا، لذا إن استدعينا print(u)‎، فسنحصل على القيمة التالية: 60 هذا لأنّ 10 * 5 ستُقيّم أولًا، وسينتج عنها العدد 50، ثم نضيف إليها 10 لنحصل على 60 كنتيجة نهائية. إذا أردنا بدلًا من ذلك إضافة القيمة 10 إلى 10، ثم ضرب المجموع في 5، فيمكننا استخدام الأقواس كما نفعل في الرياضيات: u = (10 + 10) * 5 print(u) # 100 إحدى الطرق البسيطة لتذكر الأسبقيات هي حفظ الجملتين «قم أبعد ضيقًا ... قم جد طريقًا» لتذكر أوائل كلماتهما: الأسبقية الحرف المعنى 1 قم أقواس 2 أبعد الأس 3 ضيقًا الضرب 4 قم القسمة 5 جد الجمع 6 طريقًا الطرح عامل الإسناد (Assignment Operators) أكثر عوامل الإسناد استخدامًا هو إشارة التساوي =. يُسنِد عامل الإسناد (أو عامل التعيين) = القيمة الموجودة على اليمين إلى المتغير الموضوع على اليسار. على سبيل المثال، يُسنِد التعبير v = 23 العدد الصحيح 23 للمتغير v. من الشائع استخدام عوامل الإسناد المركبة التي تجري عملية رياضية على قيمة المتغير، ثم تُسنِد القيمة الجديدة الناتجة إلى ذلك المتغير. تجمع عوامل الإسناد المركبة بين عامل رياضي والعامل =؛ ففي حال الجمع، نستخدم + مع = للحصول على عامل الإسناد المركب ‎+=‎. لنطبِّق ذلك في مثال عملي: w = 5 w += 1 print(w) # 6 أولاً، نعيّن المتغير ‎w إلى القيمة 5، ثم نستخدم عامل الإسناد المركب ‎+=‎ لإضافة العدد الصحيح إلى قيمة المتغير الأيسر، ثم نُسنِد النتيجة إلى المتغير w. تُستخدم عوامل الإسناد المركبة بشكل متكرر مع حلقات for التكرارية، والتي ستستخدمها عندما تريد تكرار عمليةٍ عدة مرات: for x in range (0, 7): x *= 2 print(x) والناتج سيكون: 0 2 4 6 8 10 12 باستخدام الحلقة for، تمكنا من أتمتة العملية ‎*=‎ التي تضرب قيمة المتغير w بالعدد 2، ثم تُسنِد النتيجة إلى المتغير w لأجل استخدامها في التكرار التالي في الحلقة. لدى بايثون عامل إسناد مركب مقابل لكل من العوامل الحسابية التي تم التطرق إليها في هذه المقالة: y += 1 # إضافة القيمة ثم إسنادها y -= 1 # طرح القيمة ثم إسنادها y *= 2 # ضرب القيمة ثم إسنادها y /= 3 # تقسيم القيمة ثم إسنادها y // = 5 # تقسيم سفلي القيمة ثم إسنادها y **= 2 # تنفيذ عامل الأس على القيمة ثم إسنادها y %= 3 # إعادة باقي قسمة القيمة ثم إسناده يمكن أن يكون عامل الإسناد المركب مفيدًا عندما تحتاج إلى الزيادة أو الإنقاص التدريجي، أو عندما تحتاج إلى أتمتة عمليات معينة في برنامجك. خلاصة غطّينا في هذه المقالة العديد من العوامل التي ستستخدمها مع الأعداد الصحيحة والعشرية. يمكنك قراءة المزيد عن الأعداد في المقالة: الدوال العددية المضمّنة في بايثون 3. لمعرفة المزيد حول أنواع البيانات الأخرى، ألق نظرة على المقالة: فهم أنواع البيانات في بايثون 3، وتعرف على كيفية تحويل أنواع البيانات في المقالة: كيفية تحويل أنواع البيانات في بايثون 3. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Do Math in Python 3 with Operators لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: الدوال الرياضية المضمّنة في بايثون 3 المقالة السابقة: كيفية استخدام آلية تنسيق السلاسل النصية
  11. المتغيرات هي مفهوم برمجي مهم. إنَّها رموز تدل على القيم التي تستخدمها في برنامجك. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } ستغطي هذه المقالة بعض أساسيات المتغيرات، وكيفية استخدامها بالشكل الصحيح في برامج بايثون 3. فهم المتغيرات من الناحية الفنية، يُخصَّص للمتغير مساحة تخزينية في الذاكرة توضع القيمة المرتبطة به فيها. يُستخدم اسم المتغير للإشارة إلى تلك القيمة المُخزَّنة في ذاكرة البرنامج التي هي جزء من ذاكرة الحاسوب. المُتغيِّر أشبه بعنوان تُلصقه على قيمة مُعيَّنة: لنفترض أنّ لدينا عددًا صحيحًا يساوي 103204934813، ونريد تخزينه في متغيِّر بدلًا من إعادة كتابة هذا العدد الطويل كل مرة، لذلك سنستخدم شيئًا يُسهِّل تذكُّره، مثل المتغير my_int: my_int = 103204934813 إذا نظرنا إليه على أنَّه عنوانٌ مرتبط بقيمة، فسيبدو على النحو التالي: عنوان القيمة هو my_int المكتوب عليها، والقيمة هي 103204934813 (نوعها عدد صحيح). العبارة my_int = 103204934813 هي تعليمة إسناد (assignment statement)، وتتألف من الأجزاء التالية: اسم المتغير (my_int) معامل الإسناد، المعروف أيضًا باسم "علامة المساواة" (=) القيمة التي أُسنِدَت إلى اسم المتغير (103204934813) تشكل هذه الأجزاء الثلاثة معًا العبارة التي تُسنِد على المتغير my_int القيمة العددية الصحيحة 103204934813 . بمجرد تعيين قيمة متغير ما، نكون قد هيّئنا أو أنشأنا ذلك المتغير. وبعد ذلك، يمكننا استخدام ذلك المتغير بدلًا من القيمة. في بايثون، لا يلزم التصريح عن المتغيرات قبل استخدامها كما هو الحال في بعض لغات البرمجة الأخرى؛ إذ يمكنك البدء في استخدام المتغير على الفور. بمجرد تعيين my_int عند القيمة 103204934813، يمكننا استخدام my_int في مكان العدد الصحيح، كما في المثال التالي: print(my_int) والمخرجات هي: 103204934813 استخدام المتغيرات يسهل علينا إجراء العمليات الحسابية. في المثال التالي، سنستخدم العبارة السابقة my_int = 1040 ، ثم سنطرح من المتغير my_int القيمة 813 : print(my_int - 813) وسينتج لنا: 103204934000 في هذا المثال، يجري بايثون العملية الحسابية، ويطرح 813 من المتغير my_int ، ويعيد القيمة 103204934000 . يمكن ضبط المتغيرات وجعلها تساوي ناتج عملية حسابية. دعنا نجمع عددين معًا، ونخزِّن قيمة المجموع في المتغير x : x = 76 + 145 يشبه المثال أعلاه إحدى المعادلات التي تراها في كتب الجبر. في الجبر، تُستخدَم الحروف والرموز لتمثيل الأعداد والكميات داخل الصيغ والمعادلات، وبشكل مماثل، المتغيرات أسماء رمزية تمثل قيمة من نوع بيانات معيّن. الفرق في لغة بايثون، أنّ عليك التأكد دائمًا من أنّ المتغير موضوع على الجانب الأيسر من المعادلة. لنطبع x : print(x) والمخرجات: 221 أعادت بايثون القيمة 221 لأنَّه أُسنِد إلى المتغير x مجموع 76 و 145 . يمكن أن تمثل المتغيرات أي نوع بيانات، وليس الأعداد الصحيحة فقط: my_string = 'Hello, World!' my_flt = 45.06 my_bool = 5 > 9 # True أو False القيم المنطقية ستعيد إما my_list = ['item_1', 'item_2', 'item_3', 'item_4'] my_tuple = ('one', 'two', 'three') my_dict = {'letter': 'g', 'number': 'seven', 'symbol': '&'} إذا طبعت أيًّا من المتغيرات المذكورة أعلاه، فستعيد بايثون قيمة المتغير. على سبيل المثال، في الشيفرة التالية سنطبع متغيرًا يحتوي "قائمة": my_list = ['item_1', 'item_2', 'item_3', 'item_4'] print(my_list) وسينتج لنا: ['item_1', 'item_2', 'item_3', 'item_4'] لقد مرّرنا القيمة ['item_1' و 'item_2' و 'item_3' و 'item_4'] إلى المتغير my_list، ثم استخدمنا الدالة print()‎ لطباعة تلك القيمة باستدعاء my_list. تُخصِّص المتغيرات مساحة صغيرة من ذاكرة الحاسوب، وتقبل قيمًا تُوضَع بعد ذلك في تلك المساحة. قواعد تسمية المتغيرات تتسم تسمية المتغيرات بمرونة عالية، ولكن هناك بعض القواعد التي عليك أخذها في الحسبان: يجب أن تكون أسماء المتغيرات من كلمة واحدة فقط (بدون مسافات) يجب أن تتكوّن أسماء المتغيرات من الأحرف والأرقام والشرطة السفلية (_) فقط لا ينبغي أن تبدأ أسماء المتغيرات برقم باتباع القواعد المذكورة أعلاه، دعنا نلقي نظرة على بعض الأمثلة: صالح غير صالح لماذا غير صالح my_int my-int غير مسموح بالشرطات int4 4int لا يمكن البدء برقم MY_INT ‎$MY_INT لا يمكن استخدام أيّ رمز غير الشرطة السفلية another_int another int المتغير لا ينبغي أن يتكون من أكثر من كلمة واحدة من الأمور التي يجب أخذها في الحسبان عند تسمية المتغيرات، هو أنَّها حساسة لحالة الأحرف، وهذا يعني أنَّ my_int و MY_INT و My_Int و mY_iNt كلها مختلفة. ينبغي أن تتجنب استخدام أسماء متغيرات متماثلة لضمان ألا يحدث خلط عندك أو عند المتعاونين معك، سواء الحاليين والمستقبليّين. أخيرًا، هذه بعض الملاحظات حول أسلوب التسمية. من المتعارف عليه عند تسمية المتغيرات أن تبدأ اسم المتغير بحرف صغير، وأن تستخدم الشرطة السفلية عند فصل الكلمات. البدء بحرف كبير مقبول أيضًا، وقد يفضّل بعض الأشخاص تنسيق سنام الجمل (camelCase)، أو الخلط بين الأحرف الكبيرة والصغيرة عند كتابة المتغيرات، ولكنّ هذه الخيارات أقل شهرة. تنسيق متعارف عليه تنسيق غير متعارف عليه لماذا غير متعارف عليه my_int myInt أسلوب سنام الجمل (camelCase) غير تقليدي int4 Int4 الحرف الأول كبير - غير تقليدية my_first_string myFirstString أسلوب سنام الجمل (camelCase) غير تقليدي الخيار الأهم الذي عليك التمسك به هو الاتساق. إذا بدأت العمل في مشروع يستخدم تنسيق سنام الجمل في تسمية المتغيرات، فمن الأفضل الاستمرار في استخدام ذلك التنسيق. يمكنك مراجعة مقالة تنسيق الشيفرات البرمجية في بايثون لمزيد من التفاصيل. تغيير قيم المتغيرات كما تشير إلى ذلك كلمة "متغير"، يمكن تغيير قيم المتغيرات في بايثون بسهولة. هذا يعني أنَّه يمكنك تعيين قيمة مختلفة إلى متغير أُسنِدَت له قيمة مسبقًا بسهولة بالغة. إنّ القدرة على إعادة التعيين مفيدة للغاية، لأنك قد تحتاج خلال أطوار برنامجك إلى قبول قيم ينشئها المستخدم وتُحيلها على متغير. سهولة إعادة تعيين المتغيرات مفيد أيضًا في البرامج الكبيرة التي قد تحتاج خلالها إلى تغيير القيم باستمرار. سنعيّن إلى المتغير x أولًا عددًا صحيحًا، ثم نعيد تعيينه بسلسلة نصية: # x إسناد قيمة عددية إلى x = 76 print(x) # إلى سلسلة نصية x إعادة تعيين x = "Sammy" print(x) وسينتج لنا: 76 Sammy يوضح المثال أعلاه أنه يمكننا أولًا تعيين المتغير x وإعطاؤه قيمة عددية، ثم إعادة تعيينه بقيمة نصية. إذا أعدنا كتابة البرنامج بهذه الطريقة: x = 76 x = "Sammy" print(x) لن نتلقى سوى القيمة المعيّنة الثانية في المخرجات، لأنَّ تلك القيمة كانت أحدث تعيين: Sammy قد تكون إعادة تعيين المتغيرات مفيدة في بعض الحالات، لكن عليك أن تبقي عينك على مقروئية الشيفرة، وأن تحرص على جعل البرنامج واضحًا قدر الإمكان. الإسناد المتعدد (Multiple Assignment) في بايثون، يمكنك إسناد قيمة واحدة إلى عدة متغيرات في الوقت نفسه. يتيح لك هذا تهيئة عدَّة متغيرات دفعةً واحدةً، والتي يمكنك إعادة تعيينها لاحقًا، أو من خلال مدخلات المستخدم. يمكنك من خلال التعيينات المتعددة ضبط المتغيرات x وy و z عند القيمة 0 في سطر واحد: x = y = z = 0 print(x) print(y) print(z) الناتج سيكون: 0 0 0 في هذا المثال، عيّنّا المتغيرات الثلاثة (x و y و z) في نفس موقع الذاكرة. وكلها تساوي القيمة 0. تسمح لك بايثون أيضًا بتعيين عدة قيم لعدة متغيرات ضمن السطر نفسه. هذه القيم يمكن أن تكون من أنواع بيانات مختلفة: j, k, l = "shark", 2.05, 15 print(j) print(k) print(l) وهذه هي المخرجات: shark 2.05 15 في المثال أعلاه، أُسندَت السلسلة النصية "shark" إلى المتغير j، والعدد العشري 2.05 إلى المتغير k، والعدد الصحيح 15 إلى المتغير l. تعيين عدة متغيرات بعدة قيم في سطر واحد يمكن أن يجعل الشيفرة مختصرة ويقلل من عدد الأسطر، ولكن تأكد من أنّ ذلك ليس على حساب المقروئية. المتغيرات العامة والمحلية عند استخدام المتغيرات داخل البرنامج، من المهم أن تضع نطاق (scope) المتغير في حساباتك. يشير نطاق المتغير إلى المواضع التي يمكن الوصول منها إلى المتغير داخل الشيفرة، لأنَّه لا يمكن الوصول إلى جميع المتغيرات من جميع أجزاء البرنامج، فبعض المتغيرات عامة (global)، وبعضها محلي (local). تُعرّف المتغيرات العامة خارج الدوال. أمَّا المتغيرات المحلية، فتوجد داخل الدوال. المثال التالي يعطي فكرة عن المتغيرات العامة والمحلية: # إنشاء متغير عام، خارج الدالة glb_var = "global" def var_function(): lcl_var = "local" # إنشاء متغير محلي داخل دالة print(lcl_var) # استدعاء دالة لطباعة المتغير المحلي var_function() # طباعة متغير عام خارج دالة print(glb_var) المخرجات الناتجة: local global يُسنِد البرنامج أعلاه سلسلة نصية إلى المتغير العمومي glb_var خارج الدالة، ثم يعرّف الدالة var_function()‎. وسيُنشِئ داخل تلك الدالة متغيِّرًا محليًّا باسم lcl_var، ثم يطبعه قيمته. ينتهي البرنامج باستدعاء الدالة var_function()‎، وطباعة قيمة المتغير glb_var. لمَّا كان glb_var متغيرًا عامًّا، فيمكننا الوصول إليه داخل الدالة var_function()‎. المثال التالي يبيّن ذلك: glb_var = "global" def var_function(): lcl_var = "local" print(lcl_var) print(glb_var) # داخل الدالة glb_var طباعة var_function() print(glb_var) المخرجات: local global global لقد طبعنا المتغير العام glb_var مرتين، حيث طُبع داخل الدالة وخارجها. ماذا لو حاولنا استدعاء المتغير المحلي خارج الدالة؟ glb_var = "global" def var_function(): lcl_var = "local" print(lcl_var) print(lcl_var) لا يمكننا استخدام متغير محلي خارج الدالة التي صُرِّح عنه فيها. إذا حاولنا القيام بذلك، فسيُطلق الخطأ NameError. NameError: name 'lcl_var' is not defined دعنا ننظر إلى مثال آخر، حيث سنستخدم الاسم نفسه لمتغير عام وآخر محلي: num1 = 5 # متغير عام def my_function(): num1 = 10 # num1 استخدام نفس اسم المتغير num2 = 7 # تعيين متغير محلي print(num1) # num1 طباعة المتغير المحلي print(num2) # num2 طباعة المتغير المحلي # my_function() استدعاء my_function() # num1 طباعة المتغير العام print(num1) الناتج: 10 7 5 نظرًا لأنّ المتغير المحلي num1 صُرِّح عنه محليًا داخل إحدى الدوال، فسنرى أنّ num1 يساوي القيمة المحلية 10 عند استدعاء الدالة. عندما نطبع القيمة العامة للمتغير num1 بعد استدعاء الدالة my_function()‎، سنرى أنّ المتغير العام num1 لا يزال مساويًا للقيمة 5. من الممكن تعيين المتغيرات العامة داخل دالة باستخدام الكلمة المفتاحية global: def new_shark(): # جعل المتغير عاما global shark shark = "Sammy" # new_shark() استدعاء الدالة new_shark() # shark طباعة المتغير العام print(shark) رغم أنّ المتغير المحلي shark عُيِّن داخل الدالة new_shark()‎، إلا أنه يمكن الوصول إليه من خارج الدالة بسبب العبارة global المستخدمة قبل تعيين المتغير داخل الدالة. بسبب استخدام العبارة global، فلن يُطلق أيّ خطأ عندما نستدعي print(shark)‎ خارج الدالة. رغم أنَّه يمكنك تعيين متغير عام داخل دالة، إلا أنّها من العادات غير المستحبة في البرمجة، لأنها قد تؤثر على مقروئية الشيفرة. هناك شيء آخر يجب تذكره، وهو أنَّك إذا أشرت إلى متغير داخل دالة، دون تعيين قيمة له، فسيُعَدّ هذا المتغير عامًا بشكل ضمني. للحصول على متغير محلي، يجب عليك إسناد قيمة له داخل متن الدالة. عند التعامل مع المتغيرات، من المهم أن تختار بين استخدام المتغيرات العامة أو المحلية. يُفضل في العادة استخدام المتغيرات المحلية، ولكن إن وجدت نفسك تستخدم نفس المتغير في عدة دوال، فقد ترغب في جعله عامًا. أما إن كنت تحتاج المتغير داخل دالة أو صنف واحد فقط، فقد يكون الأولى استخدام متغير محلي. خلاصة لقد مررنا في هذه المقالة على بعض حالات الاستخدام الشائعة للمتغيرات في بايثون 3. المتغيرات هي لبنة مهمة في البرمجة، إذ تُمثِّل حاضنةً لمختلف أنواع البيانات في بايثون. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Use Variables in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية استخدام آلية تنسيق السلاسل النصية المقالة السابقة: كيفية التحويل بين أنواع البيانات
  12. تُستخدَم أنواع البيانات في بايثون لتصنيف نوع معيَّن من البيانات، وتحديد القيم التي يمكنك تعيينها لذلك النوع، والعمليات التي يمكنك إجراؤها عليها. هناك أوقات نحتاج إلى تحويل القيم من نوع إلى آخر لأجل معالجتها بطريقة مختلفة. على سبيل المثال، قد نحتاج إلى ضم (concatenate) القيم العددية إلى سلاسل نصية. سترشدك هذه المقالة إلى كيفية تحويل الأعداد والسلاسل النصية والصفوف والقوائم، بالإضافة إلى تقديم بعض الأمثلة التوضيحية. تحويل الأنواع العددية هناك نوعان من البيانات العددية في بايثون: الأعداد الصحيحة والأعداد العشرية. ستعمل في بعض الأحيان على شيفرة برمجية كتبها شخص آخر، وقد تحتاج إلى تحويل عدد صحيح إلى عدد عشري، أو العكس، أو قد تجد أنك تستخدم عددًا صحيحًا في الوقت الذي تحتاج إلى أعداد عشرية. يتوفر في بايثون توابع مضمّنة تُسهِّل عليك تحويل الأعداد الصحيحة إلى أعداد عشرية، أو العكس. تحويل الأعداد الصحيحة إلى أعداد عشرية يحوّل التابع float()‎ الأعداد الصحيحة إلى أعداد عشرية. لاستخدام هذه الدالة، ضع عددًا صحيحًا بين القوسين: float(57) في هذه الحالة، سيتم تحويل 57 إلى 57.0. يمكنك أيضًا استخدام هذه الدالة مع المتغيرات. لنُحِل على المتغير f القيمة 57، ثم نطبع العدد العشري الجديد: f = 57 print(float(f)) الناتج سيكون: 57.0 يمكننا باستخدام الدالة float()‎ تحويل الأعداد الصحيحة إلى أعداد عشرية. تحويل الأعداد العشرية إلى أعداد صحيحة بايثون لديه دالة أخرى مضمَّنة لتحويل الأعداد عشرية إلى أعداد صحيحة: وهي int()‎. تعمل الدالة int()‎ بشكل مشابه للدالة float()‎: يمكنك إضافة عدد عشري داخل القوسين لتحويله إلى عدد صحيح: int(390.8) في هذه الحالة، سيتم تحويل 390.8 إلى 390. يمكنك أيضا استخدام هذه الدالة مع المتغيرات. لنصرِّح أنَّ b يساوي 125.0، وأنَّ c يساوي 390.8، ثم نطبع العددين العشريين الجديدين: b = 125.0 c = 390.8 print(int(b)) print(int(c)) والمخرجات ستكون: 125 390 عند تحويل الأعداد العشرية إلى أعداد صحيحة بواسطة الدالة int()‎، فإنّ بايثون تقتطع الأجزاء العشرية من العدد وتُبقي القيمة الصحيحة؛ لذلك، لن تُحوِّل الدالة int()‎ العدد 390.8 إلى 391. تحويل الأعداد عبر القسمة في بايثون 3، عند تقسيم عدد صحيح على آخر، سينتج عدد عشرية على خلاف بايثون 2. بمعنى أنه عند قسمة 5 على 2 في بايثون 3، ستحصل على عدد عشري (مثل 2.5 عند قسمة 5 على 2): a = 5 / 2 print(a) وسينتج لنا: 2.5 في بايثون 2، ستحصل على ناتج صحيح، أي 5/2 = 2. يمكنك الحصول على عدد صحيح ناتج عن عملية القسمة باستعمال المعامل // الجديد في بايثون 3: a = 5 // 2 print(a) وسينتج لنا: 2 اقرأ درس اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 إن لم تقرأه مسبقًا. التحويل مع السلاسل النصية السلاسل النصية عبارة عن سلسلة مؤلفة من محرف واحد أو أكثر (المحرف يمكن أن يكون حرفًا، أو عددًا، أو رمزًا). السلاسل النصية هي إحدى الأشكال الشائعة من البيانات في عالم البرمجة، وقد نحتاج إلى تحويل السلاسل النصية إلى أعداد أو أعداد إلى سلاسل نصية في كثير من الأحيان، خاصةً عندما نعمل على البيانات التي ينشئها المستخدمون. تحويل الأعداد إلى سلاسل نصية يمكننا تحويل الأعداد إلى سلاسل نصية عبر التابع str()‎. يمكننا أن نمرّر إمَّا عددًا أو متغيرًا بين قوسي التابع، وبعد ذلك سيتم تحويل تلك القيمة العددية إلى قيمة نصية. دعنا ننظر أولًا في تحويل الأعداد الصحيحة. لتحويل العدد الصحيح 12 إلى سلسلة نصية، يمكنك تمرير 12 إلى التابع str()‎: str(12) عند تنفيذ str(12)‎ في سطر أوامر بايثون التفاعلي مع الأمر python في نافذة الطرفية، ستحصل على المخرجات التالية: '12' تشير علامات الاقتباس المحيطة بالعدد 12 إلى أنه لم يعد عددًا صحيحًا، ولكنه أصبح الآن سلسلة نصية. سيصبح باستخدام المتغيرات تحويل الأعداد الصحيحة إلى سلاسل نصية أكثر فائدة. لنفترض أننا نريد متابعة تقدم مستخدم في مجال البرمجة يوميًّا مثل أن ندخل عدد أسطر الشيفرة البرمجية التي كتبها. نود أن نعرض ذلك على المستخدم، وذلك بطباعة السلاسل النصية والأعداد في الوقت نفسه: user = "Sammy" lines = 50 print("Congratulations, " + user + "! You just wrote " + lines + " lines of code.") عند تنفيذ الشيفرة أعلاه، سيُطلق الخطأ التالي: TypeError: Can't convert 'int' object to str implicitly يتعذر علينا ضمّ (concatenate) السلاسل النصية والأعداد الصحيحة في بايثون، لذلك سيتعين علينا تحويل المتغير lines إلى سلسلة نصية: user = "Sammy" lines = 50 print("Congratulations, " + user + "! You just wrote " + str(lines) + " lines of code.") الآن، عندما نُنفِّذ الشيفرة البرمجية، سنحصل على المخرجات التالية، وفيها تهنئة للمستخدم على تقدُّمه: Congratulations, Sammy! You just wrote 50 lines of code. إذا أردنا تحويل عدد عشري إلى سلسلة نصية بدلًا من تحويل عدد صحيح إلى سلسلة نصية، فعلينا تتبع نفس الخطوات والصياغة السابقة. عندما نمرّر عددًا عشريًا إلى التابع str()‎، ستُعاد سلسلة نصية. يمكننا استخدام قيمة العدد العشري نفسها، أو يمكننا استخدام متغير: print(str(421.034)) f = 5524.53 print(str(f)) وسينتج لنا: 421.034 5524.53 يمكننا اختبار صحة التحويل عن طريق ضم الناتج إلى سلسلة نصية: f = 5524.53 print("Sammy has " + str(f) + " points.") وهذا هو الناتج: Sammy has 5524.53 points. الآن تأكدنا من أنَّ عددنا العشري قد حُوِّل بنجاح إلى سلسلة نصية، لأنّ عملية الضم قد تم إجراؤها دون خطأ. تحويل السلاسل النصية إلى أعداد يمكن تحويل السلاسل النصية إلى أعداد باستخدام التابعين float()‎ و int()‎. إذا لم يكن في السلسلة النصية منازل عشرية، فالأفضل أن تحولها إلى عدد صحيح باستخدام التابع int()‎. دعنا نستخدم مثال تتبع عدد أسطر الشيفرة الذي أوردناه أعلاه. قد ترغب في التعامل مع هذه القيم باستخدام الحسابات الرياضياتية لتقديم نتائج أدق للمستخدم، ولكنّ هذه القيم مخزّنة حاليًا في سلاسل نصية: lines_yesterday = "50" lines_today = "108" lines_more = lines_today - lines_yesterday print(lines_more) الناتج هو: TypeError: unsupported operand type(s) for -: 'str' and 'str' نظرًا لأنّ القيمتين العدديتين مخزنتان في سلاسل نصية، تلقينا خطأً. سبب ذلك أنَّ معامل الطرح - لا يصلح للسلاسل النصية. دعنا نعدّل الشيفرة لتضمين التابع int()‎ الذي سيحول السلاسل النصية إلى أعداد صحيحة، ويسمح لنا بالقيام بالعمليات الرياضياتية على القيم التي كانت سلاسل نصية في الأصل. lines_yesterday = "50" lines_today = "108" lines_more = int(lines_today) - int(lines_yesterday) print(lines_more) وهذه هي المخرجات: 58 المتغير line_more هو عدد صحيح تلقائيًّا، ويساوي القيمة العددية 58 في هذا المثال. يمكننا أيضًا تحويل الأعداد في المثال أعلاه إلى قيم عشرية باستخدام التابع float()‎ بدلًا من التابع int()‎. وبدلًا من الحصول على الناتج 58، سنحصل على الناتج 58.0، وهو عدد عشري. المستخدم Sammy سيكسب نقاطًا على شكل قيم عشرية: total_points = "5524.53" new_points = "45.30" new_total_points = total_points + new_points print(new_total_points) الناتج: 5524.5345.30 في هذه الحالة، يعد استخدام المعامل + مع سلسلتين نصيتين عمليةً صالحةً، لكنه سيضم السلسلتين النصّيتين بدلًا من جمع القيمتين العدديتين؛ لذلك، سيبدو الناتج غير اعتيادي، لأنه نتيجة لصق القيمتين إلى جانب بعضهما بعضًا. سنحتاج إلى تحويل هذه السلاسل النصية إلى أعداد عشرية قبل إجراء أي عمليات عليها، وذلك باستخدام التابع float()‎: total_points = "5524.53" new_points = "45.30" new_total_points = float(total_points) + float(new_points) print(new_total_points) وسينتج عن ذلك: 5569.83 الآن، وبعد أن حوّلنا السلسلتين النصيتين إلى عددين عشريين، سنحصل على النتيجة المتوقعة، والتي هي جمع 45.30 و 5524.53. إذا حاولنا تحويل سلسلة نصية ذات منازل عشرية إلى عدد صحيح، فسنحصل على خطأ: f = "54.23" print(int(f)) المخرجات: ValueError: invalid literal for int() with base 10: '54.23' إذا مرّرنا عددًا عشريًا موضوعًا في سلسلة نصية إلى التابع int()‎، فسنحصل على خطأ، لأنها لن تُحوَّل إلى عدد صحيح. يتيح لنا تحويل السلاسل النصية إلى أعداد تعديل نوع البيانات الذي نعمل عليه بسرعة حتى نتمكن من إجراء عمليات على قيم عددية مكتوبة على شكل سلاسل نصية. التحويل إلى صفوف وقوائم يمكنك استخدام التابعين list()‎ و tuple()‎ لتحويل القيم المُمرّرة إليهما إلى قائمة أو صف على التوالي. في بايثون: القائمة هي تسلسل مرتب قابل للتغيير من العناصر الموضوعة داخل قوسين معقوفين []. الصف عبارة عن تسلسل مرتب ثابت (غير قابل للتغيير) من العناصر الموضوعة بين قوسين (). التحويل إلى صفوف نظرًا لكون الصفوف غير قابلة للتغيير، فيمكن أن يحسِّن تحويل قائمة إلى صف أداء البرامج تحسينًا كبيرًا. عندما نستخدم التابع tuple()‎، فسوف يُعيد القيمة المُمرَّرة إليه على هيئة صف. print(tuple(['pull request', 'open source', 'repository', 'branch'])) المخرجات: ('pull request', 'open source', 'repository', 'branch') نرى أنّ الصف قد طُبع في المخرجات، إذ أنَّ العناصر موضوعة الآن بين قوسين، بدلًا من القوسين المربعين. دعنا نستخدم tuple()‎‎ مع متغير يحتوي قائمة: sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis shrimp'] print(tuple(sea_creatures)) سينتج: ('shark', 'cuttlefish', 'squid', 'mantis shrimp') مرة أخرى، نرى أنّ القائمة حُوِّلت إلى صف، كما يشير إلى ذلك القوسان. يمكننا تحويل أي نوع قابل للتكرار (iterable) إلى صف، بما في ذلك السلاسل النصية: print(tuple('Sammy')) المخرجات: ('S', 'a', 'm', 'm', 'y') نظرًا لأنه يمكننا التكرار (iterate) على السلاسل النصية، يمكننا تحويلها إلى صفوف باستخدام التابع tuple()‎. أمَّا أنواع البيانات غير القابلة للتكرار، مثل الأعداد الصحيحة والأعداد العشرية، فستُطلق عملية تحويلها خطأً: print(tuple(5000)) والناتج سيكون: TypeError: 'int' object is not iterable في حين أنه من الممكن تحويل عدد صحيح إلى سلسلة نصية، ومن ثم تحويل السلسلة النصية إلى صف، كما في العبارة tuple(str(5000))‎، فمن الأفضل تجنب مثل هذه التعليمات البرمجية المعقدة. التحويل إلى قوائم يمكن أن يكون تحويل القيم، وخاصة الصفوف، إلى قوائم مفيدًا عندما تحتاج إلى نسخة قابلة للتغيير من تلك القيم. سنستخدم التابع list()‎ لتحويل الصف التالي إلى قائمة. ونظرًا لأنّ صياغة القوائم تستخدم الأقواس، تأكد من تضمين أقواس التابع list()‎، وكذلك الأقواس الخاصة بالتابع print()‎: print(list(('blue coral', 'staghorn coral', 'pillar coral'))) المخرجات هي: ['blue coral', 'staghorn coral', 'pillar coral'] تشير الأقواس المعقوفة [] إلى أنَّه قد تم إرجاع قائمة من الصف الأصلي الذي مُرِّر عبر التابع list()‎. لجعل الشيفرة سهلة القراءة، يمكننا إزالة أحد أزواج الأقواس باستخدام متغير: coral = ('blue coral', 'staghorn coral', 'pillar coral') list(coral) إن طبعنا list(coral)‎، فسنتلقى المخرجات نفسها الموجودة أعلاه. تمامًا مثل الصفوف، يمكن تحويل السلاسل النصية إلى قوائم: print(list('shark')) الناتج: ['s', 'h', 'a', 'r', 'k'] هنا حُوِّلَت السلسلة shark إلى قائمة، وهذا يوفر لنا نسخة قابلة للتغيير من القيمة الأصلية. خلاصة لقد وضحنا في هذه المقالة كيفية تحويل العديد من أنواع البيانات الأصلية المهمة إلى أنواع بيانات أخرى، وذلك باستخدام التوابع المُضمّنة. تحويل أنواع البيانات في بايثون يوفر لك مرونةً إضافيةً في مشاريعك البرمجية. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Convert Data Types in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية استخدام المتغيرات المقالة السابقة: آلية فهرسة السلاسل النصية وطريقة تقسيمها
  13. توفر List Comprehensions طريقةً مختصرةً لإنشاء القوائم بناءً على قوائم موجودة مسبقًا. فعند استخدام list comprehensions فيمكن بناء القوائم باستخدام أيّ نوع من البيانات المتسلسلة التي يمكن الدوران على عناصرها عبر حلقات التكرار، بما في ذلك السلاسل النصية و tuples. من ناحية التركيب اللغوي، تحتوي list comprehensions على عنصر يمكن المرور عليه ضمن تعبيرٍ متبوعٍ بحلقة for. ويمكن أن يُتبَع ما سبق بتعابير for أو if إضافية، لذا سيساعدك الفهم العميق لحلقات for والعبارات الشرطية في التعامل مع list comprehensions. توفِّر list comprehensions طريقةً مختلفةً لإنشاء القوائم وغيرها من أنواع البيانات المتسلسلة. وعلى الرغم من إمكانية استخدام الطرائق الأخرى للدوران، مثل حلقات for، لإنشاء القوائم، لكن من المفضَّل استعمال list comprehensions لأنها تقلِّل عدد الأسطر الموجودة في برنامجك. List Comprehensions يمكن بناء list comprehensions في بايثون كالآتي: list_variable = [x for x in iterable] ستُسنَد القائمة، أو أي نوع من البيانات يمكن المرور على عناصره، إلى متغير. المتغيرات الإضافية –التي تُشير إلى عناصر موجودة ضمن نوع البيانات الذي يمكن المرور على عناصره– تُبنى حول عبارة for. والكلمة المحجوزة in تستعمل بنفس استعمالها في حلقات for وذلك لمرور على عناصر iterable. لننظر إلى مثالٍ يُنشِئ قائمةً مبنيةً على سلسلةٍ نصية: shark_letters = [letter for letter in 'shark'] print(shark_letters) أسندنا في المثال السابق قائمةً جديدةً إلى المتغير shark_letters، واستعملنا المتغير letter للإشارة إلى العناصر الموجودة ضمن السلسلة النصية 'shark'. استعملنا بعد ذلك الدالة print()‎ لكي نتأكد من القائمة الناتجة والمُسنَدة إلى المتغير shark_letters، وحصلنا على الناتج الآتي: ['s', 'h', 'a', 'r', 'k'] القائمة التي أنشأناها باستخدام list comprehensions تتألف من العناصر التي تكوِّن السلسلة النصية 'shark'، وهي كل حرف في الكلمة shark. يمكن إعادة كتابة تعابير list comprehensions كحلقات for، لكن لاحظ أنَّك لا تستطيع إعادة كتابة كل حلقة for بصيغة list comprehensions. لنعد كتابة المثال السابق الذي أنشأنا فيه القائمة shark_letters باستخدام حلقة for، وهذا سيساعدنا في فهم كيف تعمل list comprehensions عملها: shark_letters = [] for letter in 'shark': shark_letters.append(letter) print(shark_letters) عند إنشائنا للقائمة عبر استخدام الحلقة for، فيجب تهيئة المتغير الذي سنُسنِد العناصر إليه كقائمة فارغة، وهذا ما فعلناه في أوّل سطر من الشيفرة السابقة. ثم بدأت حلقة for بالدوران على عناصر السلسلة النصية 'shark' مستعملةً المتغير letter للإشارة إلى قيمة العنصر الحالي. ومن ثم أضفنا كل عنصر في السلسلة النصية إلى القائمة ضمن حلقة for وذلك باستخدام الدالة list.append(x). الناتج من حلقة for السابقة يماثل ناتج list comprehension في المثال أعلاه: ['s', 'h', 'a', 'r', 'k'] الخلاصة: يمكن إعادة كتابة List comprehensions كحلقات for، لكن بعض حلقات for يمكن إعادة كتابتها لتصبح List comprehensions لتقليل كمية الشيفرات المكتوبة. استخدام التعابير الشرطية مع List Comprehensions يمكن استخدام التعابير الشرطية في list comprehension لتعديل القوائم أو أنواع البيانات المتسلسلة الأخرى عند إنشاء قوائم جديدة. لننظر إلى مثالٍ عن استخدام العبارة الشرطية if في تعبير list comprehension: fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus') fish_list = [fish for fish in fish_tuple if fish != 'octopus'] print(fish_list) استعملنا المتغير fish_tuple الذي من نوع البيانات tuple كأساس للقائمة الجديدة التي سنُنشِئها التي تسمى fish_list. استعملنا for و in كما في القسم السابق، لكننا أضفنا هنا العبارة الشرطية if. ستؤدي العبارة الشرطية if إلى إضافة العناصر غير المساوية للسلسلة النصية 'octopus'، لذا ستحتوي القائمة الجديدة على العناصر الموجودة في بنية tuple والتي لا تُطابِق الكلمة 'octopus'. عند تشغيل البرنامج السابق فسنلاحظ أنَّ القائمة fish_list تحتوي على نفس العناصر التي كانت موجودة في fish_tuple لكن مع حذف العنصر 'octopus': ['blowfish', 'clownfish', 'catfish'] أي أصبحت القائمة الجديدة تحتوي على بنية tuple الأصلية لكن ما عدا السلسلة النصية التي استثنيناها عبر التعبير الشرطي. سنُنشِئ مثالًا آخر يستعمل المعاملات الرياضية والأرقام الصحيحة والدالة range()‎: number_list = [x ** 2 for x in range(10) if x % 2 == 0] print(number_list) القائمة التي ستُنشَأ باسم number_list ستحتوي على مربع جميع القيم الموجودة من المجال 0 إلى 9 لكن إذا كان الرقم قابلًا للقسمة على 2. وستبدو المخرجات كالآتية: [0, 4, 16, 36, 64] دعنا نُفصِّل ما الذي يفعله تعبير list comprehension السابق، ودعنا نفكِّر بالذي سيظهر إذا استعملنا التعبير x for x in range(10) فقط. يجب أن يبدو برنامجنا الصغير كالآتي: number_list = [x for x in range(10)] print(number_list) الناتج: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] لنضف العبارة الشرطية الآن: number_list = [x for x in range(10) if x % 2 == 0] print(number_list) الناتج: [0, 2, 4, 6, 8] أدّت العبارة الشرطية if إلى قبول العناصر القابلة للقسمة على 2 فقط وإضافتها إلى القائمة، مما يؤدي إلى حذف جميع الأرقام الفردية. يمكننا الآن استخدام معامل رياضي لتربيع قيمة المتغير x: number_list = [x ** 2 for x in range(10) if x % 2 == 0] print(number_list) أي ستُربَّع قيم القائمة السابقة ‎[0, 2, 4, 6, 8] وسيُخرَج الناتج الآتي: [0, 4, 16, 36, 64] يمكننا أيضًا استعمال ما يشبه عبارات if المتشعبة في تعابير list comprehension: number_list = [x for x in range(100) if x % 3 == 0 if x % 5 == 0] print(number_list) سيتم التحقق أولًا أنَّ المتغير x قابل للقسمة على الرقم 3، ثم سنتحقق إن كان المتغير x قابل للقسمة على الرقم 5، وإذا حقَّق المتغير x الشرطين السابقين فسيُضاف إلى القائمة، وسيُظهَر في الناتج: [0, 15, 30, 45, 60, 75, 90] الخلاصة: يمكن استخدام عبارات if الشرطية لتحديد ما هي العناصر التي نريد إضافتها إلى القائمة الجديدة. حلقات التكرار المتشعبة في تعابير List Comprehension يمكن استعمال حلقات التكرار المتشعبة لإجراء عدِّة عمليات دوران متداخلة في برامجنا. سننظر في هذا القسم إلى حلقة for متشعبة وسنحاول تحويلها إلى تعبير list comprehension. هذه الشيفرة ستُنشِئ قائمةً جديدةً بالدوران على قائمتين وبإجراء عمليات رياضية عليها: my_list = [] for x in [20, 40, 60]: for y in [2, 4, 6]: my_list.append(x * y) print(my_list) سنحصل على الناتج الآتي عند تشغيل البرنامج: [40, 80, 120, 80, 160, 240, 120, 240, 360] الشيفرة السابقة تضرب العناصر الموجودة في أوّل قائمة بالعناصر الموجودة في ثاني قائمة في كل دورة. لتحويل ما سبق إلى تعبير list comprehension، وذلك باختصار السطرين الموجودين في الشيفرة السابقة وتحويلهما إلى سطرٍ وحيدٍ، الذي يبدأ بإجراء العملية x*y، ثم ستلي هذه العملية حلقة for الخارجية، ثم يليها حلقة for الداخلية؛ وسنضيف تعبير print()‎ للتأكد أنَّ ناتج القائمة الجديدة يُطابِق ناتج البرنامج الذي فيه حلقتين متداخلتين: my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6]] print(my_list) الناتج: [40, 80, 120, 80, 160, 240, 120, 240, 360] أدى استعمال تعبير list comprehension في المثال السابق إلى تبسيط حلقتَي for لتصبحا سطرًا وحيدًا، لكن مع إنشاء نفس القائمة والتي ستُسنَد إلى المتغير my_list. توفِّر لنا تعابير list comprehension طريقةً بسيطةً لإنشاء القوائم، مما يسمح لنا باختصار عدِّة أسطر إلى سطرٍ وحيد. لكن من المهم أن تبقي في ذهنك أنَّ سهولة قراءة الشيفرة لها الأولوية دومًا، لذا إذا أصبحتَ تعابير list comprehension طويلةً جدًا ومعقدة، فمن الأفضل حينها تحويلها إلى حلقات تكرار عادية. الخلاصة تسمح تعابير list comprehension لنا بتحويل قائمة أو أي نوع من البيانات المتسلسلة إلى سلسلةٍ جديدة، ولها شكلٌ بسيطٌ يُقلِّل عدد الأسطر التي نكتبها. تتبع تعابير list comprehension شكلًا رياضيًا معيّنًا، لذا قد يجدها المبرمجون أولو الخلفية الرياضية سهلة الفهم. وصحيحٌ أنَّ تعابير list comprehension تختصر الشيفرةـ لكن من المهم جعل سهولة قراءة الشيفرة من أولوياتنا، وحاول تجنّب الأسطر الطويلة لتسهيل قراءة الشيفرة. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة –وبتصرّف– للمقال Understanding List Comprehensions in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم نوع البيانات Tuples في بايثون 3 المقالة السابقة: كيفية استخدام توابع القوائم في بايثون 3
  14. الدالة str.format()‎ المتوافرة للسلاسل النصية تسمح لك باستبدال المتغيرات وتنسيق القيم. مما يمنحك القدرة على تجميع العناصر مع بعضها عبر إدخالها في مواضع معينة. سيشرح لك هذا الدرس أشهر الاستخدامات لآلية تنسيق السلاسل النصية في بايثون، والتي ستساعدك في جعل شيفرتك وبرنامجك أسهل قراءةً واستخدامًا. استخدام «المُنسِّقات» تعمل المُنسِّقات (formatters) بوضع حقول قابلة للاستبدال تُعرَّف عبر وضع قوسين معقوفين {} في السلسلة النصية ثم استدعاء الدالة str.format()‎، إذ ستُمرَّر القيمة التي تريد وضعها ضمن السلسلة النصية إلى الدالة format()‎ وستوضع هذه القيمة في نفس مكان الحقل القابل للاستبدال الموجود في السلسلة الأصلية عندما تُشغِّل برنامجك. لنطبع سلسلةً نصيةً تستخدم «مُنسِّقًا» (formatter): print("Sammy has {} balloons.".format(5)) الناتج: Sammy has 5 balloons. أنشأنا في المثال السابق سلسلةً نصيةً تحتوي على قوسين معقوفين: "Sammy has {} balloons." ثم أضفنا الدالة str.format()‎ ومررنا إليها القيمة الرقمية 5 وهذا يعني أنَّ القيمة 5 ستوضع مكان القوسين المعقوفين: Sammy has 5 balloons. يمكننا أيضًا إسناد السلسلة النصية الأصلية التي تحتوي مُنسِّقًا إلى متغير: open_string = "Sammy loves {}." print(open_string.format("open source")) الناتج: Sammy loves open source. أضفنا في المثال السابق السلسلة النصية "open source" إلى سلسلةٍ نصيةٍ أكبر باستبدالها للقوسين المعقوفين الموجودَين في السلسلة الأصلية. تسمح لك المُنسِّقات في بايثون باستخدام الأقواس المعقوفة لحجز أماكن للقيم التي ستمررها مستقبلًا عبر الدالة str.format()‎. استخدام المُنسِّقات لحجز أكثر من مكان يمكنك استخدام أكثر من زوج من الأقواس المعقوفة عند استعمال المُنسِّقات؛ فيمكنك أن تضيف سلسلةً نصيةً أخرى إلى المثال السابق وذلك بإضافة زوج آخر من الأقواس المعقوفة وتمرير قيمة ثانية إلى الدالة كما يلي: new_open_string = "Sammy loves {} {}." # {} مكانين محجوزين عبر print(new_open_string.format("open-source", "software")) # تمرير قيمتين إلى الدالة مفصولٌ بينهما بفاصلة الناتج: Sammy loves open-source software. أضفنا زوجًا آخر من الأقواس المعقوفة إلى السلسلة النصية للسماح بوضع قيمة ثانية، ثم مررنا سلسلتين نصيتين إلى الدالة str.format()‎ مفصولٌ بينهما بفاصلة. سنضيف عمليات استبدال أخرى عبر اتباع نفس الآلية التي شرحناها أعلاه: sammy_string = "Sammy loves {} {}, and has {} {}." print(sammy_string.format("open-source", "software", 5, "balloons")) الناتج: Sammy loves open-source software, and has 5 balloons. إعادة ترتيب المنسقات عبر المعاملات الموضعية عندما نترك الأقواس المعقوفة دون معاملات (parameters) ممررة إليها، فستضع بايثون القيم المُمرَّرة إلى الدالة str.format()‎ بالترتيب. هذا تعبيرٌ فيه زوجين من الأقواس المعقوفة يوضع مكانهما سلسلتان نصيتان شبيهٌ بما رأيناه سابقًا في هذا الدرس: print("Sammy the {} has a pet {}!".format("shark", "pilot fish")) الناتج: Sammy the shark has a pet pilot fish! اُستبدِل أوّل زوجٍ من الأقواس المعقوفة ووضعت مكانه القيمة "shark"، ووضعت القيمة "pilot fish" مكان الزوج الثاني من الأقواس. القيم التي مررناها إلى الدالة str.format()‎ كانت بهذا الترتيب: ("shark", "pilot fish") إن سبق لك دراسة أنواع البيانات المُختلفة على بايثون فقد تلاحظ أنَّ القيمة السابقة هي من النوع tuple، ويمكن الوصول إلى كل قيمة موجودة فيها عبر فهرسٍ رقميٍ تابعٍ لها، والذي يبدأ من الفهرس 0. يمكننا تمرير أرقام الفهارس إلى داخل القوسين المعقوفين: print("Sammy the {0} has a pet {1}!".format("shark", "pilot fish")) سنحصل بعد تنفيذ المثال السابق على نفس الناتج التي ظهر دون تحديد أرقام الفهارس يدويًا، وذلك لأننا استدعينا القيم بالترتيب: Sammy the shark has a pet pilot fish! لكن إن عكسنا أرقام الفهارس في معاملات الأقواس المعقوفة فسنتمكن من عكس ترتيب القيم المُمرَّرة إلى السلسلة النصية الأصلية: print("Sammy the {1} has a pet {0}!".format("shark", "pilot fish")) الناتج: Sammy the pilot fish has a pet shark! لكن إن حاولت استخدام الفهرس ذي الرقم 2 ولم تكن لديك إلا قيمتين موجودتين في الفهرسين 0 و 1، فأنت تستدعي قيمةً خارج المجال المسموح، ولهذا السبب ستظهر رسالة خطأ: print("Sammy the {2} has a pet {1}!".format("shark", "pilot fish")) الناتج: IndexError: tuple index out of range تُشير رسالة الخطأ إلى وجود قيمتين فقط ومكانهما هو 0 و1، لذا كان الفهرس 2 غير مرتبطٍ بقيمةٍ وكان خارج المجال المسموح. لنضف الآن مكانين محجوزين إلى السلسلة النصية ولنمرر بضع قيم إلى الدالة str.format()‎ لكي نفهم آلية إعادة الترتيب فهمًا تامًا. هذه هي السلسلة النصية الجديدة التي فيها أربعة أزواج من الأقواس المعقوفة: print("Sammy is a {}, {}, and {} {}!".format("happy", "smiling", "blue", "shark")) الناتج: Sammy is a happy, smiling and blue shark! ستوضع القيم المُمرَّرة إلى الدالة str.format()‎ بنفس ترتيب ورودها في حال لم نستعمل المعاملات داخل الأقواس المعقوفة. تملك السلاسل النصية المُمرَّرة إلى الدالة str.format()‎ الفهارس الآتية المرتبطة بها: “happy” “smiling” “blue” “shark” 0 1 2 3 لنستخدم الآن أرقام الفهارس لتغيير ترتيب ظهور القيم المرتبطة بها في السلسلة النصية: print("Sammy is a {3}, {2}, and {1} {0}!".format("happy", "smiling", "blue", "shark")) الناتج: Sammy is a shark, blue, and smiling happy! ولمّا كنّا قد بدأنا بالفهرس ذي الرقم 3، فستظهر القيمة "shark" أولًا. أي أنَّ وضع رقم الفهرس بين القوسين كمعامل سيؤدي إلى تغيير ترتيب ظهور القيم في السلسلة النصية الأصلية. نستطيع -بالإضافة إلى المعاملات الموضعية الرقمية- أن نربط بين القيم وبين كلمات محجوزة مخصصة ومن ثم نستدعيها عبر وضع الكلمة المحجوزة بين القوسين المعقوفين كما يلي: print("Sammy the {0} {1} a {pr}.".format("shark", "made", pr = "pull request")) الناتج: Sammy the shark made a pull request. أظهر المثال السابق استخدام كلمة محجوزة كوسيط بالإضافة إلى المعاملات الموضعية، يمكنك استخدام الكلمة المحجوزة pr كوسيط بالإضافة إلى أرقام الفهارس، وتستطيع أيضًا إعادة ترتيب تلك الوسائط كيفما شئت: print("Sammy the {pr} {1} a {0}.".format("shark", "made", pr = "pull request")) الناتج: Sammy the pull request made a shark. استخدام المعاملات الموضعية والكلمات المحجوزة سيمنحنا تحكمًا أكبر بكيفية معالجة السلسلة النصية الأصلية عبر إعادة ترتيب القيم المُمرَّرة إليها. تحديد نوع القيمة يمكنك وضع معاملات أخرى ضمن القوسين المعقوفين، سنستخدم الصيغة الآتية {field_name:conversion} حيث field_name هو الفهرس الرقمي للوسيط الممرَّر إلى الدالة str.format()‎ والذي شرحناه تفصيليًا في القسم السابق، و conversion هو الرمز المستعمل للتحويل إلى نوع البيانات الذي تريده. «رمز التحويل» يعني رمزًا من حرفٍ وحيد الذي تستخدمه بايثون لمعرفة نوع القيمة المُراد «تنسيقها». الرموز التي سنستخدمها في أمثلتنا هي s للسلاسل النصية و d لإظهار الأرقام بنظام العد العشري (ذي الأساس 10) و f لإظهار الأعداد ذات الفاصلة. يمكنك قراءة المزيد من التفاصيل عن رموز التنسيق في بايثون 3 (وغير ذلك من المواضيع المرتبطة بهذا المجال) في التوثيق الرسمي. لننظر إلى مثالٍ نُمرِّر فيه رقمًا صحيحًا عبر الدالة format()‎ لكننا نريد إظهاره كعددٍ ذي فاصلة عبر رمز التحويل f: print("Sammy ate {0:f} percent of a {1}!".format(75, "pizza")) الناتج: Sammy ate 75.000000 percent of a pizza! وضعت القيمة -مكان أوّل ورود للصيغة {field_name:conversion}- كعددٍ ذي فاصلة، أما ثاني ورود للقوسين المعقوفين فكان بالصيغة {field_name}. لاحظ في المثال السابق وجود عدد كبير من الأرقام الظاهرة بعد الفاصلة العشرية، لكنك تستطيع تقليل عددها. فعندما نستخدم الرمز f للقيم ذات الفاصلة نستطيع أيضًا تحديد دقة القيمة الناتجة بتضمين رمز النقطة . متبوعًا بعدد الأرقام بعد الفاصلة التي نود عرضها. حتى لو أكل سامي 75.765367% من قطعة البيتزا فلن نحتاج إلى هذا القدر الكبير من الدقة، إذ يمكننا مثلًا أن نجعل عدد المنازل العشرية ثلاث منازل بعد الفاصلة بوضعنا ‎.3 قبل رمز التحويل f: print("Sammy ate {0:.3f} percent of a pizza!".format(75.765367)) الناتج: Sammy ate 75.765 percent of a pizza! أما إذا أردنا عرض منزلة عشرية وحيدة، فيمكننا إعادة كتابة السلسلة السابقة كالآتي: print("Sammy ate {0:.1f} percent of a pizza!".format(75.765367)) الناتج: Sammy ate 75.8 percent of a pizza! لاحظ كيف أدى تعديل دقة الأرقام العشرية إلى تقريب الرقم (وفق قواعد التقريب الاعتيادية). وصحيحٌ أننا عرضنا رقمًا دون منازل عشرية كعددٍ ذي فاصلة، إلا أننا إذا حاولنا تحويل عدد عشري إلى عدد صحيح باستخدام رمز التحويل d فسنحصل على خطأ: print("Sammy ate {0:.d} percent of a pizza!".format(75.765367)) الناتج: ValueError: Unknown format code 'd' for object of type 'float' إذا لم ترغب بعرض أيّة منازل عشرية، فيمكنك كتابة تعبير كالآتي: print("Sammy ate {0:.0f} percent of a pizza!".format(75.765367)) الناتج: Sammy ate 76 percent of a pizza! لن يؤدي ما سبق إلى تحويل العدد العشري إلى عددٍ صحيح، وإنما سيؤدي إلى تقليل عدد المنازل العشرية الظاهرة بعد الفاصلة. إضافة حواشي لمّا كانت الأماكن المحجوزة عبر القوسين المعقوفين هي حقول قابلة للاستبدال (أي ليست قيمًا فعليةً) فيمكنك إضافة حاشية (padding) أو إضافة فراغ حول العنصر بزيادة حجم الحقل عبر معاملات إضافية، قد تستفيد من هذا الأمر عندما تحتاج إلى تنظيم البيانات بصريًا. يمكننا إضافة حقلٍ بحجمٍ معيّن (مُقاسًا بعدد المحارف) بتحديد ذاك الحجم بعد النقطتين الرأسيتين : كما في المثال الآتي: print("Sammy has {0:4} red {1:16}!".format(5, "balloons")) الناتج: Sammy has 5 red balloons ! أعطينا في المثال السابق حقلًا بحجم 4 محارف للعدد 5، وأعطينا حقلًا بحجم 16 محرفًا للسلسلة النصية balloons (لأنها سلسلة طويلة نسبيًا). وكما رأينا من ناتج المثال السابق، يتم محاذاة السلاسل النصية افتراضيًا إلى اليسار والأعداد إلى اليمين، يمكنك أن تُغيّر من هذا بوضع رمز خاص للمحاذاة بعد النقطتين الرأسيتين مباشرةً. إذ سيؤدي الرمز > إلى محاذاة النص إلى يسار الحقل، أما الرمز ^ فسيوسِّط النص في الحقل، والرمز < سيؤدي إلى محاذاته إلى اليمين. لنجعل محاذاة العدد إلى اليسار ونوسِّط السلسلة النصية: print("Sammy has {0:<4} red {1:^16}!".format(5, "balloons")) الناتج: Sammy has 5 red balloons ! نلاحظ الآن أنَّ محاذاة العدد 5 إلى اليسار، مما يعطي مساحة فارغةً في الحقل قبل الكلمة red، وستظهر السلسلة النصية balloons في منتصف الحقل وتوجد مسافة فارغة على يمينها ويسارها. عندما نُنسِّق الحقل لنجعله أكبر من حجمه الطبيعي فستملأ بايثون الحقل افتراضيًا بالفراغات، إلا أننا نستطيع تغيير محرف الملء إلى محرفٍ آخر بوضعه مباشرةً بعد النقطتين الرأسيتين: print("{:*^20s}".format("Sammy")) الناتج: *******Sammy******** ستضع بايثون السلسلة النصية المُمرَّرة إلى الدالة str.format()‎ ذات الفهرس 0 مكان القوسين المعقوفين لأننا لم نطلب منها عكس ذلك، ومن ثم سنضع النقطتين الرأسيتين ثم سنُحدِّد أننا سنستعمل المحرف * بدلًا من الفراغات لملء الحقل، ثم سنوسِّط السلسلة النصية عبر استعمال الرمز ^ مُحدِّدين أنَّ حجم الحقل هو 20 محرف، ومُشيرين في نفس الوقت إلى أنَّ الحقل هو حقلٌ نصيٌ عبر وضع الرمز s. يمكننا استخدام هذه المعاملات مع المعاملات التي استخدمناها وشرحناها في الأقسام السابقة: print("Sammy ate {0:5.0f} percent of a pizza!".format(75.765367)) الناتج: Sammy ate 76 percent of a pizza! حدِّدنا داخل القوسين المعقوفين رقم فهرس القيمة العددية ثم وضعنا النقطتين الرأسيتين ثم اخترنا حجم الحقل ثم وضعنا نقطةً . لنضبط عدد المنازل العشرية الظاهرة، ثم اخترنا نوع الحقل عبر رمز التحويل f. استخدام المتغيرات مرَّرنا منذ بداية هذا الدرس وإلى الآن الأعداد والسلاسل النصية إلى الدالة str.format()‎ مباشرةً، لكننا نستطيع تمرير المتغيرات أيضًا، وذلك بنفس الآلية المعتادة: nBalloons = 8 print("Sammy has {} balloons today!".format(nBalloons)) الناتج: Sammy has 8 balloons today! يمكننا أيضًا استخدام المتغيرات لتخزين السلسلة النصية الأصلية بالإضافة إلى القيم التي ستُمرَّر إلى الدالة: sammy = "Sammy has {} balloons today!" nBalloons = 8 print(sammy.format(nBalloons)) الناتج: Sammy has 8 balloons today! ستُسهِّل المتغيرات من التعامل مع تعبيرات التنسيق وتُبسِّط عملية إسناد مدخلات المستخدم وإظهارها مُنسَّقةً في السلسلة النصية النهائية. استخدام المُنسِّقات لتنظيم البيانات يسطع نجم آلية التنسيق التي نشرحها في هذا الدرس عندما تُستخدَم لتنظيم البيانات بصريًا، فلو أردنا إظهار نتائج قاعدة البيانات إلى المستخدمين، فيمكننا استعمال المُنسِّقات لزيادة حجم الحقل وتعديل المحاذاة لجعل الناتج أسهل قراءةً. لننظر إلى حلقة تكرار تقليدية في بايثون التي تطبع i و i*i و i*i*i لمجالٍ من الأعداد من 3 إلى 13: for i in range(3,13): print(i, i*i, i*i*i) الناتج: 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728 صحيحٌ أنَّ الناتج مُنظَّمٌ قليلًا، إلا أنَّ الأعداد تتداخل مع بعضها بصريًا مما يُصعِّب قراءة الأسطر الأخيرة من الناتج، وإذا كنتَ تتعامل مع مجموعة أكبر من البيانات التي يتواجد فيها أعداد أكبر (أو أصغر) مما عرضناه في مثالنا، فقد تبدو لك المشكلة جليةً حينها. لنحاول تنسيق الناتج السابق لإعطاء مساحة أكبر لإظهار الأعداد: for i in range(3,13): print("{:3d} {:4d} {:5d}".format(i, i*i, i*i*i)) لم نُحدِّد في المثال السابق ترتيب الحقل وبدأنا مباشرةً بكتابة النقطتين الرأسيتين متبوعةً بحجم الحقل ورمز التحويل d (لأننا نتعامل مع أعداد صحيحة). أعطينا في المثال السابق حجمًا للحقل مساويًا لعدد أرقام العدد الذي نتوقع طباعته في الحقل المعني مضافًا إليه 2، لذا سيبدو الناتج كالآتي: 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728 يمكننا أيضًا تحديد حجم ثابت للحقل لنحصل على أعمدة متساوية العرض، مما يضمن إظهار الأعداد الكبيرة بصورة صحيحة: for i in range(3,13): print("{:6d} {:6d} {:6d}".format(i, i*i, i*i*i)) الناتج: 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 11 121 1331 12 144 1728 يمكننا أيضًا تعديل محاذاة النص الموجود في الأعمدة باستخدام الرموز > و ^ و <، وتبديل d إلى f لإظهار منازل عشرية، وغير ذلك مما تعلمناه في هذا الدرس لإظهار البيانات الناتجة كما نرغب. الخلاصة قد يكون استخدام المنسقات لوضع القيم في سلسلةٍ نصيةٍ أمرًا مفيدًا لتسهيل تنظيم البيانات والقيم، فالمنسقات هي آليةٌ تساعد في جعل الناتج مقروءًا للمستخدم. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Use String Formatters in Python 3 لصاحبته Lisa Tagliaferri. اقرأ أيضًا المقالة التالية: كيفية إجراء العمليات الحسابية المقالة السابقة: كيفية استخدام المتغيرات
  15. السلاسل النصية في بايثون هي مجموعةٌ مُنشأةٌ من المحارف المنفصلة والتي تُمثِّل الأحرف والأرقام والفراغات والرموز. ولأنَّ السلسلة النصية هي «سلسلة»، فيمكن الوصول إليها كغيرها من أنواع البيانات المتسلسلة، عبر الفهارس والتقسيم. سيشرح لك هذا الدرس كيفية الوصول إلى السلاسل النصية بفهارسها، وتقسيمها إلى مجموعات من المحارف، وسيُغطي طرائق إحصاء المحارف وتحديد مواضعها. آلية فهرسة السلاسل النصية وكما في نوع البيانات list الذي فيه عناصر مرتبطة بأرقام، فإنَّ كل محرف في السلسلة النصية يرتبط بفهرس معيّن، بدءًا من الفهرس 0. فللسلسلة النصية Sammy Shark!‎ ستكون الفهارس والمحارف المرتبطة بها كالآتي: وكما لاحظت، سيرتبط المحرف S بالفهرس 0، وستنتهي السلسلة النصية بالفهرس 11 مع الرمز !. لاحظ أيضًا أنَّ الفراغ بين كلمتَي Sammy و Shark له فهرسٌ خاصٌ به، وفي مثالنا سيكون له الفهرس 5. علامة التعجب (!) لها فهرسٌ خاصٌ بها أيضًا، وأيّة رموز أو علامات ترقيم أخرى مثل *#$&.;? سترتبط بفهرسٍ مخصصٍ لها. وحقيقة أنَّ المحارف في بايثون لها فهرسٌ خاصٌ بها ستعني أنَّ بإمكاننا الوصول إلى السلاسل النصية وتعديلها كما نفعل مع أنواع البيانات المتسلسلة الأخرى. الوصول إلى المحارف عبر أرقام الفهارس الموجبة يمكننا الحصول على محرف من سلسلة نصية بالإشارة إليه عبر فهرسه. يمكننا فعل ذلك بوضع رقم الفهرس بين قوسين مربعين. سنُعرِّف في المثال الآتي سلسلةً نصيةً ونطبع المحرف المرتبط بالفهرس المذكور بين قوسين مربعين: ss = "Sammy Shark!" print(ss[4]) الناتج: y عندما نُشير إلى فهرسٍ معيّنٍ في سلسلةٍ نصيةٍ، فستُعيد بايثون المحرف الموجود في ذاك الموضع، ولمّا كان المحرف y موجودًا في الفهرس الرابع في السلسلة النصية ss = "Sammy Shark!"‎ فعندما طبعنا ss[4] فظهر الحرف y. الخلاصة: أرقام الفهارس ستسمح لنا بالوصول إلى محارف معيّنة ضمن سلسلة نصية. الوصول إلى المحارف عبر أرقام الفهارس السالبة إذا كانت لديك سلسلةٌ طويلةٌ وأردنا تحديد أحد محارفها لكن انطلاقًا من نهايتها، فعندئذٍ نستطيع استخدام الأرقام السالبة للفهارس، بدءًا من الفهرس ‎-1. لو أردنا أن نستخدم الفهارس السالبة مع السلسلة النصية Sammy Shark!‎، فستبدو كما يلي: يمكننا أن نطبع المحرف r في السلسلة السابقة في حال استخدمنا الفهارس السالبة بالإشارة إلى المحرف الموجود في الفهرس ‎-3 كما يلي: print(ss[-3]) الخلاصة: يمكننا الاستفادة من الفهارس السالبة لو أردنا الوصول إلى محرف في آخر سلسلة نصية طويلة. تقسيم السلاسل النصية يمكننا أن نحصل على مجال من المحارف من سلسلة نصية، فلنقل مثلًا أننا نريد أن نطبع الكلمة Shark فقط، يمكننا فعل ذلك بإنشائنا «لقسم» من السلسلة النصية، والذي هو سلسلةٌ من المحارف الموجودة ضمن السلسلة الأصلية. فالأقسام تسمح لنا بالوصول إلى عدِّة محارف دفعةً واحدة باستعمال مجال من أرقام الفهارس مفصولة فيما بينها بنقطتين رأسيتين [x:y]: print(ss[6:11]) الناتج: Shark عند إنشائنا لقسم مثل [6:11] فسيُمثِّل أوّل رقم مكان بدء القسم (متضمنًا المحرف الموجود عند ذاك الفهرس)، والرقم الثاني هو مكان نهاية القسم (دون تضمين ذاك المحرف)، وهذا هو السبب وراء استخدمنا لرقم فهرس يقع بعد نهاية القسم الذي نريد اقتطاعه في المثال السابق. نحن نُنشِئ «سلسلةً نصيةً فرعيةً» (substring) عندما نُقسِّم السلاسل النصية، والتي هي سلسلةٌ موجودةٌ ضمن سلسلةٍ أخرى. وعندما نستخدم التعبير ss[6:11] فنحن نستدعي السلسلة النصية Shark التي تتواجد ضمن السلسلة النصية Sammy Shark!‎. إذا أردت تضمين نهاية السلسلة (أو بدايتها) في القسم الذي ستُنشِئه، فيمكننا ألّا نضع أحد أرقام الفهارس في string[n:n]. فمثلًا، نستطيع أن نطبع أوّل كلمة من السلسلة ss –أي Sammy– بكتابة ما يلي: print(ss[:5]) فعلنا ذلك بحذف رقم الفهرس قبل النقطتين الرأسيتين، ووضعنا رقم فهرس النهاية فقط، الذي يُشير إلى مكان إيقاف اقتطاع السلسلة النصية الفرعية. لطباعة منتصف السلسلة النصية إلى آخرها، فسنضع فهرس البداية فقط قبل النقطتين الرأسيتين، كما يلي: print(ss[7:]) الناتج: hark! بكتابة فهرس البداية فقط قبل النقطتين الرأسيتين وترك تحديد الفهرس الثاني، فإنَّ السلسلة الفرعية ستبدأ من الفهرس الأول إلى نهاية السلسلة النصية كلها. يمكنك أيضًا استخدام الفهارس السالبة في تقسيم سلسلة نصية، فكما ذكرنا سابقًا، تبدأ أرقام الفهارس السلبية من الرقم ‎-1، ويستمر العد إلى أن نصل إلى بداية السلسلة النصية. وعند استخدام الفهارس السالبة فسنبدأ من الرقم الأصغر لأنه يقع أولًا في السلسلة. لنستخدم فهرسين ذوي رقمين سالبين لاقتطاع جزء من السلسلة النصية ss: print(ss[-4:-1]) الناتج: ark السلسلة النصية «ark» مأخوذة من السلسلة النصية «Sammy Shark!‎» لأنَّ الحرف «a» يقع في الموضع ‎-4 والمحرف k يقع قبل الفهرس ‎-1 مباشرةً. تحديد الخطوة عند تقسيم السلاسل النصية يمكن تمرير معامل ثالث عند تقسيم السلاسل النصية إضافةً إلى فهرسَي البداية والنهاية، وهو الخطوة، التي تُشير إلى عدد المحارف التي يجب تجاوزها بعد الحصول على المحرف من السلسلة النصية. لم نُحدِّد إلى الآن الخطوة في أمثلتنا، إلا أنَّ قيمته الافتراضية هي 1، لذا سنحصل على كل محرف يقع بين الفهرسين. لننظر مرةً أخرى إلى المثال السابق الذي يطبع السلسلة النصية الفرعية «Shark»: print(ss[6:11]) Shark سنحصل على نفس النتائج بتضمين معامل ثالث هو الخطوة وقيمته 1: print(ss[6:11:1]) Shark إذًا، إذا كانت الخطوة 1 فهذا يعني أنَّ بايثون ستُضمِّن جميع المحارف بين فهرسين، وإذا حذفتَ الخطوة فستعتبرها بايثون مساويةً للواحد. أما لو زدنا الخطوة، فسنرى أنَّ بعض المحارف ستهمل: print(ss[0:12:2]) SmySak تحديد الخطوة بقيمة 2 كما في ss[0:12:2] سيؤدي إلى تجاوز حرف بين كل حرفين، ألقِ نظرةً على المحارف المكتوبة بخطٍ عريضٍ: Sammy Shark! لاحظ أنَّ الفراغ الموجود في الفهرس 5 قد أُهمِل أيضًا عندما كانت الخطوة 2. إذا وضعنا قيمةً أكبر للخطوة، فسنحصل على سلسلةٍ نصيةٍ فرعيةٍ أصغر بكثير: print(ss[0:12:4]) Sya حذف الفهرسين وترك النقطتين الرأسيتين سيؤدي إلى إبقاء كامل السلسلة ضمن المجال، لكن إضافة معامل ثالث وهو الخطوة سيُحدِّد عدد المحارف التي سيتم تخطيها. إضافةً إلى ذلك، يمكنك تحديد رقم سالب كخطوة، مما يمكِّنك من كتابة السلسلة النصية بترتيبٍ معكوس إذا استعملتَ القيمة ‎-1: print(ss[::-1]) الناتج: !krahS ymmaS لنجرِّب ذلك مرةً أخرى لكن إذا كانت الخطوة ‎-2: print(ss[::-2]) الناتج: !rh ma في المثال السابق (ss[::-2])، سنتعامل مع كامل السلسلة النصية لعدم وجود أرقام لفهارس البداية والنهاية، وسيتم قلب اتجاه السلسلة النصية لاستخدامنا لخطوةٍ سالبة. بالإضافة إلى أنَّ الخطوة ‎-2 ستؤدي إلى تخطي حرف بين كل حرفين بترتيبٍ معكوس: !krahS[whitespace]ymmaS سيُطبَع الفراغ في المثال السابق. الخلاصة: تحديد المعامل الثالث عند تقسيم السلاسل النصية سيؤدي إلى تحديد الخطوة التي تُمثِّل عدد المحارف التي سيتم تخطيها عند الحصول على السلسلة الفرعية من السلسلة الأصلية. دوال الإحصاء بعد أن تعرفنا على آلية فهرسة المحارف في السلاسل النصية، حان الوقت لمعاينة بعض الدوال التي تُحصي السلاسل النصية أو تعيد أرقام الفهارس. يمكننا أن نستفيد من ذلك بتحديد عدد المحارف التي نريد استقبالها من مدخلات المستخدم، أو لمقارنة السلاسل النصية. ولدى السلاسل النصية –كغيرها من أنواع البيانات– عدِّة دوال تُستخدم للإحصاء. لننظر أولًا إلى الدالة len()‎ التي تُعيد طول أيّ نوع متسلسل من البيانات، بما في ذلك string و lists و tuples و dictionaries. لنطبع طول السلسلة النصية ss: print(len(ss)) 12 طول السلسلة النصية «Sammy Shark!‎» هو 12 محرفًا، بما في ذلك الفراغ وعلامة التعجب. بدلًا من استخدام متغير، فلنحاول مباشرةً تمرير سلسلة نصية إلى الدالة len()‎: print(len("Let's print the length of this string.")) 38 الدالة len()‎ تُحصي العدد الإجمالي من المحارف في سلسلة نصية. إذا أردنا إحصاء عدد مرات تكرار محرف أو مجموعة من المحارف في سلسلة نصية، فيمكننا استخدام الدالة str.count()‎، لنحاول إحصاء الحرف «a» في السلسلة النصية ss = "Sammy Shark!"‎: print(ss.count("a")) 2 يمكننا البحث عن محرفٍ آخر: print(ss.count("s")) 0 صحيحٌ أنَّ الحرف «S» قد ورد في السلسلة النصية، إلا أنَّه من الضروري أن تبقي بذهنك أنَّ بايثون حساسةٌ لحالة الأحرف، فلو أردنا البحث عن حروفٍ معيّنة بغض النظر عن حالتها، فعلينا حينها استخدام الدالة str.lower()‎ لتحويل حروف السلسلة النصية إلى حروفٍ صغيرة أولًا. يمكنك قراءة المزيد من المعلومات عن دالة str.lower()‎ في درس «مقدمة إلى دوال التعامل مع السلاسل النصية في بايثون 3» لنحاول استخدام الدالة str.count()‎ مع سلسلة من المحارف: likes = "Sammy likes to swim in the ocean, likes to spin up servers, and likes to smile." print(likes.count("likes")) الناتج هو 3، حيث تتواجد مجموعة المحارف «likes» ثلاث مرات في السلسلة النصية الأصلية. يمكننا أيضًا معرفة موقع الحرف أو مجموعة الحروف في السلسلة النصية، وذلك عبر الدالة str.find()‎، وسيُعاد موضع المحرف بناءً على رقم فهرسه. يمكننا أن نعرف متى يقع أوّل حرف «m» في السلسلة النصية ss كالآتي: print(ss.find("m")) 2 أوّل مرة يقع فيها الحرف «m» في الفهرس 2 من السلسلة «Sammy Shark!‎»، يمكنك أن تراجع بداية هذا الدرس لرؤية جدول يبيّن ارتباطات المحارف مع فهارسها في السلسلة السابقة. لنرى الآن مكان أوّل ظهور لمجموعة المحارف «likes» في السلسلة likes: print(likes.find("likes")) 6 أوّل مرة تظهر فيها السلسلة «likes» هي في الفهرس 6، أي مكان وجود الحرف l من likes. ماذا لو أردنا أن نعرف موضع ثاني تكرار للكلمة «likes»؟ نستطيع فعل ذلك بتمرير معاملٍ ثانٍ إلى الدالة str.find()‎ الذي سيجعلها تبدأ بحثها من ذاك الفهرس، فبدلًا من البحث من أوّل السلسلة النصية سنبحث انطلاقًا من الفهرس 9: print(likes.find("likes", 9)) 34 بدأ البحث في هذا المثال من الفهرس 9، وكانت أوّل مطابقة للسلسلة النصية «likes» عند الفهرس 34. إضافةً إلى ذلك، يمكننا تحديد نهاية إلى مجال البحث بتمرير معامل ثالث. وكما عند تقسيم السلاسل النصية، يمكننا استخدام أرقام الفهارس السالبة للعد عكسيًا: print(likes.find("likes", 40, -6)) 64 يبحث آخر مثال عن موضع السلسلة النصية «likes» بين الفهرس 40 و ‎-6، ولمّا كان المعامل الأخير هو رقم سالب، فسيبدأ العد من نهاية السلسلة الأصلية. دوال الإحصاء مثل len()‎ و str.count()‎ و str.find()‎ مفيدةٌ في تحديد طول السلسلة النصية وعدد حروفها وفهارس ورود محارف معيّنة فيها. الخلاصة ستمنحنا القدرة على تحديد محارف بفهارسها أو تقسيم سلسلة نصية أو البحث فيها مرونةً عاليةً عند التعامل مع السلاسل النصية. ولأنَّ السلاسل النصية هي نوعٌ من أنواع البيانات المتسلسلة (كنوع البيانات list)، فيمكننا الوصول إلى عناصرها عبر فهارس خاصة. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Index and Slice Strings in Python 3 لصاحبته Lisa Tagliaferri. اقرأ أيضًا المقال التالي: كيفية التحويل بين أنواع البيانات المقال السابق: مقدمة إلى دوال التعامل مع السلاسل النصية
  16. تُستخدم في بايثون، كما هو الحال في جميع لغات البرمجة، أنواع البيانات لتصنيف البيانات. هذا مهم لأنّ نوع البيانات الذي تستخدمه سيحدد القيم التي يمكن تعيينها لها، وما الذي يمكن فعله بها (بما في ذلك العمليات التي يمكن تنفيذها عليها). سنتعرف في هذه المقالة على أهم أنواع البيانات الأصلية لبايثون. هذا ليس استقصاءً شاملًا لأنواع البيانات، ولكنه سيساعدك على التعرف على الخيارات المتاحة لك في بايثون. مدخل أنواع البيانات في بايثون مشابهة إلى حد ما لأنواع البيانات التي نستخدمها في العالم الحقيقي. من أمثلة أنواع البيانات في العالم الحقيقي الأعداد، مثل: الأعداد الصحيحة الطبيعية (0، 1، 2، ...)، والأعداد الصحيحة النسبية (...، 1-، 0، 1، ...)، والأعداد غير النسبية (π). يمكننا عادة في الرياضيات جمع أعداد من أنواع مختلفة مثل إضافة 5 إلى π: 5 + π يمكننا إما الاحتفاظ بالمعادلة كإجابة، وستكون النتيجة عددًا غير نسبي (irrational number)، أو يمكننا تقريب (round) العدد π إلى عدد ذي منازل عشرية محددة، ثم نجمع العددين: 5 + π = 5 + 3.14 = 8.14 ولكن، إذا حاولنا إضافة عدد إلى نوع بيانات آخر، مثل الكلمات، فستصبح الأمور مربكة وغير ذات معنى. فكيف ستحل المعادلة التالية مثلًا؟ hsoub + 8 بالنسبة إلى الكلمة hsoub، يمكن عدكل نوع من أنواع البيانات مختلفًا تمامًا، مثل الكلمات والأعداد، لذلك يتعين علينا توخي الحذر بشأن كيفية استخدامها، وكيفية التعامل معها في العمليات. الأعداد سيُفسَّر كل عدد تُدخله إلى بايثون كعدد؛ ليس مطلوبًا منك إعلان نوع البيانات الذي تدخله لأنّ بايثون تَعدُّ أيّ عدد مكتوب بدون فواصل عشرية بمثابة عدد صحيح (integer، كما هو حال 138)، وأيّ عدد مكتوب بفواص لعشرية بمثابة عدد عشري (float كما هو حال 138.0). الأعداد الصحيحة كما هو الحال في الرياضيات، الأعداد الصحيحة (integer) في البرمجة هي أعداد كاملة، يمكن أن تكون موجبة أو سالبة أو معدومة (...، ‎1،0،-1، ...). ويُعرف هذا النوع أيضًا باسم int. كما هو الحال مع لغات البرمجة الأخرى، يجب ألا تستخدم الفواصل في الأعداد المؤلفة من أربعة أرقام أو أكثر، لذلك لا تكتب 1,000 في برنامجك، واكتب 1000. يمكننا طباعة العدد الصحيح على النحو التالي: print(-25) وسينتج: -25 أو يمكننا الإعلان عن متغير، والذي هو في هذه الحالة رمزٌ للعدد الذي نستخدمه أو نتعامل معه، مثلًا: my_int = -25 print(my_int) وسينتج لنا: -25 يمكننا أن نجري العمليات الحسابية على الأعداد الصحيحة في بايثون: int_ans = 116 - 68 print(int_ans) المخرجات: 48 يمكن استخدام الأعداد الصحيحة بعدة طرق في برامج بايثون، ومع استمرارك في تعلم المزيد عن هذه اللغة، ستتاح لك الكثير من الفرص لاستخدام الأعداد الصحيحة وفهم المزيد عن هذا النوع من البيانات. الأعداد العشرية الأعداد العشرية (Floating-Point Numbers) هي أعداد حقيقية، مما يعني أنه يمكن أن تكون أعدادًا جذرية أو غير نسبية. لهذا السبب، يمكن أن تحتوي الأعداد العشرية على جزء كسري، مثل 9.0 أو ‎-116.42. وببساطة، فالأعداد العشرية هي أعداد تحتوي الفاصلة العشرية. كما فعلنا مع الأعداد الصحيحة، يمكننا طباعة الأعداد العشرية هكذا: print(17.3) وسينتج لنا: 17.3 يمكننا أيضًا أن نعلن عن متغير يحتوى عددًا عشريًا، مثلًا: my_flt = 17.3 print(my_flt) الناتج: 17.3 وكما هو الحال مع الأعداد الصحيحة، يمكننا أن نجرى العمليات الحسابية على الأعداد العشرية: flt_ans = 564.0 + 365.24 print(flt_ans) الناتج: 929.24 الأعداد الصحيحة والأعداد العشرية مختلفان عمومًا، إذ أنّ 3 ≠ 3.0، لأنّ 3 عدد صحيح، بينما 3.0 عدد عشري. القيم المنطقية هناك قيمتان فقط لنوع البيانات المنطقية (Boolean) وهما True و False. تُستخدم القيم المنطقية لتمثيل قيم الحقيقة الموافقة للمنطق الرياضياتي. عادة ما يبدأ اسم البيانات المنطقية بالحرف B، إشارة إلى اسم عالم الرياضيات George Boole. القيمتان True و False تُكتبان دائمًا بحرفين كبيرين T و F، لأنها قيم خاصة في بايثون. الكثير من العمليات الحسابية في الرياضيات تُنتج قيمًا منطقيًا، إما True أو False: أكبر من 500 > 100 True 1 > 5 False أصغر من 200 < 400 True 4 < 2 False التساوي 5 = 5 True 500 = 400 False كما هو الحال مع الأعداد، يمكننا تخزين القيم المنطقية في المتغيرات: my_bool = 5 > 8 يمكننا بعد ذلك طباعة القيمة المنطقية باستدعاء الدالة print()‎: print(my_bool) بما أنّ العدد 5 ليس أكبر من 8، فسوف نحصل على المخرجات التالية: False ستتعلم مع مرور الوقت كيفية استخدام القيم المنطقية، وكيف يمكن للدوال والعمليات المنطقية أن تغير مسار البرنامج. السلاسل النصية السلسلة النصية (string) هي عبارة عن تسلسل من محرف واحد أو أكثر (محارف وأعداد ورموز)، ويمكن أن تكون ثابتة أو متغيرة. تحاط السلاسل النصية إما بعلامات الاقتباس المفردة ' أو علامات الاقتباس المزدوجة "، لذلك لإنشاء سلسلة نصية، ضع سلسلة من الأحرف بين علامتي اقتباس: 'هذه سلسلة نصية ضمن علامتي اقتباس مفردتين' "هذه سلسلة نصية ضمن علامتي اقتباس مزدوجتين" يمكنك استخدام علامات الاقتباس المفردة أو علامات الاقتباس المزدوجة، المهم أن تكون متسقًا في برنامجك. البرنامج البسيط "Hello, World!‎" يوضح كيف يمكن استخدام السلاسل النصية في البرمجة، حيث أنّ حروف عبارة Hello، World!‎ تمثل سلسلة نصية. print("Hello, World!") كما هو الحال مع أنواع البيانات الأخرى، يمكننا تخزين السلاسل النصية في المتغيرات: hw = "Hello, World!" وطباعة السلسلة عن طريق استدعاء المتغير: print(hw) // Hello, World! مثل الأعداد، هناك العديد من العمليات التي يمكن إجراؤها على السلاسل النصية من أجل تحقيق النتائج التي نسعى إليها. السلاسل النصية مهمة لتوصيل المعلومات إلى المستخدم، وكذلك لتمكين المستخدم من تمرير المعلومات إلى البرنامج. القوائم القائمة (lists) عبارة عن تسلسل مرتّب قابل للتغيير (mutable). وكما تُعرّف السلاسل النصية باستخدام علامات الاقتباس، يتم تعريف القوائم باستخدام الأقواس المعقوفة []. مثلًا، هذه قائمة تحوي أعدادًا صحيحةً: [-3, -2, -1, 0, 1, 2, 3] وهذه قائمة من الأعداد العشرية: [3.14, 9.23, 111.11, 312.12, 1.05] وهذه قائمة من السلاسل النصية: ['shark', 'cuttlefish', 'squid', 'mantis shrimp'] في المثال التالي، سنسمّى قائمة السلاسل النصية خاصتنا sea_creatures: sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis shrimp'] يمكننا طباعتها عن طريق استدعاء المتغير: print(sea_creatures) وسترى أنّ المخرجات تشبه تمامًا القائمة التي أنشأناها: ['shark', 'cuttlefish', 'squid', 'mantis shrimp'] القوائم هي نوع بيانات مرن للغاية، لأنها قابلة للتغيير، حيث يمكن إضافة قيم إليها، أو إزالته، أو تغييرها. هناك نوع بيانات آخر مشابه لقوائم، بيْد أنه غير قابل للتغيير، ويُسمى الصف (tuple). الصفوف (Tuples) يُستخدم الصف (tuple) لتجميع البيانات. إنه تسلسل ثابت من العناصر وغير قابل للتغيير. الصفوف تشبه القوائم إلى حد كبير، لكنها تستخدم الأقواس () بدلًا من الأقواس المعقوفة []، ولأنها غير قابلة للتغيير، فلا يمكن تغيير أو تعديل قيمها. تبدو الصفوف كالتالي: ('blue coral', 'staghorn coral', 'pillar coral') يمكننا تخزين الصفوف في المتغيرات وطباعتها: coral = ('blue coral', 'staghorn coral', 'pillar coral') print(coral) والمخرجات هي: ('blue coral', 'staghorn coral', 'pillar coral') كما هو الحال في أنواع البيانات الأخرى، تطبع بايثون الصفوف تمامًا كما كتبناها، حيث تطبع سلسلة من القيم بين قوسين. القواميس القاموس (Dictionaries) هو نوع مُضمّن في بايثون، إذ تُربط مفاتيحُ بالقيم المقابلة لها في شكل أزواج، هذه الأزواج مفيدة لتخزين البيانات في بايثون. يتم إنشاء القواميس باستخدام الأقواس المعقوصة {}. تُستخدم القواميس عادةً لحفظ البيانات المترابطة، مثل المعلومات المقابلة لرقم تعريف. يبدو القاموس كما يلي: {'name': 'Sammy', 'animal': 'shark', 'color': 'blue', 'location': 'ocean'} ستلاحظ أنه بالإضافة إلى الأقواس المعقوصة، توجد علامات النقطتين الرأسيتين (colons) داخل القاموس. الكلمات الموجودة على يسار النقطتين الرأسيتين هي المفاتيح. المفاتيح قد تكون أيّ نوع بيانات غير قابل للتغيير. المفاتيح في القاموس أعلاه هي: 'name', 'animal', 'color', 'location'‎. الكلمات الموجودة على يمين النقطتين هي القيم. يمكن أن تتألف القيم من أي نوع من البيانات. القيم في القاموس أعلاه هي: 'Sammy', 'shark', 'blue', 'ocean'‎. مثل أنواع البيانات الأخرى، يمكننا تخزين القواميس في متغيرات، وطباعتها: sammy = {'name': 'Sammy', 'animal': 'shark', 'color': 'blue', 'location': 'ocean'} print(sammy) والمخرجات هي: {'color': 'blue', 'animal': 'shark', 'name': 'Sammy', 'location': 'ocean'} إذا أردت الحصول على اللون (color) الخاص بـ Sammy، فيمكنك القيام بذلك عن طريق استدعاء sammy ['color']‎. هذا مثال على ذلك: print(sammy['color']) # blue القواميس من أنواع البيانات المهمة في برامج بايثون. خلاصة في هذه المرحلة، يُفترض أن يكون لديك فهم جيد لبعض أنواع البيانات الرئيسية المتاحة في بايثون. أنواع البيانات هذه ستصبح جزءًا طبيعيًا من حياتك كمبرمج للغة بايثون. يمكنك التعرف على المزيد من التفاصيل عن هذه الأنواع في موسوعة حسوب: الأعداد الصحيحة الأعداد العشرية القيم المنطقية السلاسل النصية القوائم الصفوف القواميس بمجرد أن تقوّي وتعمّق فهمك لأنواع البيانات المتاحة في بايثون، يمكنك الانتقال إلى تعلم كيفية تحويل أنواع البيانات في بايثون 3. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Data Types in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: مدخل إلى التعامل مع السلاسل النصية في بايثون 3 المقالة السابقة: كيفية كتابة التعليقات في بايثون 3
  17. التعليقات هي عبارات دخيلة على الشيفرات البرمجية وليست جزءًا منها، إذ تتجاهلها المصرّفات (compilers) والمترجمات (interpreters). يُسهِّل تضمين التعليقات في الشيفرات من قراءتها وفهمها ومعرفة وظيفة كل جزء من أجزائها، لأنها توفر معلومات وشروحات حول ما يفعله كل جزء من البرنامج. بناءً على الغرض من البرنامج، يمكن أن تكون التعليقات بمثابة مُذكَّرات لك، أو يمكنك كتابتها لمساعدة المبرمجين الآخرين على فهم الشيفرة. يُستحسَن كتابة التعليقات أثناء كتابة البرامج أو تحديثها، لأنّك قد تنسى السياق وتسلسل الأفكار لاحقًا، والتعليقات المكتوبة في وقت لاحق قد تكون أقل فائدة على المدى الطويل. صياغة التعليقات تبدأ التعليقات السطرية في بايثون بالعلامة # ومسافة بيضاء، وتستمر حتى نهاية السطر. بشكل عام، ستبدو التعليقات على النحو التالي: # هذا تعليق نظرًا لأنَّ التعليقات لا تُنفَّذ، فعند تشغيل البرنامج، لن ترى أي إشارة للتعليقات، فالتعليقات توضع في الشيفرة المصدرية ليقرأها الناس، وليس للتنفيذ. في برنامج "Hello, World!‎" قد يبدو التعليق كما يلي: # في سطر الأوامر “Hello, World!” طبع print("Hello, World!") في الحلقة for، قد تبدو التعليقات كما يلي: # كمصفوفة من السلاسل النصية sharks تعريف المتغير sharks = ['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem'] # sharks تمر على المصفوفة For حلقة for shark in sharks: print(shark) يجب أن تُحاذى التعليقات على نفس المسافة البادئة (indent) للشيفرة التي تعلّق عليها. بمعنى أنّ التعليقات على دالة ليس لها مسافة بادئة ستكون هي أيضًا بدون مسافة بادئة، وسيكون لكل مستوى من المسافات البادئة التالية تعليقات تتوافق مع الشيفرات البرمجية التي تعلِّق عليها. على سبيل المثال، الشيفرة التالية تعرّف الدالة again()‎ التي تسأل المستخدم إن كان يريد استخدام الحاسبة مجدَّدًا، مع بعض التعليقات: ... # لسؤال المستخدم إن كان يريد استخدام الحاسبة مجددا again() تعريف الدالة def again(): # أخذ المدخلات من المستخدم calc_again = input(''' Do you want to calculate again? Please type Y for YES or N for NO. ''') # calculate() فستُنفّذ الدالة Y إن أدخل المستخدم if calc_again == 'Y': calculate() # فقل وداعا للمستخدم وأنه البرنامج N إن كتب المستخدم elif calc_again == 'N': print('See you later.') # إن أدخل المستخدم حرفًا آخر، فأعد تنفيذ الدالة else: again() الهدف من التعليقات هو مساعدة المبرمج الأصلي، أو أيّ شخص آخر يستخدم مشروعه أو يتعاون معه، على فهمه. وإذا تعذّر صيانة التعليقات وتحديثها تحديثًا صحيحًا، وبالتوازي مع الشيفرة، فإنّ عدم تضمين التعليقات قد يكون أفضل من كتابة تعليق يتناقض مع الشيفرة. يجب أن تجيب التعليقات عن سؤال "لماذا" بدلًا من "ماذا" أو "كيف". لأنه ما لم تكن الشيفرة صعبة ومعقَّدة، فإن النّظر إلى الشيفرة عمومًا كافٍ لفهم ما الذي تفعله الشيفرة، أو كيف تفعله. التعليقات الكتلية يمكن استخدام التعليقات الكتلية (Block Comments) لتوضيح الشيفرات البرمجية المعقدة التي لا تتوقع أن يكون القارئ على دراية بها. تنطبق هذه التعليقات الطويلة على جزء من الشيفرة أو جميعها، كما توضع في نفس مستوى المسافة البادئة للشيفرة. في التعليقات الكتلية، يبدأ كل سطر بالعلامة # معقوبةً بمسافة بيضاء واحدة. إذا كنت بحاجة إلى استخدام أكثر من فقرة واحدة، فيجب فصلها بسطر يحتوي على علامة # واحدة. فيما يلي مثال على كتلة تعليقات تشرح ما يحدث في الدالة main()‎ المعرفة أدناه: # parser الوسائط عبر المتغير main سوف تحلل الدالة # الوسائط ستُحدَّد بواسطة المستخدم على سطر الأوامر. هذا سيمرر # الذي يريد المستخدم تحليله مع اسم الملف word الوسيط # المراد استخدامه، وكذلك تقديم نص مساعد إذا لم يُدخل المستخدم # الوسيط بشكل صحيح def main(): parser = argparse.ArgumentParser() parser.add_argument( "word", help="the word to be searched for in the text file." ) parser.add_argument( "filename", help="the path to the text file to be searched through" ) ... تُستخدَم التعليقات الكتلية عادةً عندما تكون الشيفرة غير واضحة، وتتطلب شرحًا شاملاً. يجب أن تتجنب الإفراط في التعليق على الشيفرة، ويجب أن تثق في قدرة المبرمجين الآخرين على فهم الشيفرة، إلا إذا كنت تكتب لجمهور معين. التعليقات السطرية توضع التعليقات السطرية (Inline comments) على نفس السطر الذي توجد فيه العبارة البرمجية. ومثل التعليقات الأخرى، فإنها تبدأ بالعلامة # ومسافة بيضاء واحدة. بشكل عام، تبدو التعليقات السطرية كما يلي: [code] # تعليق مضمن حول الشيفرة لا ينبغي الإكثار من استخدام التعليقات السطرية، ولكن عند استخدامها في محلها يمكن أن تكون فعالة لشرح الأجزاء الصعبة من الشيفرة. وقد تكون مفيدة أيضًا إن ظننت أنَّك قد لا تتذكر سطرًا من الشيفرة في المستقبل، أو إذا كنت تتعاون مع شخص قد لا يكون على دراية بجميع جوانب الشيفرة. على سبيل المثال، إذا لم يكن هناك توضيح مسبق، فقد لا تعلم أنت أو المتعاونون معك أنّ الشيفرة التالية تنشئ عددًا عقديًا، لذلك قد ترغب في إضافة تعليق مضمّن: z = 2.5 + 3j # إنشاء عدد عقدي يمكن أيضًا استخدام التعليقات السطرية لشرح السبب وراء فعل شيء ما، أو بعض المعلومات الإضافية، كما في المثال التالي: x = 8 # بقيمة عشوائية x ابتداء يجب استخدام التعليقات السطرية عند الضرورة وحسب، كما ينبغي أن توفر إرشادات مفيدة للشخص الذي يقرأ البرنامج. تعليق جزء من الشيفرة بدواعي الاختبار والتنقيح بالإضافة إلى استخدام التعليقات كوسيلة لتوثيق الشيفرة، يمكن أيضًا استخدام العلامة # لتعليق جزء من الشيفرة وتعطيله أثناء اختبار أو تنقيح البرنامج الذي تعمل عليه. أي عندما تواجه أخطاء بعد إضافة أسطر جديدة إلى الشيفرة، فقد ترغب في تعليق بعضها لمعرفة موضع الخلل. يمكن أن يتيح لك استخدام العلامة # تجربة بدائل أخرى أثناء إعداد الشيفرة. على سبيل المثال، قد تفاضل بين استخدام الحلقة while أو حلقة for أثناء برمجة لعبة، ويمكنك تعليق إحداهما بينما تختبر أيّهما أفضل: import random number = random.randint(1, 25) # number_of_guesses = 0 for i in range(5): # while number_of_guesses < 5: print('Guess a number between 1 and 25:') guess = input() guess = int(guess) # number_of_guesses = number_of_guesses + 1 if guess < number: print('Your guess is too low') if guess > number: print('Your guess is too high') if guess == number: break if guess == number: print('You guessed the number!') else: print('You did not guess the number. The number was ' + str(number)) يتيح لك تعليق الشيفرة البرمجية تجربة عدة طرق ومقاربات برمجية، بالإضافة إلى مساعدتك على العثور على مكمن الخطأ من خلال التعليق المنهجي لبعض أجزاء البرنامج. خلاصة سيساعدك استخدام التعليقات في برامج بايثون على جعل برامجك أكثر مقروئية، سواء لك أو لغيرك. التعليقات المناسبة وذات الصلة والمفيدة ستسهّل تعاون الآخرين معك في مشاريع البرمجة وتجعل شيفرتك أكثر قيمة. يمكنك تعلم المزيد عن التعليقات من موسوعة حسوب. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Write Comments in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم أنواع البيانات المقالة السابقة: كيفية استخدام سطر أوامر بايثون التفاعلي
  18. يوفر سطر أوامر بايثون التفاعلي (Python interactive console)، ويسمى أيضًا مترجم بايثون (Python interpreter) للمبرمجين طريقة سريعة لتنفيذ الأوامر، وتجربة أو اختبار التعليمات البرمجية دون الحاجة إلى إنشاء وكتابة أي شيفرة برمجية. يمكن الوصول من خلال سطر الأوامر التفاعلي إلى جميع دوال بايثون المُضمّنة، وجميع الوحدات المثبّتة، وتاريخ الأوامر، والإكمال التلقائي. ويوفر سطر الأوامر التفاعلي الفرصة لاستكشاف وتجربة شيفرات تعليمات بايثون، والقدرة على نسخ الشيفرة البرمجية ولصقها في ملف الشيفرة المصدرية عندما تصبح جاهزة أي بعد تجريبها والتأكد من عملها. ستتناول هذه المقالة كيفية العمل بسطر الأوامر التفاعلي لبايثون، وكيفية الاستفادة منه أثناء كتابة الشيفرة. فتح سطر الأوامر التفاعلي يمكن الوصول إلى سطر الأوامر التفاعلي من أيّ حاسوب محلي أو خادم مثبّت فيه بايثون. التعليمة التي ستستخدمها عمومًا للدخول إلى سطر الأوامر التفاعلي في الإصدار الافتراضي لبايثون هي: python إذا أعددت البيئة البرمجية وجهزتها وفق إرشادات الدرس السابق، فيمكنك إنشاء بيئة واستعمال إصدار بايثون والوحدات المُثبَّتة فيها عن طريق الدخول أولاً إلى تلك البيئة (إن لم تُهيِّئ البية الوهمية بعد، فعد إلى الدرس السابق وجهِّز البيئة الوهمية قبل تنفيذ الأوامر التالية): cd environments . my_env/bin/activate ثم اكتب الأمر python: (my_env) sammy@ubuntu:~/environments$ python في مثالنا الحالي، الإصدار الافتراضي هو Python 3.5.2، والذي يُعرَض في المخرجات بمجرد إدخال الأمر، إلى جانب إشعار حقوق الملكية، وبعض الأوامر التي يمكنك كتابتها للحصول على معلومات إضافية: Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> في بداية كل سطر ستجد ثلاث علامات "أكبر من" (<<<): >>> يمكنك استهداف إصدارات محددة من بايثون عن طريق إلحاق رقم الإصدار بالأمر، وبدون مسافات مثل: python2.7 Python 2.7.12 (default, Nov 19 2016, 06:48:10) [GCC 5.4.0 20160609] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> المخرجات تبيّن لنا أننا نستخدم الإصدار Python 2.7.12. إذا كان هذا هو الإصدار الافتراضي لبايثون 2، فيمكننا أيضًا الدخول إلى سطر الأوامر التفاعلي باستخدام الأمر python2. بالمقابل، يمكننا استدعاء إصدار بايثون 3 الافتراضي باستخدام الأمر التالي: python3 Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> يمكن أيضًا أن نفتح سطر الأوامر التفاعلي أعلاه باستخدام الأمر python3.5. بعد تشغيل سطر الأوامر التفاعلي لبايثون، يمكننا المضي قدمًا والبدء في العمل. العمل في سطر أوامر بايثون التفاعلي يقبل مترجم بايثون التفاعلي (Python interactive interpreter) قواعد لغة بايثون، والتي تضعها بعد البادئة <<<. يمكننا، على سبيل المثال، إنشاء متغير وإسناد قيمة له بالشكل التالي: >>> birth_year = 1868 بمجرد تعيين قيمة العدد الصحيح 1868 إلى المتغير birth_year، سنضغط على زر الإدخال ونحصل على سطر جديد يبدأ بثلاث علامات "أكبر من" (<<<): >>> birth_year = 1868 >>> يمكننا الاستمرار في تعيين المتغيرات، وإجراء الحسابات الرياضياتية: >>> birth_year = 1868 >>> death_year = 1921 >>> age_at_death = death_year - birth_year >>> print(age_at_death) 53 >>> كما نفعل في ملفات البرامج النصية، أنشأنا متغيرات جديدة أخرى وأسندنا قيمةً لها تناسب اسمها، ثم طرحنا قيمة متغيرٍ من آخر، وطلبنا من سطر الأوامر طباعة المتغير الذي يمثل الفرق عبر الدالة print()‎. يمكنك أيضًا استخدام سطر الأوامر التفاعلي كآلة حاسبة: >>> 203 / 20 10.15 >>> هنا، قسمنا العدد الصحيح 203 على 20، نحصل على الناتج 10.15. تعدد الأسطر عندما نكتب شيفرة متعددة الأسطر، سيستخدم المترجم أسطر الاستمرارية، وهي أسطر مسبوقة بثلاث نقاط (...). وللخروج من أسطر الاستمرارية، ستحتاج إلى الضغط على الزر ENTER مرتين. الشيفرة التالية تعيّن قيمتي متغيّرين، ثم تستخدم عبارة شرطية لتحديد ما يجب طباعته: >>> sammy = 'Sammy' >>> shark = 'Shark' >>> if len(sammy) > len(shark): ... print('Sammy codes in Java.') ... else: ... print('Sammy codes in Python.') ... Sammy codes in Python. >>> في هذه الحالة، طولا السلسلتين النصيتين متساويان، لذلك يتم تنفيذ العبارة else. لاحظ أنك ستحتاج إلى الحفاظ على مسافة بادئة بايثون (Python indenting) المؤلفة من أربعة مسافات بيضاء، وإلا سيُطلق خطأٌ: >>> if len(sammy) > len(shark): ... print('Sammy codes in Java.') File "<stdin>", line 2 print('Sammy codes in Java.') ^ IndentationError: expected an indented block >>> إضافة إلى تجربة التعليمات البرمجية متعددة الأسطر في سطر الأوامر، يمكنك أيضًا استيراد الوحدات. استيراد الوحدات يوفر لك مترجم بايثون طريقةً سريعةً للتحقق مما إذا كانت وحدات معيّنة متوفرة في بيئة البرمجة الحالية. يمكنك ذلك باستخدام العبارة import: >>> import matplotlib Traceback (most recent call last): File "<stdin>", line 1, in <module> ImportError: No module named 'matplotlib' في الحالة أعلاه، لم تكن الوحدة matplotlib متاحة في بيئة البرمجة الحالية. لتثبيت تلك الوحدة، ستحتاج إلى ترك المترجم التفاعلي، وتثبيتها باستخدام أداة إدارة الحزم pip مثل العادة: (my_env) sammy@ubuntu:~/environments$ pip install matplotlib Collecting matplotlib Downloading matplotlib-2.0.2-cp35-cp35m-manylinux1_x86_64.whl (14.6MB) ... Installing collected packages: pyparsing, cycler, python-dateutil, numpy, pytz, matplotlib Successfully installed cycler-0.10.0 matplotlib-2.0.2 numpy-1.13.0 pyparsing-2.2.0 python-dateutil-2.6.0 pytz-2017.2 بمجرد تثبيت الوحدة matplotlib هي وجميع تبعياتها بنجاح، يمكنك العودة إلى المترجم التفاعلي: (my_env) sammy@ubuntu:~/environments$ python في هذه المرحلة، لن تتلقى أيّ رسالة خطأ إن استوردت الوحدة، ويمكنك استخدام الوحدة المثبتة إما داخل سطر الأوامر، أو داخل ملف. الخروج من سطر أوامر بايثون التفاعلي هناك طريقتان رئيسيتان لترك سطر الأوامر التفاعلي: إما استخدام اختصار لوحة المفاتيح، أو استخدام دالة من دوال بايثون. اختصار لوحة المفاتيح هو CTRL+D في أنظمة *نيكس، أو CTRL+Z ثم CTRL في أنظمة ويندوز، وبذلك ستخرج من سطر الأوامر، ويعيدك إلى البيئة الطرفية الأصلية: ... >>> age_at_death = death_year - birth_year >>> print(age_at_death) 53 >>> sammy@ubuntu:~/environments$ بدلًا من ذلك، الدالة quit()‎ ستنهي سطر الأوامر التفاعلي، وتعيدك إلى بيئة المحطة الطرفية الأصلية التي كنت فيها سابقًا: >>> octopus = 'Ollie' >>> quit() sammy@PythonUbuntu:~/environments$ في حال استخدام الدالة quit()‎، فستُسجَّل في ملف التأريخ (history file)، بالمقابل لن يُسجّل اختصار لوحة المفاتيح CTRL+D ذلك: # /home/sammy/.python_history الملف ... age_at_death = death_year - birth_year print(age_at_death) octopus = 'Ollie' quit() يمكن إنهاء مترجم بايثون بكلا الطريقتين، فاختر ما يناسبك. الاطلاع على التأريخ من فوائد سطر الأوامر التفاعلي أنّ جميع أوامرك تؤرَّخ في الملف ‎.python_history في أنظمة *ينكس، بحيث يمكنك الاطلاع عليها في أيّ محرر نصي، مثل nano: nano ~/.python_history بمجرد فتحه باستخدام محرر نصوص، سيبدو ملف تأريخ بايثون الخاص بك على هذا النحو: # /home/sammy/.python_history الملف import pygame quit() if 10 > 5: print("hello, world") else: print("nope") sammy = 'Sammy' shark = 'Shark' ... بمجرد الانتهاء من ملفك، يمكنك الضغط على CTRL+X للخروج. من خلال تتبع الأحداث المُؤرَّخة في بايثون، يمكنك الرجوع إلى الأوامر والتجارب السابقة، ونسخ ولصق أو تعديل الشيفرة لاستخدامها في الملفات البرمجية أو في Jupyter Notebook. الخلاصة سطر الأوامر التفاعلي هو فضاءٌ لتجربة شيفرة بايثون، إذ يمكنك استخدامه كأداة للاختبار والتجريب وغير ذلك. لتنقيح (Debug) ملفات البرمجة في بايثون، يمكنك استخدام الوحدة code لفتح مترجم تفاعلي داخل ملف، وسنتحدث عن ذلك بالتفصيل في الدرس التالي: كيفية تنقيح بايثون باستخدام سطر الأوامر التفاعلي. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Work with the Python Interactive Console لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة اللاحقة: كيفية كتابة التعليقات في بايثون 3 المقالة السابقة: كيف تكتب أول برنامج لك في بايثون 3
  19. لدى بايثون عدِّة دوال مبنية فيها للتعامل مع السلاسل النصية. تسمح هذه الدوال لنا بتعديل وإجراء عمليات على السلاسل النصية بسهولة. يمكنك أن تتخيل الدوال على أنها «أفعال» يمكننا تنفيذها على عناصر موجودة في الشيفرة. الدوال المبنية في اللغة هي الدوال المُعرَّفة داخل لغة بايثون وهي جاهزة مباشرةً للاستخدام. سنشرح في هذا الدرس مختلف الدوال التي نستطيع استخدامها للتعامل مع السلاسل النصية في بايثون 3. جعل السلاسل النصية بأحرف كبيرة أو صغيرة الدالتان str.upper()‎ و str.lower()‎ ستُعيدان السلسلة النصية بعد تحويل حالة جميع أحرفها الأصلية إلى الأحرف الكبيرة أو الصغيرة (على التوالي وبالترتيب). ولعدم قدرتنا على تعديل السلسلة النصية بعد إنشائها، فستُعاد سلسلةٌ نصيةٌ جديدةٌ. لن تُعدَّل أيّة محارف غير لاتينية في السلسلة النصية الأصلية وستبقى على حالها. لنحوِّل السلسلة النصية Sammy Shark إلى أحرفٍ كبيرة: ss = "Sammy Shark" print(ss.upper()) الناتج: SAMMY SHARK لنحوِّلها الآن إلى أحرفٍ صغيرة: print(ss.lower()) وسينتج: sammy shark ستُسهِّل الدالتان str.upper()‎ و str.lower()‎ عملية التحقق من مساواة سلسلتين نصيتين لبعضهما أو لمقارنتهما وذلك عبر توحيد حالة الأحرف. فلو كتب المستخدم اسمه بأحرفٍ صغيرةٍ فسنستطيع أن نتأكد إن كان مُسجَّلًا في قاعدة البيانات بمقارنته بعد تحويل حالة أحرفه. الدوال المنطقية تتوفر في بايثون عدِّة دوال التي ستتحقق من القيم المنطقية (Boolean). هذه الدوال مفيدةٌ عند إنشائنا للنماذج التي يجب على المستخدمين ملأها؛ فمثلًا، إذا سألنا المستخدم عن الرمز البريدي وأردنا أن نقبل السلاسل النصية التي تحتوي أرقامًا فقط، أو عندما نسأله عن اسمه فسنقبل سلسلةً نصيةً تحتوي حروفًا فقط. هنالك عددٌ من الدوال التي تُعيد قيمًا منطقيةً: str.isalnum()‎: تُعيد true إذا احتوت السلسلة النصية على أرقام وأحرف فقط (دون رموز). str.isalpha()‎: تُعيد true إذا احتوت السلسلة النصية على أحرف فقط (دون أرقام أو رموز). str.islower()‎: تُعيد true إذا كانت جميع أحرف السلسلة النصية صغيرة. str.isnumeric()‎: تُعيد true إذا احتوت السلسلة النصية على أرقام فقط. str.isspace()‎: تُعيد true إذا لم تحتوي السلسلة النصية إلا على الفراغات. str.istitle()‎: تُعيد true إذا كانت حالة أحرف السلسلة النصية كما لو أنها عنوان (أي أنَّ أوّل حرف من كل كلمة كبير، والبقية صغيرة). str.isupper()‎: تُعيد true إذا كانت جميع أحرف السلسلة النصية كبيرة. لننظر إلى بعضها عمليًا: number = "5" letters = "abcdef" print(number.isnumeric()) print(letters.isnumeric()) الناتج: True False استخدام الدالة str.isnumeric()‎ على السلسلة النصية 5 سيُعيد القيمة True، بينما استخدام نفس الدالة على السلسلة النصية abcdef سيُعيد False. وبشكلٍ مماثل، يمكننا معرفة إن كانت حالة الأحرف في سلسلةٍ نصيةٍ كما لو أنها عنوان، أو أنها كبيرة أو صغيرة. لنُنشِئ بدايةً بعض السلاسل النصية: movie = "2001: A SAMMY ODYSSEY" book = "A Thousand Splendid Sharks" poem = "sammy lived in a pretty how town" لنجرّب الدوال المنطقية لمعرفة الناتج (سنعرض كل دالتين وناتجهما تحتهما): print(movie.islower()) print(movie.isupper()) False True print(book.istitle()) print(book.isupper()) True False print(poem.istitle()) print(poem.islower()) False True ستساعدنا معرفة إن كانت أحرف السلسلة النصية بحالة صغيرة أو كبيرة أو كأنها عنوان في تصنيف البيانات تصنيفًا سليمًا، وتوفِّر لنا الفرصة لتوحيد طريقة تخزين البيانات بالتحقق من حالة أحرفها ثم تعديلها وفقًا لذلك. الدوال المنطقية التي تعمل على السلاسل النصية مفيدةٌ أيضًا عندما نريد التحقق إن حقَّقَت مدخلات المستخدم شروطًا معيّنة. الدوال join()‎ و split()‎ و replace()‎ توفِّر الدوال str.join()‎ و str.split()‎ و str.replace()‎ إمكانياتٍ إضافيةً لتعديل السلاسل النصية في بايثون. الدالة str.join()‎ تجمع سلسلتين نصيتين مع بعضهما، لكنها تفعل ذلك بتمرير إحداها إلى الأخرى. لنُنشِئ سلسلةً نصيةً: balloon = "Sammy has a balloon." لنستخدم الآن الدالة str.join()‎ لإضافة فراغات إلى تلك السلسلة النصية كالآتي: " ".join(balloon) إذا طبعنا الناتج: print(" ".join(balloon)) فسنجد أنَّ السلسلة النصية الجديدة هي السلسلة الأولى لكن بين كل حرفين فراغ: S a m m y h a s a b a l l o o n . يمكننا أيضًا استخدام الدالة str.join()‎ لإنشاء مقلوب سلسلة نصية: print("".join(reversed(balloon))) .noollab a sah ymmaS لم نرغب في إضافة أيّة سلسلة نصية إلى أخرى، لذا أبقينا على السلسلة النصية فارغةً دون محتوى داخلها. الدالة str.join()‎ مفيدةٌ أيضًا لجمع قائمة (list) من السلاسل النصية وإخراجها إلى سلسلةٍ وحيدة. لنُنشِئ سلسلة نصية يُفصَل بين كلماتها بفاصلة من القائمة الآتية: print(",".join(["sharks", "crustaceans", "plankton"])) sharks,crustaceans,plankton إذا أردتَ وضع فاصلة ثم فراغ بين القيم في المثال السابق، فيمكنك أن تُعيد كتابة التعبير البرمجي السابق لإضافة فراغ بعد الفاصلة كما يلي: ", ".join(["sharks", "crustaceans", "plankton"]). وكما نستطيع جمع السلاسل النصية مع بعضها بعضًا، نستطيع أيضًا تجزئتها، وذلك عبر الدالة str.split()‎: print(balloon.split()) ['Sammy', 'has', 'a', 'balloon.'] الدالة str.split()‎ ستُعيد قائمة (list) تحتوي سلاسل نصية كانت مفصولةً بالفراغات في السلسلة النصية الأصلية إذا لم يُمرَّر معاملٌ لتحديد محرف الفصل. يمكنك أيضًا استخدام الدالة str.split()‎ لحذف أجزاء معيّنة من السلسلة النصية الأصلية، فلنحاول مثلًا حذف الحرف a: print(balloon.split("a")) ['S', 'mmy h', 's ', ' b', 'lloon.'] حُذِفَ الحرف a من السلسلة النصية وأصبح الناتج مقسومًا عند كل ورود للحرف a مع الإبقاء على الفراغات. تأخذ الدالة str.replace()‎ سلسلةً نصيةً وتُعيد نسخةً محدَّثةً منها بعد إجراء بعض عمليات الاستبدال عليها. لنفترض أنَّ البالون الذي يملكه سامي قد ضاع، ولعدم امتلاك سامي للبالون في الوقت الراهن، فسنُبدِّل الكلمة "has" إلى "had": print(balloon.replace("has","had")) أوّل سلسلة نصية داخل أقواس الدالة replace()‎ هي السلسلة النصية التي نريد استبدالها، والسلسلة النصية الثانية هي السلسلة التي نريد وضعها بدلًا من الأولى. ناتج تنفيذ السطر السابق هو: Sammy had a balloon. استخدام دوال تعديل السلاسل النصية مثل str.join()‎ و str.split()‎ و str.replace سيمنحك تحكمًا كبيرًا بمعالجة السلاسل النصية في بايثون. الخلاصة لقد تعلمنا في هذا الدرس بعض الدوال المُضمَّنة في لغة بايثون لمعالجة النصوص والتعامل معها ومعرفة بعض خصائصها. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال An Introduction to String Methods in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقال التالي: آلية فهرسة السلاسل النصية وطريقة تقسيمها المقال السابق: كيفية تنسيق النصوص
  20. تتألف السلاسل النصية عادةً من النص المكتوب، وهنالك عدِّة حالات نحتاج فيها إلى تحكمٍ أكبر بكيفية إظهار النص وجعلها أسهل قراءةً للبشر عبر وضع علامات الترقيم والسطور الجديدة والمحاذاة. سنشرح في هذا الدرس كيفية التعامل مع السلاسل النصية في بايثون لكي يظهر النص الناتج بتنسيقٍ صحيح. القيم الحرفية لنفرِّق أولًا بين القيم الحرفية للسلاسل النصية (string literal) والسلاسل النصية نفسها (string value)، فالقيم الحرفية هي ما نراه في الشيفرة المصدرية للبرنامج، بما في ذلك علامتَي الاقتباس. أما السلسلة النصية نفسها فهي ما نراها عندما نستدعي الدالة print()‎ عند تشغيل البرنامج. ففي برنامج «Hello, World!‎» التقليدي، تكون القيمة الحرفية هي "Hello, World!‎" بينما السلسلة النصية هي Hello, World!‎ دون علامتَي الاقتباس. أي أنَّ السلسلة النصية هي ما نراه في نافذة الطرفية عندما نُشغِّل برنامج بايثون. لكن بعض السلاسل النصية قد تحتوي على علامات اقتباس، مثل اقتباسنا لمقولةٍ ما. ولأنَّ القيم الحرفية والقيم الفعلية للسلاسل النصية غير متساوية، فمن الضروري في أغلب الحالات إضافة تنسيق إلى القيم الحرفية لعرض السلاسل النصية كما ينبغي. علامات الاقتباس بسبب إمكانيتنا استخدام علامات الاقتباس المفردة أو المزدوجة في بايثون، فمن السهل تضمين الاقتباسات بوضعها بين علامتَي اقتباس مزدوجتين في سلسلةٍ نصيةٍ محاطةٍ بعلامتَي اقتباس مفردتين كما في السلسلة الآتية: 'Sammy says, "Hello!"' أو يمكننا استخدام علامة اقتباس فردية (أو كما يسمونها «فاصلة عليا» [apostrophe]) في سلسلةٍ نصيةٍ محاطةٍ بعلامتَي اقتباس مزدوجتين: "Sammy's balloon is red." إذًا، يمكننا التحكم بطريقة عرض علامات الاقتباس والفواصل العليا في سلاسلنا النصية عبر استخدام النوع الصحيح من علامات الاقتباس لإحاطة كامل السلسلة النصية. كتابة النص على أكثر من سطر طباعة السلاسل النصية على أكثر من سطر ستجعل منها واضحةً وسهلة القراءة. إذ يمكن تجميع النصوص المكتوبة بعدِّة أسطر لزيادة وضوحها، أو لتنسيقها كرسالة، أو للحفاظ على تعدد الأسطر في الأشعار. نستخدم ثلاث علامات اقتباس فردية ''' أو ثلاث علامات اقتباس مزدوجة """ للإحاطة بالسلسلة النصية التي تمتد على أكثر من سطر: ''' This string is on multiple lines within three single quotes on either side. ''' """ This string is on multiple lines within three double quotes on either side. """ يمكنك الآن طباعة السلاسل النصية في عدِّة أسطر لجعل النصوص سهلة القراءة –خصوصًا الطويلة منها– وذلك عبر استخدام ثلاث علامات اقتباس متتالية. «تهريب» المحارف طريقة أخرى لتنسيق السلاسل النصية هي استخدام «محرف التهريب» (escape character). فجميع عمليات تهريب المحارف تبدأ بالخط المائل الخلفي (backslash، أي \) متبوعًا بمحرفٍ آخر الذي له معنى خاص يفيد في تنسيق السلسلة النصية. هذه قائمة بأكثر محارف التهريب شيوعًا: \: سطرٌ جديدٌ في سلسلةٍ نصيةٍ متألفةٍ من عدِّة أسطر. \\: طباعة رمز الخط المائل الخلفي. ‎\'‎: طباعة علامة اقتباس فردية. ‎\"‎: طباعة علامة اقتباس مزدوجة. ‎\‎n‎: طباعة محرف الانتقال إلى سطرٍ جديد. ‎\t: طباعة محرف الجدولة (Tab). لنستخدم محرف التهريب لإضافة علامات الاقتباس إلى سلسلتنا النصية السابقة، لكن هذه المرة سنُحيط السلسلة النصية بعلامتَي اقتباس مزدوجتين: print("Sammy says, \"Hello!\"") Sammy says, "Hello!" تمكننا عبر محرف التهريب ‎\"‎ من استخدام علامات الاقتباس المزدوجة للإحاطة بالسلسلة النصية التي تحتوي على نصٍ مقتبسٍ ومحاطٍ بعلامتَي اقتباس مزدوجتين. نستطيع أيضًا استخدام محرف التهريب ‎\'‎ لإضافة علامة اقتباس مفردة ضمن السلسلة النصية المحاطة بعلامتَي اقتباس مفردتين: print('Sammy\'s balloon is red.') Sammy's balloon is red. ولأننا نستخدم الآن محرف التهريب فنستطيع وضع علامات الاقتباس المفردة حتى لو كانت السلسلة النصية كلها موجودة بين علامتَي اقتباس مفردتين. عندما نستخدم علامات الاقتباس الثلاثية –كما فعلنا أعلاه– فسنجد فراغًا في أعلى وأسفل النص عند طباعته. نستطيع حذف تلك الفراغات عبر استخدام محرف التهريب \ في بداية ونهاية السلسلة النصية مع الإبقاء على النص مقروءًا بسهولة في الشيفرة. """\ This multi-line string has no space at the top or the bottom when it prints.\ """ وبشكلٍ شبيهٍ بما سبق، يمكننا استخدام محرف التهريب ‎\n لوضع أسطر جديدة دون الحاجة إلى الضغط على زر Enter أو Return: print("This string\nspans multiple\nlines.") This string spans multiple lines. يمكننا الدمج بين محارف التهريب، إذ سنطبع في المثال الآتي سلسلةً نصيةً على أكثر من سطر، ونستعمل فيها مسافة جدولة (tab) بين الترقيم ومحتوى السطر: print("1.\tShark\n2.\tShrimp\n10.\tSquid") 1. Shark 2. Shrimp 10. Squid علامة الجدولة الأفقية التي وضعناها عبر محرف التهريب ‎\t ستؤدي إلى محاذاة الكتابة في العمود النصي الثاني في المثال أعلاه، مما يجعل قراءتها سهلةً جدًا. وصحيحٌ أنَّ محرف التهريب ‎\n يعمل عملًا جيدًا في النصوص القصير، لكن لا نُغفِل أهمية أن تكون الشيفرة المصدرية مقروءةً بسهولةٍ أيضًا. فلو كان النص طويلًا، فأرى أنَّ من الأفضل استخدام علامات الاقتباس الثلاثية. رأينا أنَّ محارف التهريب تُستعمَل لإضافة تنسيق إلى السلاسل التي كان من الصعب (أو حتى المستحيل) عرضها عرضًا سليمًا دونها. فهل تستطيع مثلًا أن تطبع السلسلة النصية الآتية دون استخدام محارف التهريب Sammy says, "The balloon's color is red.‎"‎؟ السلاسل النصية «الخام» ماذا لو أردنا تجاهل كل محارف التنسيق الخاصة في سلاسلنا النصية؟ فلربما أردنا مقارنة أو التحقق من صحة بعض الشيفرات الحاسوبية التي تستخدم الخط المائل الخلفي، ولا نريد من بايثون تفسيره على أنها محرف تهريب. أتت «السلاسل النصية الخام» (raw strings) في بايثون لتحل هذه المشكلة، وتتجاهل جميع محارف التنسيق داخل سلسلة نصية، بما في ذلك محارف التهريب. يمكننا إنشاء سلسلة نصية خام بوضع الحرف r في بداية السلسلة النصية، قبل علامة الاقتباس الأولى مباشرةً: print(r"Sammy says,\"The balloon\'s color is red.\"") Sammy says,\"The balloon\'s color is red.\" سنستطيع الإبقاء على محارف التهريب كما هي في السلاسل النصية إن أسبقناها بالحرف r لتحويلها إلى سلاسل نصية خام. الخلاصة شرحنا في هذا الدرس عدِّة طرائق لتنسيق النص في بايثون 3؛ وعرفنا كيف نُظهِر السلاسل النصية كما نريد عبر استخدامنا لمحارف التهريب أو السلاسل النصية الخام، لكي يستفيد المستخدم من النص الناتج ويقرأه بسهولة. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Format Text in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقال التالي: مقدمة إلى دوال التعامل مع السلاسل النصية المقال السابق: مدخل إلى التعامل مع السلاسل النصية
  21. «السلسلة النصية» (string) هي مجموعة من المحارف (أي الأحرف والأرقام والرموز) التي إما أن تكون قيمة ثابتة أو قيمة لمتغير. وهذه السلاسل النصية مُشكَّلة من محارف يونيكود (Unicode) والتي لا يمكن تغيير مدلولها. ولأنَّ النص هو شكلٌ شائعٌ من أشكال البيانات الذي نستعمله يوميًا، لذا فإنَّ السلاسل النصية مهمة جدًا وتُمثِّل لُبنةً أساسيةً في البرمجة. سيستعرض هذا الدرس كيفية إنشاء وطباعة السلاسة النصية، وكيفية جمعها مع بعضها وتكرارها، وآلية تخزين السلاسل النصية في متغيرات. إنشاء وطباعة السلاسل النصية تتواجد السلاسل النصية إما داخل علامات اقتباس فردية ’ أو علامات اقتباس مزدوجة "، لذا لإنشاء سلسلة نصية، كل ما علينا فعله هو وضع مجموعة من المحارف بين أحد نوعَي علامات الاقتباس السابقَين: 'هذه سلسلة نصية ضمن علامتي اقتباس مفردتين.' "هذه سلسلة نصية ضمن علامتي اقتباس مزدوجتين" يمكنك الاختيار بين النوعَين السابقَين، لكن أيًّا كان اختيارك، فعليك أن تحافظ على استخدامك له في كامل برنامجك. يمكنك طباعة السلاسل النصية إلى الشاشة باستدعاء الدالة print()‎ بكل بساطة: print("Let's print out this string.") Let's print out this string. بعد أن فهمتَ كيفية تهيئة السلاسل النصية في بايثون، لنلقِ نظرةً الآن إلى كيفية التعامل مع السلاسل النصية في برامجك وتعديلها. جمع السلاسل النصية عملية الجمع (concatenation) تعني إضافة سلسلتين نصيتين إلى بعضهما بعضًا لإنشاء سلسلة نصية جديدة. نستخدم المعامل + لجمع السلاسل النصية؛ أبقِ في ذهنك أنَّ المعامل + يعني عملية الجمع عند التعامل مع الأعداد، أما عندما نستخدمه مع السلاسل النصية فيعني إضافتها إلى بعضها. لنجمع السلستين النصيتين "Sammy" و "Shark" مع بعضها ثم نطبعهما باستخدام الدالة print()‎: print("Sammy" + "Shark") SammyShark إذا أردتَ وضع فراغ بين السلسلتين النصيتين، فيمكنك بكل بساطة وضعه عند نهاية السلسلة النصية الأولى، أي بعد الكلمة “Sammy”: print("Sammy " + "Shark") Sammy Shark لكن احرص على عدم استعمال المعامل + بين نوعَين مختلفَين من البيانات، فلن نتمكن من جمع السلاسل النصية والأرقام مع بعضها، فلو حاولنا مثلًا أن نكتب: print("Sammy" + 27) فسنحصل على رسالة الخطأ الآتية: TypeError: Can't convert 'int' object to str implicitly أما إذا أردنا أن نُنشِئ السلسلة النصية "Sammy27" فعلينا حينها وضع الرقم 27 بين علامتَي اقتباس ("27") مما يجعله سلسلةً نصيةً وليست عددًا صحيحًا. سنستفيد من تحويل الأعداد إلى سلاسل نصية عندما نتعامل مع أرقام الهواتف على سبيل المثال، لأننا لن نحتاج إلى إجراء عملية حسابية على رمز الدولة ورمز المنطقة في أرقام الهواتف، إلا أننا نريدهما أن يظهرا متتابعَين. عندما نجمع سلسلتين نصيتين أو أكثر فنحن نُنشِئ سلسلةً نصيةً جديدةً التي يمكننا استخدامها في برنامجنا. تكرار السلاسل النصية هنالك أوقاتٌ نحتاج فيها إلى استخدام بايثون لأتمتة المهام، وإحدى الأمور التي يمكننا أتمتتها هي تكرار سلسلة نصية لعدِّة مرات. إذ نستطيع فعل ذلك عبر المعامل *، وكما هو الأمر مع المعامل + فإنَّ المعامل * له استخدامٌ مختلف عندما نتعامل مع أرقام، حيث يُمثِّل عملية الضرب. أما عندما نستخدمه بين سلسلةٍ نصيةٍ ورقمٍ فإنَّ المعامل * هو معامل التكرار، فوظيفته هي تكرار سلسلة نصية لأي عدد مرات تشاء. لنحاول طباعة السلسلة النصية “Sammy” تسع مرات دون تكرارها يدويًا، وذلك عبر المعامل *: print("Sammy" * 9) المخرجات: SammySammySammySammySammySammySammySammySammy يمكننا بهذه الطريقة تكرار السلسلة النصية لأيِّ عددٍ نشاء من المرات. تخزين السلاسل النصية في متغيرات المتغيرات هي «رموز» التي يمكننا استعمالها لتخزين البيانات في برنامج. يمكنك تخيل المتغيرات على أنها صندوقٌ فارغٌ يمكنك ملؤه بالبيانات أو القيم. السلاسل النصية هي نوعٌ من أنواع البيانات، لذا يمكننا استعمالها لملء المتغيرات. التصريح عن السلاسل النصية كمتغيرات سيُسهِّل علينا التعامل معها في برامجنا. لتخزين سلسلة نصية داخل متغير، فكل ما علينا فعله هو إسنادها إليه. سنُصرِّح في المثال الآتي عن المتغير my_str: my_str = "Sammy likes declaring strings." أصبح المتغير my_str الآن مُشيرًا إلى سلسلةٍ نصيةٍ، والتي أمسى بمقدورنا طباعتها كما يلي: print(my_str) وسنحصل على الناتج الآتي: Sammy likes declaring strings. استخدام المتغيرات لاحتواء قيم السلاسل النصية سيساعدنا في الاستغناء عن إعادة كتابة السلسلة النصية في كل مرة نحتاج استخدامها، مما يُبسِّط تعاملنا معها وإجراءنا للعمليات عليها في برامجنا. الخلاصة لقد تعلمنا في درسنا هذا أساسيات التعامل مع السلاسل النصية في لغة بايثون 3. بما في ذلك إنشاءها وطباعتها وجمعها وتكرارها، إضافةً إلى تخزينها في متغيرات، وهذه هي المعلومات الأساسية التي عليك فهمها للانطلاق في تعاملك مع السلاسل النصية في برامج بايثون 3. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال An Introduction to Working with Strings in Python 3 لصاحبته -Lisa Tagliaferri اقرأ أيضًا المقالة التالي: كيفية تنسيق النصوص المقال السابق: فهم أنواع البيانات
  22. كتابة برنامج يطبع العبارة "مرحبا بالعالم!‎" وتنفيذه هو أحد التقاليد الأساسية في مجال البرمجة، ويشكل أول برنامج بسيط وكامل للمبتدئين، وكذلك يُعدُّ اختبارًا لأنظمة وبيئات البرمجة، كما يعطي البرنامج فكرة عن الصياغة الأساسية للغات البرمجة. ستتعلم في هذه المقالة كيفية كتابة برنامج "مرحبا بالعالم!" في بايثون 3. المتطلبات الأساسية يجب أن يكون لديك بايثون 3 مثبتًا، بالإضافة إلى إعداد بيئة برمجة محلية على حاسوبك. إن لم تكن قد ثبَّت بايثون وأعددت البيئة البرمجة، فعد إلى الدرس السابق واتبع الخطوات اللازمة لإنجاز ذلك قبل إكمال هذا الدرس. مرحلة كتابة البرنامج لكتابة البرنامج "مرحبا بالعالم!‎"، سننشئ ملفًا جديدًا باسم hello.py، ثم نفتحه بمحرر نصوص لسطر الأوامر، (مثل nano الموجود على أنظمة لينكس): nano hello.py إن لم يكن لديك المُحرِّر nano، فأنشئ الملف hello.py وافتحه باستعمال أي محرِّر موجود على نظام التشغيل لديك (مثل المفكرة على أنظمة ويندوز). بمجرد فتح الملف النصي في نافذة الطرفية (أو محرِّر النصوص)، سنقوم بكتابة برنامجنا فيه وذلك بكتابة التعليمة البرمجية التالية: print("مرحبا بالعالم!‎") دعنا نشرّح هذه التعليمة. print()‎ هي دالة (function) تخبر الحاسوب بتنفيذ إجراء ما. نعرف أنَّها دالة لأنها تستخدم الأقواس. تطلب print()‎ من بايثون أن يعرض أو يخرج ما نضعه بين القوسين. بشكل افتراضي، ستُعرَض المُخرجات في نافذة الطرفية عند تنفيذ البرنامج. بعض الدوال، مثل print()‎، هي دوال مُدمجة (built-in) في بايثون بشكل افتراضي. هذه الدوال المدمجة متوفرة لنا دائمًا لاستخدامها في برامجنا. يمكننا أيضًا تعريف دوالنا الخاصة وبناءها من عناصر أخرى. داخل قوسي الدالة print()‎ توجد سلسلة من الأحرف - مرحبا بالعالم!‎‎ - محاطة بعلامتي اقتباس. وهذه الأحرف الموضوعة بين علامات الاقتباس تُسمى سلاسل نصية (strings) وهي أحد أنواع البيانات التي سنتعرف عليها لاحقًا. بعد الانتهاء من كتابة البرنامج، يمكنك الخروج من nano عن طريق الضغط على ctrl+x، وعندما يُطلب منك حفظ الملف، اضغط على y. بعد الخروج من المُحرِّر nano، ستعود إلى نافذة الطرفية. مرحلة تنفيذ البرنامج بعد الانتهاء من كتابة برنامج "مرحبا بالعالم!‎"، فنحن جاهزون لتنفيذه. سنستخدم الأمر python3 معقوبًا باسم ملف البرنامج: python3 hello.py سيعرض برنامج hello.py الذي أنشأته للتو المخرجات التالية على نافدة الطرفية: مرحبا بالعالم!‎ دعني أشرح لك ما فعله البرنامج بمزيد من التفصيل. في الشيفرة البرمجية، مررنا السلسلة النصية مرحبا بالعالم!‎‎ إلى الدالة print()‎ التي وظيفتها طباعة ما يُمرَّر إليها على مجرى الخرج (نافذة الطرفية في حالتنا هذه). في هذا المثال، السلسلة النصية مرحبا بالعالم!‎‎ تُسمى أيضًا وسيطًا (argument)، نظرًا لأنها قيمة مُمرّرة إلى دالة. علامتا الاقتباس اللتان تحيطان بالسلسلة النصية مرحبا بالعالم!‎‎ لن تُطبعا على الشاشة لأنهما تُستخدمان لإعلام بايثون بأنّهما تحتويان على سلسلة نصية. تُحدِّد علامتا الاقتباس مُبتدأ السلسلة النصية ومنتهاها. بعد تنفيذ البرنامج، يمكنك الآن التأكد من أنّك نجحت في تثبيت بايثون 3، وأنّ البرنامج مكتوب ومُصَاغ صياغةً صحيحة. الخلاصة تهانينا! لقد أتممت كتابة أول برنامج لك، برنامج "مرحبا بالعالم!‎"، في بايثون 3. من الآن وصاعدًا، يمكنك استخدام الدالة print()‎ لعرض أية عبارات نصية أو قيم أخرى، ويمكنك أيضًا إنشاء ملفات برامج جديدة وتنفيذها بالطريقة ذاتها. هذه المقالة جزء من سلسلة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Write Your First Python 3 Program لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة اللاحقة: كيفية استخدام سطر أوامر بايثون التفاعلي المقالة السابقة: كيفية تثبيت بايثون 3 وإعداد بيئتها البرمجية
  23. بعد أن أخذت فكرة عامة عن لغة البرمجة بايثون وتعرف على تاريخها والفرق بين أهم إصدارين لها، الإصدار 2 و الإصدار 3 في الدرس السابق، ستتعلم في هذا الدرس كيفية تثبيت بايثون على نظام تشغيلك وإعداد البيئة البرمجية اللازمة لكتابة البرامج وتنفيذها خلال رحلتك التعليمية هذه. فهرس هذا الدرس -لسهولة الانتقال إلى نظام التشغيل الذي تريده- هو: كيفية تثبيت بايثون 3 وإعداد بيئة برمجية على أوبنتو 16.04 كيفية تثبيت بايثون 3 وإعداد بيئة برمجية على أوبنتو 18.04 كيفية تثبيت بايثون 3 وإعداد بيئة برمجية على ديبيان 8 كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على CentOS 7 كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على macOS كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على ويندوز 10 الأمور التي سنسلط الضوء عليها هي: تثبيت بايثون 3 على نظام تشغيلك ثم إعداد بيئته البرمجية. تتمثل عملية تهيئة البيئة البرمجية بإعداد بيئة وهمية تمكِّنك من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه يملك مجموعة من الاعتماديات (dependencies) والتي لن تؤثِّر على غيرها من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. بعد تثبيت بايثون وإكمال إعداد البيئة الوهمية، سنعلمك كيفية إنشاء برنامجٍ بسيطٍ يعرض العبارة «Hello World!‎» (أهلًا بالعالم!) الشهيرة، وبهذا سنتحقق من عمل البيئة عملًا صحيحًا، وستصبح آنذاك طريقة إنشاء برامج بايثون وتنفيذها مألوفةً لديك مما يمهد الطريق لكتابة وتنفيذ مشاريع بايثون اللاحقة. اختر مما يلي الدرس الخاص بنظام تشغيل حاسوبك (حاولنا شمل أشهر أنظمة التشغيل، لينكس وويندوز وماك) وانتقل إليه لاتباع الخطوات اللازمة لتنفيذ ما سبق. كيفية تثبيت بايثون 3 وإعداد بيئة برمجية في أوبنتو 16.04 أوبنتو هي إحدى أشهر توزيعات نظام التشغيل لينكس. تأتي أنظمة لينكس غالبًا محملةً بنسخة بايثون مثبتة وجاهزة للعمل. مع ذلك، لا يكون الإصدار المُثبَّت مطابق للإصدار الذي نريده في بعض الأحيان. سيأخذ هذا الدرس بيدك لتعليمك كيفية تثبيت الإصدار 3 من بايثون على أوبنتو 16.04 مع ضبط بيئته البرمجية. سيشرح لك خطوةً بخطوة عملية تثبيت بايثون 3 على جهازك المحلي وضبط البيئة البرمجية عبر سطر الأوامر. صحيح أن هذه الخطوات مخصصة للإصدار 16.04 من أوبنتو، إلا أنه يمكن الاستفادة منها في التوزيعات الأخرى المعتمدة على ديبيان. كيفية تثبيت بايثون 3 وإعداد بيئة برمجية على أوبنتو 18.04 أوبنتو هي إحدى أشهر توزيعات نظام التشغيل لينكس والذي يحوي نسخة بايثون مثبَّتةً وجاهزةً للعمل. مع ذلك، لا يكون الإصدار المُثبَّت مطابقًا للإصدار الذي نريده في بعض الأحيان. سيرشدك هذا الدرس لكيفية تثبيت الإصدار 3 من بايثون على أوبنتو 18.04 مع ضبط بيئته البرمجية. سيشرح لك خطوةً بخطوة عملية تثبيت بايثون 3 على جهازك المحلي وضبط البيئة البرمجية عبر سطر الأوامر. صحيح أن هذه الخطوات مخصصة للإصدار 18.04 من أوبنتو، إلا أنه يمكن الاستفادة منها في التوزيعات الأخرى المعتمدة على ديبيان. كيفية تثبيت بايثون 3 وإعداد بيئة برمجية على ديبيان 8 ديبيان هي إحدى أشهر توزيعات نظام التشغيل لينكس أيضًا. تكون بايثون مثبتة في معظم أنظمة التشغيل لينكس ولكن لا يكون الإصدار المُثبَّت مطابقًا للإصدار الذي نريده في بعض الأحيان. سيرشدك هذا المقال خطوةً بخطوة لتثبيت بايثون 3 على جهازك المحلي ذي نظام التشغيل ديبيان 8 وضبط البيئة البرمجية عبر سطر الأوامر. صحيح أن هذه الخطوات مخصصة للإصدار 8 من ديبيان، إلا أنه يمكن الاستفادة منها في التوزيعات الأخرى المعتمدة على ديبيان. كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على CentOS 7 CentOS هي إحدى توزيعات نظام التشغيل لينكس أيضًا. تأتي أنظمة لينكس غالبًا محملةً بنسخة بايثون مثبتة وجاهزة للعمل. مع ذلك، لا يكون الإصدار المثبت مطابق للإصدار الذي نريده. سيأخذ هذا الدرس بيدك لتعليمك كيفية تثبيت الإصدار 3 من بايثون على CentOS 7 مع ضبط بيئته البرمجية واختبارها عبر سطر الأوامر. كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على macOS إن كان نظام تشغيلك هو macOS، فهذا الدرس هو لك. ستتلعم فيه خطوةً بخطوة كيفية تثبيت بايثون 3 على macOS، وتثبيت بيئتها البرمجية عبر سطر الأوامر، ولا تقلق إن لم يكن لديك أدنى فكرة عن استعمال سطر الأوامر. بدايةً، يشرح المقال كيفية تثبيت Xcode -هي بيئة تطوير متكاملة (IDE)- ثم تثبيت وإعداد Homebrew استعدادًا لتثبيت بايثون 3. ينتقل بعدها إلى إعداد البيئة الوهمية وإنشاء وتنفيذ برنامج بسيط (أشرنا إليه في آنفًا). كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على ويندوز 10 إن كنت من مستخدمي نظام التشغيل الشهير ويندوز، فقد أتيت إلى الدرس الصحيح. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى تثبيت بايثون 3 في ويندوز 10، وتهيئة بيئته البرمجية عبر سطر الأوامر. الخطوة الأولى لإنجاز ذلك هي فتح وإعداد PowerShell -برنامج من ميكروسوفت يوفر واجهة سطر الأوامر- ثم تثبيت مدير الحزم Chocolatey وذلك من أجل تثبيت بايثون 3. يُعرِّج بعدها على إعداد البيئة الوهمية وإنشاء برنامج بسيط وتنفيذه (أشرنا إليه في آنفًا). اقرأ أيضًا الدرس التالي: الدرس السابق: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3
  24. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (scripting) والأتمتة وتحليل البيانات وتعلم الآلة (machine learning) والتطوير الخلفي (back-end development). ظهرت بايثون سنة 1991، واستوحي اسمها من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وبسيطة الإعداد، وجعل طريقة كتابتها مباشرة، مع توفير تقرير مباشر عند حدوث أخطاء. وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعدُّ مستقبل بايثون. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 في macOS، وتثبيت بيئة برمجة عبر سطر الأوامر. المتطلبات المسبقة لمتابعة هذه المقالة، يجب أن تملك جهازًا عليه نظام macOS متصل بالشبكة مع صلاحيات مدير (administrative access). إذا لم تكن لك خبرة في التعامل مع بيئة النافذة الطرفية، فيمكنك مطالعة المقالة "مدخل إلى طرفيّة لينكس Linux Terminal". الخطوة الأولى: فتح نافذة الطرفية سنجري معظم أطوار التثبيت والإعدادات عبر سطر الأوامر، والذي هو طريقةٌ غيرُ رسوميةٍ للتعامل مع الحاسوب، فبدلًا من الضغط على الأزرار، ستكتب نصًّا وتعطيه للحاسوب لينفذه، وسيُظهِر لك ناتجًا نصيًا أيضًا. يمكن أن يساعدك سطر الأوامر على تعديل أو أتمتة مختلف المهام التي تنجزها على الحاسوب يوميًا، وهو أداةٌ أساسيةٌ لمطوري البرمجيات. طرفية ماك (macOS Terminal) هي تطبيق يمكنك استخدامه للدخول إلى واجهة سطر الأوامر. مثل التطبيقات الأخرى، ستجد تطبيق الطرفية بالذهاب إلى Finder، وفتح المجلد Applications، ثم الذهاب إلى المجلد Utilities، ثم النقر المزدوج على Terminal لفتحه. أو يمكنك استخدام Spotlight عبر الضغط على الزرّين command و spacebar للعثور على Terminal بكتابته في المربع الذي سيظهر. هنالك الكثير من الأوامر التي عليك تعلمها لكي تتمكن من الاستفادة منه. هنالك مقالات في أكاديمية حسوب (كدرس مدخل إلى طرفيّة لينكس Linux Terminal) ستعلمك أساسيات سطر الأوامر، وهنالك كتاب «سطر أوامر لينكس» الذي يُعتَبر مرجعًا لطريقة التعامل مع سطر الأوامر في لينكس، والذي يشبه نظيره في ماك. الخطوة الثانية: تثبيت Xcode Xcode هي بيئة تطوير متكاملة (IDE) تتألف من أدوات تطوير البرامج لنظام التشغيل MacOS. قد يكون Xcode مثبتًا عندك سلفًا. للتحقق من ذلك، اكتب في نافذة الطرفية ما يلي: xcode-select -p إن حصلت على المخرجات التالية، فهذا يعني أنّ مثبت Xcode: /Library/Developer/CommandLineTools إن تلقيت خطأ، فتثّبت Xcode من المتجر App Store واعتمد الخيارات الافتراضية. بعد تثبيت Xcode، ارجع إلى النافذة الطرفية. ثم ثبّت التطبيق Command Line Tools عن طريق كتابة: xcode-select --install عند هذه المرحلة، يكون قد تم تثبيت Xcode، والتطبيق Command Line Tools الخاص به، ونحن الآن مستعدون لتثبيت مدير الحزم Homebrew. الخطوة الثالثة: تثبيت وإعداد Homebrew في حين أنّ طرفية OS X تتمتع بالكثير من وظائف طرفية لينكس وأنظمة يونيكس الأخرى، إلا أنها لا تأتي بمدير حزم جيد. مدير الحزم (package manager) هو مجموعة من أدوات البرمجيات التي تعمل على أتمتة عمليات التثبيت، بما في ذلك التثبيت الأولي للبرامج، وترقيتها، وإعدادها، وإزالتها عند الحاجة. تحفظ هذه الأدوات التثبيتات في موقع مركزي، ويمكنها صيانة جميع حزم البرامج على النظام وفق تنسيقات (formats) معروفة. توفر Homebrew لنظام التشغيل OS X نظام إدارة حزم مجاني ومفتوح المصدر يبسط عملية تثبيت البرنامج. لتثبيت Homebrew، اكتب في نافذة الطرفية ما يلي: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" تم تطوير Homebrew عبر روبي، لذلك سيعدّل مسار روبي على جهازك. يسحب الأمر curl السكربت من عنوان URL المحدد. سيوضح ذلك السكربت ما سيفعله، ثم يوقف العملية ليطلب منك التأكيد. يوفر لك هذا الكثير من الملاحظات حول ما سيفعله السكربت في نظامك، ويمنحك الفرصة للتحقق من العملية. لاحظ أنك عند إدخال كلمة المرور فلن تعرض الطرفية المحارف التي تكتبها، ولكنها ستُسجّل، بعد إدخال كلمة المرور اضغط على الزر return. واضغط على الحرف y إن طُلِب منك تأكيد التثبيت. لنلق نظرة على الرايات (flags) المرتبطة بالأمر curl: تخبر الرايتان ‎-f أو ‎--fail الطرفية بعدم إعطاء مخرجات على هيئة مستند HTML عند حدوث أخطاء في الخادم. تُصمِت الرايتان ‎-s أو ‎--silent الأمر curl، بمعنى أنه لن يعرض معلومات التقدم، وعند جمعها مع الرايتين ‎-S أو ‎--show-error، ستجعل curl تُظهر رسالة خطأ في حال الفشل. تطلب الرايتان ‎-L أو ‎--location من curl إعادة الطلبية (request) إلى مكان جديد إذا أبلغ الخادم بأنّ الصفحة المطلوبة قد نُقِلت إلى موقع أخر. بمجرد اكتمال عملية التثبيت، سنضع مجلد Homebrew في أعلى متغير البيئة PATH. سيضمن ذلك أن يتم استدعاء عمليات تثبيت Homebrew عبر الأدوات التي قد يختارها نظام التشغيل Mac OS X تلقائيًا، والتي قد تتعارض مع بيئة التطوير التي تنشئها. يجب عليك إنشاء أو فتح الملف ‎~/.bash_profile باستخدام محرر نصوص سطر الأوامر nano باستخدام الأمر nano: nano ~/.bash_profile بعد فتح الملف في نافذة الطرفية، اكتب ما يلي: export PATH=/usr/local/bin:$PATH لحفظ التغييرات، اضغط على المفتاح control والحرف o بالتزامن، وعند مطالبتك بالتأكيد، اضغط على المفتاح return. يمكنك الآن الخروج من nano عن طريق الضغط على المفتاح control والحرف x بالتزامن. لتفعيل هذه التغييرات، اكتب في نافذة الطرفية: source ~/.bash_profile ستصير الآن التغييرات التي أجريتها على متغير البيئة PATH فعالة. يمكننا التحقق من أنّ Homebrew قد ثُبِّت بنجاح عن طريق كتابة: brew doctor إذا لم تكن هناك حاجة إلى أي تحديثات في هذا الوقت، فستطبع الطرفية ما يلي: Your system is ready to brew. خلاف ذلك، قد تحصل على تنبيه يدعوك إلى تنفيذ أمر آخر مثل brew update للتأكد من أنّ Homebrew محدّث. بمجرد أن تصبح Homebrew جاهزة، يمكنك تثبيت بايثون 3. المرحلة الرابعة: تثبيت بايثون 3 يمكنك استخدام Homebrew للبحث عن البرامج التي يمكنك تثبيتها عبر الأمر brew search، ويمكنك الحصول على قائمة الحزم والوحدات ذات العلاقة ببايثون فقط عبر كتابة: brew search python نافذة الطرفية ستخرج قائمة من الحزم والوحدات التي يمكنك تثبيتها على النحو التالي: app-engine-python micropython python3 boost-python python wxpython gst-python python-markdown zpython homebrew/apache/mod_python homebrew/versions/gst-python010 homebrew/python/python-dbus Caskroom/cask/kk7ds-python-runtime homebrew/python/vpython Caskroom/cask/mysql-connector-python سيكون بايثون 3 (python3) من بين العناصر المدرجة في القائمة. لذلك دعنا نثبّتها: brew install python3 ستعرض لك نافذة الطرفية ملاحظات بشأن عملية تثبيت بايثون 3، وقد يستغرق الأمر بضع دقائق قبل اكتمال التثبيت. إلى جانب بايثون 3، ستثبّت Homebrew الأدوات pip و setuptools و wheel. سنستخدم pip، وهي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تعلم المزيد عن الوحدات والحزم التي يمكنك تثبيتها بالأداة pip بقراءة المقالة كيفية استيراد الوحدات في بايثون 3 من هذه السلسلة. يمكن تثبيت حزم بايثون بكتابة ما يلي: pip3 install package_name عليك وضع اسم الحزمة أو المكتبة التابعة لبايثون مكان package_name مثل Django لتطوير الويب، أو NumPy لإجراء الحسابات العلمية. لذا، إن شئتَ تنزيل NumPy فيمكنك تنفيذ الأمر pip3 install numpy. تسهّل الأداة setuptools تحزيم مشاريع بايثون، أما wheel فهي تنسيق حُزم (built-package format) لبايثون يمكنه تسريع إنتاجية البرامج عن طريق تقليل عدد المرات التي تحتاج فيها إلى التصريف. بعد إكمال العملية، يمكننا التحقق من إصدار بايثون 3 المُثبّت في النظام بكتابة: python3 --version ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون المثبّت. والذي سيكون افتراضيًا أحدث إصدار مستقر ومتاح من بايثون 3. لتحديث إصدار بايثون 3، يمكنك أولاً تحديث Homebrew، ثم تحديث بايثون: brew update brew upgrade python3 من الممارسات الجيدة تحديث إصدار بايثون الذي تعمل به من حين لآخر. الخطوة الخامسة: إعداد بيئة افتراضية الآن بعد تثبيت Xcode و Homebrew وبايثون، يمكننا المضي قدمًا لإنشاء بيئة البرمجة خاصتنا. تُمكِّنك البيئات الافتراضية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه ستكون له اعتماديّاته (dependencies) الخاصة به، والتي لن تؤثِّر على غيره من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون، وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. يمكنك ضبط أيّ عددٍ تشاء من البيئات الافتراضية، وكل بيئة ستكون ممثلة بمجلد في حاسوبك يحتوي على عدد من السكربتات. اختر المجلد الذي تريد أن تضع فيه بيئات بايثون، أو يمكنك إنشاء مجلد جديد باستخدام الأمر mkdir كما يلي: mkdir environments cd environments بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، تستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر التالي: python3.6 -m venv my_env سيُنشِئ هذا الأمر مجلدًا جديدًا (في هذه الحالة يُسمى my_env) فيه بعض الملفات: يشير الملف pyvenv.cfg إلى توزيعة بايثون التي استخدمتها لتنفيذ الأمر. يحتوي المجلد الفرعي lib نسخة من إصدار بايثون، ويحتوي على مجلد يسمى site-packages، والذي سيكون فارغًا في البداية، ولكنه سيُستخدم لتخزين وحدات الطرف الثالث التي ستثبّتها. المجلد الفرعي include يُصرِّف (packages) الحزم. يحتوي المجلد الفرعي bin نسخة من رُقامة بايثون (Python binary) جنبًا إلى جنب مع سكربت التفعيل (activate shell script) الذي سيُستخدم تعمل هذه الملفات مع بعضها لضمان أنَ تكون مشاريعك معزولةٌ عن سياق الآلة المحلية، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى الحزمٍ التي يحتاجها. عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر التالي الذي سيُنفِّذ سكربت التفعيل: source my_env/bin/activate يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها my_env، وهذا يعني أننا لن سنستخدم إلا إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة. ملاحظة: يمكنك داخل البيئة الافتراضية أن تستخدم الأمر python بدلًا من python3 والأمر pip بدلًا من pip3 إن شئتَ. أما إذا كنتَ تستخدم بايثون 3 خارج البيئة الافتراضية، فيجب عليك حينها استخدام python3 و pip3 حصرًا. لأنّ python وpip ستستدعيان إصدارًا قديمًا من بايثون. يجب أن تكون بيئتك الافتراضية جاهزةً للاستخدام بعد اتباعك للخطوات السابقة. الخطوة الثالثة: إنشاء برنامج بسيط بعد أن أكملنا ضبط بيئتنا الافتراضية، لننشِئ برنامجًا بسيطًا يعرض العبارة «مرحبا بالعالم!»، وبهذا سنتحقق من أنَّ البيئة تعمل بالشكل الصحيح، ولكي تتعوّد على إنشاء برامج بايثون إن كنتَ وافدًا جديدًا على اللغة. علينا أولًا تشغيل محرر ملفات نصية لإنشاء ملف جديد، وليكن المحرر nano الذي يعمل من سطر الأوامر: (my_env) sammys-MBP:~ sammy$ nano hello.py بعد فتح الملف في نافذة الطرفية، سنكتب البرنامج الخاص بنا: print("مرحبا بالعالم!") أغلق محرر nano بالضغط على Ctrl+x ثم اضغط على y عندما يسألك عن حفظ الملف. بعد أن يُغلَق المحرر nano وتعود إلى سطر الأوامر، حاول تنفيذ البرنامج: (my_env) sammys-MBP:~ sammy$ python hello.py سيؤدي برنامج hello.py الذي أنشأتَه إلى طباعة الناتج التالي في الطرفية: مرحبا بالعالم! للخروج من البيئة، اكتب الأمر deactivate وستعود إلى مجلدك الأصلي. الخلاصة تهانينا! لقد ضبطتَ الآن بيئة تطويرٍ للغة بايثون 3 في نظام Mac OS X، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق. ترجمة -وبتصرّف- للمقال How To Install Python 3 and Set Up a Local Programming Environment on macOS لصاحبته Lisa Tagliaferri
  25. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (scripting) والأتمتة وتحليل البيانات وتعلم الآلة (machine learning) والتطوير الخلفي (back-end development). ظهرت بايثون سنة 1991، واستوحي اسمها من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وبسيطة الإعداد، وجعل طريقة كتابتها مباشرة، مع توفير تقرير مباشر عند حدوث أخطاء. وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعدُّ مستقبل بايثون. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 على لينيكس، وتثبيت بيئة برمجة عبر سطر الأوامر. صحيحٌ أنَّ هذا الدرس يشرح عملية التثبيت في دبيان 8، إلا أنَّ المفاهيم الأساسية فيه تنطبق على جميع توزيعات دبيان لينيكس (Debian Linux). المتطلبات المسبقة لمتابعة هذه المقالة، يجب أن تملك صلاحيات مستخدم غير جذري (non-root user ) مع امتيازات sudo على توزيعة دبيان 8، أو توزيعة أخرى من دبيان لينيكس (Debian Linux). إذا لم تكن لك خبرة في التعامل مع بيئة النافذة الطرفية، فيمكنك مطالعة المقالة "مدخل إلى طرفيّة لينكس Linux Terminal". الخطوة الأولى: إعداد بايثون 3 سنُثبِّت ونضبط بايثون عبر سطر الأوامر، والذي هو طريقةٌ غيرُ رسوميةٍ للتعامل مع الحاسوب، فبدلًا من الضغط على الأزرار، ستكتب نصًّا وتعطيه للحاسوب لينفذه، وسيُظهِر لك ناتجًا نصيًا أيضًا. يمكن أن يساعدك سطر الأوامر على تعديل أو أتمتة مختلف المهام التي تنجزها على الحاسوب يوميًا، وهو أداةٌ أساسيةٌ لمطوري البرمجيات، وهنالك الكثير من الأوامر التي عليك تعلمها لكي تتمكن من الاستفادة منه. هنالك مقالات في أكاديمية حسوب (كدرس مدخل إلى طرفيّة لينكس Linux Terminal) ستعلمك أساسيات سطر الأوامر، وهنالك كتاب «سطر أوامر لينكس» الذي يُعتَبر مرجعًا لطريقة التعامل مع سطر الأوامر. ستجد تطبيق «Terminal» (البرنامج الذي تستعمله للوصول إلى سطر الأوامر) بفتح القائمة في الزاوية السفلى اليسرى من الشاشة ثم كتابة «terminal» في شريط البحث، ثم الضغط على أيقونة التطبيق التي ستظهر بعدئذٍ. أو يمكنك أن تضغط على Ctrl+Alt+T في لوحة المفاتيح بنفس الوقت لتشغيل تطبيق الطرفية Terminal. في دبيان 8 والإصدارات الأخرى من دبيان لينكس، ستجد كلًا من بايثون 3 وبايثون 2 مثبتين مسبقًا. للتأكد من أنّ إصدارات بايثون حديثة، سنحدّث النظام ونرقّيه باستخدام الأمر apt-get: sudo apt-get update sudo apt-get -y upgrade الخيار ‎-y يعني أنَّك توافق على تثبيت جميع الحزم القابلة للتحديث، لكن قد تحتاج إلى تأكيد ذلك عند تحديث النظام وذلك اعتمادًا على الحزم التي ستُحدَّث، ونسخة لينكس. بعد إكمال العملية، يمكننا التحقق من إصدار بايثون 3 المُثبّت في النظام بكتابة: python3 -V ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون المثبّت. قد يختلف الرقم بناءً على النسخة المثبتة في توزيعتك، لكن يجب أن يكون شبيهًا بما يلي: Python 3.5.2 لإدارة الحزم البرمجية الخاصة ببايثون، سنثبّت pip، وهي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تعلم المزيد عن الوحدات والحزم التي يمكنك تثبيتها بالأداة pip بقراءة المقالة كيفية استيراد الوحدات في بايثون 3 من هذه السلسلة: sudo apt-get install -y python3-pip يمكن تثبيت حزم بايثون بكتابة ما يلي: pip3 install package_name حيث عليك وضع اسم الحزمة أو المكتبة التابعة لبايثون مكان package_name مثل Django لتطوير الويب، أو NumPy لإجراء الحسابات العلمية. لذا، إن شئتَ تنزيل NumPy فيمكنك تنفيذ الأمر pip3 install numpy. هناك عدة حزم وأدوات تطوير أخرى يجب تثبيتها للتأكد من أنّ بيئة البرمجة جاهزة: sudo apt-get install build-essential libssl-dev libffi-dev python-dev بعد أن انتهينا من ضبط بايثون وتثبيت pip، يمكننا الآن إنشاء «بيئة افتراضية» (virtual environment) لمشاريعنا. الخطوة الثانية: إعداد بيئة افتراضية تُمكِّنك البيئات الافتراضية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه ستكون له اعتماديّاته (dependencies) الخاصة به، والتي لن تؤثِّر على غيره من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون، وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. يمكنك ضبط أيُّ عددٍ تشاء من البيئات الافتراضية، وكل بيئة ستكون ممثلة بمجلد في حاسوبك يحتوي على عدد من السكربتات. هناك عدة طرق لإعداد بيئة برمجية في بايثون، لكننا سنستخدم وحدة (module) برمجية باسم venv، وهي جزءٌ من مكتبة بايثون 3 القياسية. سنثبّت venv على نظامنا بكتابة: sudo apt-get install -y python3-venv بعد إتمام التثبيت، فنحن جاهزون لإنشاء البيئات الافتراضية، يمكننا الآن إما اختيار مجلد نضع فيه بيئات بايثون، أو إنشاء مجلد جديد باستخدام الأمر mkdir كما يلي: mkdir environments cd environments بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، تستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر الآتي: python3.6 -m venv my_env سيُنشِئ الأمر pyvenv مجلدًا جديدًا فيه بعض الملفات التي يمكن عرضها باستخدام الأمر ls: ls my_env ستظهر لك مخرجات شبيهة بالمخرجات التالية: bin include lib lib64 pyvenv.cfg share تعمل هذه الملفات مع بعضها لضمان أنَ تكون مشاريعك معزولةٌ عن سياق الآلة المحلية، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى الحزمٍ التي يحتاجها. تتوافر أيضًا Python Wheels، والتي هي صيغة بناء حزمٍ (built-package format) لبايثون، والتي يمكن أن تُسرِّع من تطوير البرامج بتقليل عدد المرات التي تحتاج فيها إلى تصريف (compile) المشروع، وهي موجودةٌ في كل المجلدات المُسمّاة lib. عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر التالي الذي سيُنفِّذ سكربت التفعيل: source my_env/bin/activate يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها my_env، وقد يكون مظهر المِحَث مختلفًا في توزيعة دبيان، وذلك اعتمادًا على الإصدار المستخدم؛ لكن يجب أن تشاهد اسم البيئة بين قوسين في بداية السطر: (my_env) sammy@sammy:~/environments$ ستسمح لك السابقة بمعرفة أنَّ البيئة my_env مفعلة حاليًا، وهذا يعني أننا سنستخدم إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة. ملاحظة: يمكنك داخل البيئة الافتراضية أن تستخدم الأمر python بدلًا من python3 والأمر pip بدلًا من pip3 إن شئتَ. أما إذا كنتَ تستخدم بايثون 3 خارج البيئة الافتراضية، فيجب عليك حينها استخدام python3 و pip3 حصرًا. يجب أن تكون بيئتك الافتراضية جاهزةً للاستخدام بعد اتباعك للخطوات السابقة. الخطوة الثالثة: إنشاء برنامج بسيط بعد أن أكملنا ضبط بيئتنا الافتراضية، لننشِئ برنامجًا بسيطًا يعرض العبارة «مرحبا بالعالم!»، وبهذا سنتحقق من أنَّ البيئة تعمل بالشكل الصحيح، ولكي تتعوّد على إنشاء برامج بايثون إن كنتَ وافدًا جديدًا على اللغة. علينا أولًا تشغيل محرر ملفات نصية لإنشاء ملف جديد، وليكن المحرر nano الذي يعمل من سطر الأوامر: (my_env) sammy@sammy:~/environments$ nano hello.py بعد فتح الملف في نافذة الطرفية، سنكتب البرنامج الخاص بنا: print("مرحبا بالعالم!") أغلق محرر nano بالضغط على Ctrl+x ثم اضغط على y عندما يسألك عن حفظ الملف. بعد أن يُغلَق المحرر nano وتعود إلى سطر الأوامر، حاول تنفيذ البرنامج: (my_env) sammy@sammy:~/environments$ python hello.py سيؤدي برنامج hello.py الذي أنشأتَه إلى طباعة الناتج التالي في الطرفية: مرحبا بالعالم! للخروج من البيئة، اكتب الأمر deactivate وستعود إلى مجلدك الأصلي. الخلاصة تهانينا! لقد ضبطتَ الآن بيئة تطويرٍ للغة بايثون 3 في نظام لينكس دبيان، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق. ترجمة -وبتصرّف- للمقال How To Install Python 3 and Set Up a Local Programming Environment on Debian 8 لصاحبته Lisa Tagliaferri