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



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

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

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

نوع المُحتوى


التصنيفات

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

التصنيفات

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

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 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

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

  1. طُوِّرَت بايثون في أواخر الثمانينات، وأُطلقَت لأول مرة عام 1991. استُوحي اسمها من المجموعة الكوميدية البريطانية Monty Python، تُعدُّ بايثون خليفة للغة البرمجة ABC متعددة الأغراض. تضمنت بايثون في إصداراتها الأولى معالجة الاستثناءات، والدوال، والأصناف والوراثة. 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; } سيرشدك هذا الدرس إلى أفضل آليات وممارسات ترحيل الشيفرات من بايثون 2 إلى بايثون 3، وما إن كان عليك جعل الشيفرة متوافقة مع كلا الإصدارين. خلفية عامة صدر الإصدار 2 من بايثون عام 2000، ليُدشِّن حقبةً جديدةً من التطوير تقوم على الشفافية والشمولية، إذ شمل هذا الإصدار العديد من الميزات البرمجية، واستمر في إضافة المزيد طوال مدة تطويره. يُعد إصدار بايثون 3 مستقبل بايثون، وهو إصدار اللغة قيد التطوير حاليًا، فجاء في أواخر عام 2008، ليعالج العديد من عيوب التصميم الداخلية ويُعدِّلها. بيْد أنَّ اعتماد بايثون 3 كان بطيئًا بسبب عدم توافقه مع بايثون 2. في خضم ذلك، جاء الإصدار بايثون 2.7 في عام 2010 ليكون آخر إصدارات بايثون ‎2.x وليُسِّهل على مستخدمي بايثون ‎2.x الانتقال إلى بايثون 3 من خلال توفير قدر من التوافق بين الاثنتين، فهذا هو الهدف الأساسي من إطلاقه. يمكنك معرفة المزيد حول إصدارات بايثون والاختيار من بينها من المقالة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3. ابدأ ببايثون 2.7 للانتقال إلى بايثون 3، أو لدعم بايثون 2 وبايثون 3 معًا، يجب عليك التأكد من أنّ شيفرة بايثون 2 متوافقة تمامًا مع بايثون 2.7. يعمل العديد من المطورين حصريًا بشيفرات بايثون 2.7، أمَّا المبرمجون الذي يعملون بشيفرات أقدم، فعليهم أن يتأكدوا من أنّ الشيفرة تعمل جيدًا مع بايثون 2.7، وتتوافق معه. التأكُّد من توافق الشيفرة مع بايثون 2.7 أمرٌ بالغ الأهمية لأنه الإصدار الوحيد من بايثون 2 الذي ما يزال قيد الصيانة، وتُصحَّحُ ثغراته. فإذا كنت تعمل بإصدار سابق من بايثون 2، فستجد نفسك تتعامل مع مشكلات في شيفرة لم تعد مدعومة، ولم تعد ثغراتها تُصحَّح. هناك أيضًا بعض الأدوات التي تسِّهل ترحيل الشيفرة، مثل الحزمة Pylint التي تبحث عن الأخطاء البرمجية، لكن لا تدعمها إصدارات بايثون السابقة للإصدار 2.7. من المهم أن تضع في حسبانك أنَّه رغم أنَّ بايثون 2.7 ما زالت قيد الدعم والصيانة في الوقت الحالي، إلا أنَّها ستموت في النهاية. ستجد في PEP 373 تفاصيل الجدول الزمني لإصدار بايثون 2.7، وفي وقت كتابة هذا المقال، فإنّ أجل بايثون 2.7 حُدِّد في عام 2020 (يحتمل أن تكون قد ماتت وأنت تقرأ هذه السطور :-| ). الاختبار اختبار الشيفرة جزءٌ أساسيٌّ من عملية ترحيل شيفرة بايثون 2 إلى بايثون 3. فإذا كنت تعمل على أكثر من إصدار واحد من بايثون، فعليك أيضًا التحقُّق من أنَّ أدوات الاختبار التي تستخدمها تغطي جميع الإصدارات للتأكُّد من أنَّها تعمل كما هو متوقع. يمكنك إضافة حالات بايثون التفاعلية (interactive Python cases) إلى السلاسل النصية التوثيقية (docstrings) الخاصة بكافة الدوال والتوابع والأصناف والوحدات، ثم استخدام الوحدة doctest المضمنة للتحقق من أنها تعمل كما هو موضح، إذ يعدُّ ذلك جزءًا من عملية الاختبار. إلى جانب doctest، يمكنك استخدام الحزمة package.py لتتبع وحدة الاختبار. ستراقب هذه الأداة برنامجك وتحدد الأجزاء التي تُنفِّذها من الشيفرة، والأجزاء التي يمكن تنفيذها ولكن لم تُنفَّذ. يمكن أن تطبع Cover.py تقارير في سطر الأوامر، أو تنتج مستند HTML. تُستخدم عادةً لقياس فعالية الاختبارات، إذ توضح الأجزاء من الشيفرة التي اختُبِرت، والأجزاء التي لم تُختبَر. تَذكَّر أنه ليس عليك اختبار كل شيء، لكن تأكَّد من تغطية أيّ شيفرة غامضة أو غير عادية. للحصول على أفضل النتائج، يُنصح أن تشمل التغطية 80٪ من الشيفرة. تعرف على الاختلافات بين بايثون 2 و بايثون 3 سيمكّنك التعرّف على الاختلافات بين بايثون 2 و بايثون 3 من استخدام الميزات الجديدة المتاحة، أو التي ستكون متاحة في بايثون 3. تتطرق مقالتنا حول "اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3" إلى بعض الاختلافات الرئيسية بين الإصدارين. يمكنك أيضًا مراجعة توثيق بايثون الرسمي لمزيد من التفاصيل. عند البدء في ترحيل الشيفرة، فهناك بعض التغييرات في الصياغة عليك تنفيذها فوريًا. print حلت الدالة print()‎‎ في بايثون 3 مكان التعليمة print في بايثون 2: بايثون 2 بايثون 3 "مرحبا بالعالم!" print ("مرحبا بالعالم!")print exec تغيَّرت التعليمة exec في بايثون 2 وأصبحت دالةً تسمح بمتغيرات محلية (locals) وعامة (globals) صريحة في بايثون 3: بايثون 2 بايثون 3 exec code exec(code)‎ exec code in globals exec(code, globals)‎ exec code in (globals, locals)‎ exec(code, globals, locals)‎ / و // تُجرِي بايثون 2 القسمة التقريبية (floor division) بالعامل / ، بينما تخصص بايثون 3 العامل // لإجراء القسمة التقريبية: بايثون 2 بايثون 3 ‎5 / 2 = 2‎ ‎5 / 2 = 2.5‎ ‎5 // 2 = 2‎ لاستخدام هذين المعاملين في بايثون 2، استورد division من الوحدة __future__: from __future__ import division اقرأ المزيد عن قسمة الأعداد الصحيحة من المقالة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3. raise في بايثون 3، يتطلب إطلاق الاستثناءات ذات الوسائط استخدام الأقواس، كما لا يمكن استخدام السلاسل النصية كاستثناءات: بايثون 2 بايثون 3 raise Exception, args raise Exception raise Exception(args)‎ raise Exception, args, traceback raise Exception(args).with_traceback(traceback)‎ raise "Error"‎ raise Exception("Error")‎ except في بايثون 2، كان من الصعب إدراج الاستثناءات المُتعدِّدة، لكن ذلك تغيَّر في بايثون 3. لاحظ أنَّ as تُستخدَم صراحةً مع except في بايثون 3: بايثون 2 بايثون 3 except Exception, variable:‎ except AnException as variable:‎ except (OneException, TwoException) as variable:‎ def في بايثون 2، يمكن للدوال أن تقبل سلاسل مثل الصفوف أو القوائم. أمَّا في بايثون 3، فقد أزيل هذا الأمر. بايثون 2 بايثون 3 def function(arg1, (x, y)):‎ def function(arg1, x_y): x, y = x_y expr لم تعد صياغة علامة الاقتباس المائلة `` في بايثون 2 صالحة، واستخدم بدلًا عنها repr()‎أوstr.format()‎` في بايثون 3. بايثون 2 بايثون 3 `x = `355/113`` `x = repr(355/113):` تنسيق السلاسل النصية (String Formatting) لقد تغيرت صياغة تنسيق السلاسل النصية من بايثون 2 إلى بايثون 3. بايثون 2 بايثون 3 `"%d %s" % (i, s)` `"{} {}".format(i, s)` `"%d/%d=%f" % (355, 113, 355/113)` `"{:d}/{:d}={:f}".format(355, 113, 355/113)` تعلم كيفية استخدام تنسيقات السلاسل النصية في بايثون 3 من مقالة كيفية استخدام آلية تنسيق السلاسل النصية في بايثون 3. class ليست هناك حاجة لتمرير object في بايثون 3. بايثون 2 class MyClass(object): pass بايثون 3 class MyClass: pass في بايثون 3، تُضبَط الأصناف العليا (metaclasses) بالكلمة مفتاحية metaclass. بايثون 2: class MyClass: __metaclass__ = MyMeta class MyClass(MyBase): __metaclass__ = MyMeta بايثون 3: class MyClass(metaclass=type): pass class MyClass(MyBase, metaclass=MyMeta): pass تحديث الشيفرة هناك أدَاتان رئيّسيتان لتَحديث الشيفرة تلقائيًا إلى بايثون 3 مع الحفاظ على توافقيّتها مع بايثون 2 وهما: future و modernize. تختلف آليَتا عمل هاتين الأداتين، إذ تحاول future نقل أفضل ممارسات بايثون 3 إلى بايثون 2، في حين أنّ modernize تسعى إلى إنشاء شيفرات موحدة لبايثون تتوافق مع 2 و 3 وتستخدم الوحدة six لتحسين التوافقية. يمكن أن تساعدك هاتان الأداتان في إعادة كتابة الشيفرة وتحديد ورصد المشاكل المحتملة وتصحيحها. يمكنك تشغيل الأداة عبر مجموعة unittest لفحص الشيفرة والتحقق منها بصريًا، والتأكد من أنّ المراجعات التلقائية التي أُجريَت دقيقة. وبمجرد انتهاء الاختبارات، يمكنك تحويل الشيفرة. بعد هذا، ستحتاج على الأرجح إلى إجراء مراجعة يدوية، وخاصة استهداف الاختلافات بين بايثون 2 و 3 المذكورة في القسم أعلاه. إن أردت استخدام future، فعليك إضافة عبارة الاستيراد التالية في جميع وحدات بايثون 2.7: from __future__ import print_function, division, absolute_imports, unicode_literals رغم أن هذا لن يعفيك من إعادة كتابة الشيفرة، إلا أنه سيضمن لك أن تتماشى شيفرة بايثون 2 مع صياغة بايثون 3. أخيرًا، يمكنك استخدام الحزمة pylint لتحديد ورصد أي مشكلات محتملة أخرى في الشيفرة. تحتوي هذه الحزمة على مئات القواعد التي تغطي مجموعة واسعة من المشكلات التي قد تطرأ، بما فيها قواعد الدليل PEP 8، بالإضافة إلى أخطاء الاستخدام. قد تجد أنّ بعض أجزاء شيفرتك تربك pylint وأدوات الترحيل التلقائي الأخرى. حاول تبسيطها، أو استخدم unittest. التكامل المستمر (Continuous Integration) إذا أردت أن تجعل شفرتك متوافقة مع عدة إصدارات من بايثون، فستحتاج إلى تشغيل الإطار unittest باستمرار وفق مبدأ التكامل المستمر (وليس يدويًا)، أي أن تفعل ذلك أكبر عدد ممكن من المرات أثناء عملية التطوير. إذا كنت تستخدم الحزمة six لصيانة التوافقية بين بايثون 2 و 3، فستحتاج إلى استخدام عدة بيئات عمل لأجل الاختبار. إحدى حزم إدارة البيئة التي قد تكون مفيدة لك هي الحزمة tox، إذ ستفحص تثبيتات الحزمة مع مختلف إصدارات بايثون، وإجراء الاختبارات في كل بيئة من بيئات عملك، كما يمكن أن تكون بمثابة واجهة عمل للتكامل المستمر. خلاصة من المهم أن تعلم أنه مع ازدياد تركيز المطورين على بايثون 3، فستصبح اللغة أكثر دقةً وتماشيًا مع احتياجات المبرمجين، وسيضعف دعم بايثون 2.7. إذا قرَّرت أن تجعل شيفرتك متوافقة مع كل من بايثون 2 و بايثون 3، فقد تواجه صعوبة في ذلك لأنَّ بايثون 2 ستتلقى دعمًا أقل مع مرور الوقت. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Port Python 2 Code to Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة السابقة: كيف تستخدم التسجيل Logging في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  2. التنقيح (debugging) هو جزء من عملية تطوير البرمجيات، ويروم البحث عن الأخطاء والمشاكل في الشيفرة، والتي تحول دون تنفيذ البرنامج تنفيذًا صحيحًا. الوحدة code هي إحدى الأدوات المفيدة التي يمكن استخدامها لمحاكاة المترجم (interpreter) التفاعلي، إذ توفر هذه الوحدة فرصةً لتجربة الشيفرة التي تكتبها. قبل أن تكمل هذا المقال، أنصحك بمطالعة المقال السابق عن منقح بايثون: كيف تستخدم منقح بايثون. فهم الوحدة code بدلاً من تفحص الشيفرة باستخدام منقح، يمكنك إضافة الوحدة code لوضع نقاط لإيقاف تنفيذ البرنامج، والدخول في الوضع التفاعلي لتفحص ومتابعة كيفية عمل الشيفرة. الوحدة code هي جزء من مكتبة بايثون القياسية. هذه الوحدة مفيدةٌ لأنَّها ستمكنك من استخدام مترجم دون التضحية بالتعقيد والاستدامة التي توفرها ملفات البرمجة. فيمكنك عبر استخدام الوحدة code تجنب استخدام الدالة print()‎‎‎ في شيفرتك لأجل التنقيح، لأنها طريقة غير عملية. لاستخدام هذه الوحدة في تنقيح الأخطاء، يمكنك استخدام الدالة interact()‎ الخاصة بالوحدة code، والتي توقف تنفيذ البرنامج عند استدعائها، وتوفر لك سطر أوامر تفاعلي حتى تتمكن من فحص الوضع الحالي لبرنامجك. تُكتَب هذه الدالة هكذا: code.interact(banner=None, readfunc=None, local=None, exitmsg=None) تُنفِّذ هذه الدالة حلقة اقرأ-قيِّم-اطبع (تختصر إلى REPL، أي Read–eval–print loop، وتنشئ نسخة من الصنف InteractiveConsole، والذي يحاكي سلوك مترجم بايثون التفاعلي. هذه هي المعاملات الاختيارية: banner: يمكن أن تعطيه سلسلة نصية لتعيين موضع إطلاق المترجم. readfunc: يمكن استخدامه مثل التابع InteractiveConsole.raw_input‎()‎. local: سيعينّ فضاء الأسماء (namespace) الافتراضي لحلقة المترجم (interpreter loop). exitmsg: يمكن إعطاؤه سلسلة نصية لتعيين موضع توقف المترجم. مثلًا، يمكن استخدام المعامل local بهذا الشكل: local=locals()‎ لفضاء أسماء محلي. local=globals()‎ لفضاء أسماء عام. local=dict(globals(), **locals())‎ لاستخدام كل من فضاء الأسماء العام، وفضاء الأسماء المحلي الحالي. المعامل exitmsg جديد، ولم يظهر حتى إصدار بايثون 3.6، لذلك إن كنت تستخدم إصدارًا أقدم، فحدّثه، أو لا تستخدم المعامل exitmsg. ضع الدالة interact()‎‎ حيث تريد إطلاق المترجم التفاعلي في الشيفرة. كيفية استخدام الوحدة code لتوضيح كيفية استخدام الوحدة code، سنكتب بُريمجًا عن الحسابات المصرفية يسمى balances.py. سنعيّن المعامل المحلي عند القيمة locals()‎‎‎ لجعل فضاء الأسماء محليًّا. # `code` استيراد الوحدة import code bal_a = 2324 bal_b = 0 bal_c = 409 bal_d = -2 account_balances = [bal_a, bal_b, bal_c, bal_d] def display_bal(): for balance in account_balances: if balance < 0: print("Account balance of {} is below 0; add funds now." .format(balance)) elif balance == 0: print("Account balance of {} is equal to 0; add funds soon." .format(balance)) else: print("Account balance of {} is above 0.".format(balance)) # لبدء المترجم بفضاء أسماء محلي interact()‎‎‎ استخدام code.interact(local=locals()) display_bal() لقد استدعينا الدالة code.interact()‎‎‎ مع المعامل local=locals()‎ لاستخدام فضاء الأسماء المحلي كقيمة افتراضية داخل حلقة المترجم. لنُنفِّذ البرنامج أعلاه باستخدام الأمر python3 إذا لم نكن تعمل في بيئة افتراضية، أو الأمر python خلاف ذلك: python balances.py بمجرد تنفيذ البرنامج، سنحصل على المخرجات التالية: Python 3.5.2 (default, Nov 17 2016, 17:05:23) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> سيتم وضع المؤشر في نهاية السطر ‎>>>‎، كما لو أنك في سطر الأوامر التفاعلي. من هنا، يمكنك استدعاء الدالة print()‎ لطباعة المتغيرات والدوال وغير ذلك: >>> print(bal_c) 409 >>> print(account_balances) [2324, 0, 409, -2] >>> print(display_bal()) Account balance of 2324 is 0 or above. Account balance of 0 is equal to 0, add funds soon. Account balance of 409 is 0 or above. Account balance of -2 is below 0, add funds now. None >>> print(display_bal) <function display_bal at 0x104b80f28> >>> نرى أنه باستخدام فضاء الأسماء المحلي، يمكننا طباعة المتغيرات، واستدعاء الدالة. يُظهر الاستدعاء الأخير للدالة print()‎ أنّ الدالة display_bal موجودة في ذاكرة الحاسوب. بعد أن تنتهي من العمل على المترجم، يمكنك الضغط على CTRL + D في الأنظمة المستندة إلى *نكس، أو CTRL + Z في أنظمة ويندوز لمغادرة سطر الأوامر ومتابعة تنفيذ البرنامج. إذا أردت الخروج من سطر الأوامر دون تنفيذ الجزء المتبقي من البرنامج، فاكتب quit()‎‎‎، وسيتوقف البرنامج. في المثال التالي، سنستخدم المُعاملين banner و exitmsg: # لبدء المترجم interact()‎‎‎ استخدم الدالة code.interact(banner="Start", local=locals(), exitmsg="End") display_bal() عند تنفيذ البرنامج، ستحصل على المخرجات التالية: Start >>> يتيح لك استخدام المعامل banner تعيين عدة نقاط داخل شيفرتك، مع القدرة على تحديدها. على سبيل المثال، يمكن أن يكون لديك معامل banner يطبع السلسلة النصية "In for-loop" مع معامل exmsg يطبع "Out of for-loop"، وذلك حتى تعرف مكانك بالضبط في الشيفرة. من هنا، يمكننا استخدام المترجم كالمعتاد. بعد كتابة CTRL + D للخروج من المترجم، ستحصل على رسالة الخروج، وسيتم تنفيذ الدالة: End Account balance of 2324 is 0 or above. Account balance of 0 is equal to 0, add funds soon. Account balance of 409 is 0 or above. Account balance of -2 is below 0, add funds now. سيتم تنفيذ البرنامج بالكامل بعد الجلسة التفاعلية. بمجرد الانتهاء من استخدام الوحدة code لتنقيح الشيفرة، يجب عليك إزالة دوال الوحدة code وعبارة الاستيراد حتى يُنفَّذ البرنامج مثل المعتاد. خلاصة تُستخدَم الوحدة code لإطلاق سطر الأوامر التفاعلي لتفحُّص الشيفرة خطوةً بخطوة بقصد فهم سلوكها، وتعديل الشيفرة إن لزم الأمر. لقراءة المزيد حول هذا الموضوع، يمكنك مطالعة التوثيق الرسمي للوحدة code. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Debug Python with an Interactive Console لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيف تستخدم التسجيل Logging في بايثون 3 المقالة السابقة: كيف تستخدم منقح بايثون المرجع الشامل إلى تعلم لغة بايثون
  3. التعددية الشكلية (Polymorphism) هي القدرة على استخدام واجهة موحدة لعدة أشكال مختلفة، مثل أنواع البيانات أو الأصناف . هذا يسمح للدوال باستخدام كيانات من أنواع مختلفة. بالنسبة للبرامج الكائنية في بايثون، هذا يعني أنه يمكن استخدام كائن معين ينتمي إلى صنف مُعيَّن كما لو كان ينتمي إلى صنف مختلف. تسمح التعددية الشكلية بكتابة شيفرات مرنة ومجرّدَة وسهلة التوسيع والصيانة. سوف تتعلم في هذا الدرس كيفية تطبيق التعددية الشكلية على أصناف بايثون. ما هي التعددية الشكلية؟ التعددية الشكلية هي إحدى السمات الأساسية للأصناف في بايثون، وتُستخدَم عندما تكون هناك توابع لها نفس الأسماء في عدة أصناف، أو أصناف فرعية. يسمح ذلك للدوال باستخدام كائنات من أيٍّ من تلك الأصناف والعمل عليها دون الاكتراث لنوعها. يمكن تنفيذ التعددية الشكلية عبر [الوراثة](رابط المقالة السابقة)، أو باستخدام توابعِ الأصناف الفرعية، أو إعادة تعريفها (overriding). يستخدم بايثون نظام أنواع (typing) خاص، يسمى «نظام التحقق من الأنواع: البطة نموذجًا» (Duck Typing)، وهو حالة خاصة من أنظمة التحقق من الأنواع الديناميكية (Dynamic Typing). يستخدم هذا النظامُ التعدُّديةَ الشكلية، بما في ذلك الربط المتأخر، والإيفاد الديناميكي. يعتمد هذا النظام على «نموذج البطة» بناءً على اقتباسٍ للكاتب جيمس ويتكومب رايلي: خُصِّص هذا المفهوم من قبل مهندس الحاسوب الإيطالي أليكس مارتيلي (Alex Martelli) في رسالة إلى مجموعة comp.lang.python، يقوم نظام التحقق من الأنواع هذا الذي يعتمد البطة نموذجًا على تعريف الكائن من منظور ملاءمة الغرض الذي أُنشِئ لأجله. عند استخدام نظام أنواع عادي، فإنّ ملاءمة الكائن لغرض مُعيَّن يتحدد بنوع الكائن فقط، ولكن في نموذج البطة، يَتحدَّد ذلك بوجود التوابع والخاصيات الضرورية لذلك الغرض بدلًا من النوع الحقيقي للكائن. بمعنى آخر، إذا أردت أن تعرف إن كان الكائن بطةً أم لا، فعليك التحقق مما إذا كان ذلك الكائن يمشي مشي البطة، وصوته كصوت البطة، بدلًا من أن تسأل عما إذا كان الكائن بطةً. عندما تحتوي عدة أصناف أو أصناف فرعية على توابع لها نفس الأسماء، ولكن بسلوكيات مختلفة، نقول إنّ تلك الأصناف متعددة الأشكال (polymorphic) لأنها تستعمل واجهة موحدة يمكن استخدامها مع كيانات من أنواع مختلفة. يمكن للدوال تقييم ومعالجة هذه التوابع متعدِّدة الأشكال دون معرفة أصنافها. إنشاء أصناف متعددة الأشكال للاستفادة من التَعدُّدية الشكلية، سننشئ صنفين مختلفين لاستخدامهما مع كائنين مختلفين. يحتاج هذان الصنفان المختلفان واجهة موحدة يمكن استخدامها بطريقة تعدُّدية الشكل (polymorphically)، لذلك سنعرّف فيهما توابع مختلفة، ولكن لها نفس الاسم. سننشئ صنفًا باسم ‎Shark‎ وصنفُا آخر باسم ‎Clownfish‎، وسيُعرِّف كل منهما التوابع ‎swim()‎ و ‎swim_backwards()‎ و ‎skeleton()‎. class Shark(): def swim(self): print("القرش يسبح.") def swim_backwards(self): print("لا يمكن للقرش أن يسبح إلى الوراء، لكن يمكنه أن يغوص إلى الوراء.") def skeleton(self): print("هيكل القرش مصنوع من الغضروف.") class Clownfish(): def swim(self): print("سمكة المهرج تسبح.") def swim_backwards(self): print("يمكن لسمكة المهرج أن تسبح إلى الخلف.") def skeleton(self): print("هيكل سمكة المهرج مصنوع من العظام.") في الشيفرة أعلاه، لدى الصنفين ‎Shark‎ و ‎Clownfish‎ ثلاث توابع تحمل نفس الاسم بيْد أنّ وظائف تلك التوابع تختلف من صنف لآخر. دعنا نستنسخ (instantiate) من هذين الصنفين كائنين: ... sammy = Shark() sammy.skeleton() casey = Clownfish() casey.skeleton() عند تنفيذ البرنامج باستخدام الأمر ‎python polymorphic_fish.py‎، يمكننا أن نرى أنّ كل كائن يتصرف كما هو متوقع: هيكل القرش مصنوع من الغضروف. هيكل سمكة المهرج مصنوع من العظام. الآن وقد أصبح لدينا كائنان يستخدمان نفس الواجهة، فبمقدورنا استخدام هذين الكائنين بنفس الطريقة بغض النظر عن نوعيهما. التعددية الشكلية في توابع الأصناف لإظهار كيف يمكن لبايثون استخدام الصنفين المختلفين اللذين عرّفناهما أعلاه بنفس الطريقة، سننشئ أولاً حلقة for، والتي ستمر على صف من الكائنات. ثم سنستدعي التوابع بغض النظر عن نوع الصنف الذي ينتمي إليه كل كائن. إلا أننا سنفترض أنّ تلك التوابع موجودة في كل تلك الأصناف. ... sammy = Shark() casey = Clownfish() for fish in (sammy, casey): fish.swim() fish.swim_backwards() fish.skeleton() لدينا كائنان، ‎sammy‎ من الصنف ‎Shark‎، و ‎casey‎ من الصنف ‎Clownfish‎. تمر حلقة ‎for‎ على هذين الكائنين، وتستدعي التوابع ‎swim()‎ و ‎swim_backwards()‎ و ‎skeleton()‎ على كل منها. عند تنفيذ البرنامج، سنحصل على المخرجات التالية: القرش يسبح. لا يمكن للقرش أن يسبح إلى الوراء، لكن يمكنه أن يغوص إلى الوراء. هيكل القرش مصنوع من الغضروف. سمكة المهرج تسبح. يمكن لسمكة المهرج أن تسبح إلى الخلف. هيكل سمكة المهرج مصنوع من العظام. مرت الحلقة ‎for‎ على الكائن ‎sammy‎ من الصنف ‎Shark‎، ثم على الكائن ‎casey‎ المنتمي إلى الصنف ‎Clownfish‎، لذلك نرى التوابع الخاصة بالصنف ‎Shark‎ قبل التوابع الخاصة بالصنف ‎Clownfish‎. يدلُّ هذا على أنَّ بايثون تستخدم هذه التوابع دون أن تعرف أو تعبأ بتحديد نوع الصنف الخاص بالكائنات. وهذا مثال حي على استخدام التوابع بطريقة مُتعدِّدَة الأشكال. التعددية الشكلية في الدوال يمكننا أيضًا إنشاء دالة تقبل أيّ شيء، وهذا سيسمح باستخدام التعددية الشكلية. لننشئ دالة تسمى ‎in_the_pacific()‎، والتي تأخذ كائنًا يمكننا تسميته ‎fish‎. رغم أننا سنستخدم الاسم ‎fish‎، إلا أنه يمكننا استدعاء أي كائن في هذه الدالة: … def in_the_pacific(fish): بعد ذلك، سنجعل الدالة تستخدم الكائن ‎fish‎ الذي مرّرناه إليها. وفي هذه الحالة، سنستدعي التابع ‎swim()‎ المعرّف في كل من الصنفين ‎Shark‎ و ‎Clownfish‎: ... def in_the_pacific(fish): fish.swim() بعد ذلك، سننشئ نسخًا (instantiations) من الصنفين ‎Shark‎ و ‎Clownfish‎ لنمرّرهما بعد ذلك إلى نفس الدالة ‎in_the_pacific()‎: ... def in_the_pacific(fish): fish.swim() sammy = Shark() casey = Clownfish() in_the_pacific(sammy) in_the_pacific(casey) عند تنفيذ البرنامج، سنحصل على المخرجات التالية: القرش يسبح. سمكة المهرج تسبح. رغم أننا مرّرنا كائنًا عشوائيًا (‎fish‎) إلى الدالة ‎in_the_pacific()‎ عند تعريفها، إلا أننا ما زلنا قادرين على استخدامها استخدامًا فعالًا، وتمرير نسخ من الصنفين ‎Shark‎ و ‎Clownfish‎ إليها. استدعى الكائنُ ‎casey‎ التابعَ ‎swim()‎ المُعرَّف في الصنف ‎Clownfish‎، فيما استدعى الكائنُ ‎sammy‎ التابعَ ‎swim()‎ المُعرَّف في الصنف ‎Shark‎. خلاصة تسمح التعدُّدية الشكلية باستخدام الكائنات بغض النظر عن نوعها، وهذا يوفر لبايثون مرونة كبيرة، وقابلية لتوسيع الشيفرة الكائنية. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Apply Polymorphism to Classes in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيف تستخدم منقح بايثون المقالة السابقة: وراثة الأصناف في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  4. تُسِّهل البرمجة الكائنية كتابة شيفرات قابلة لإعادة الاستخدام وتجنب التكرار في مشاريع التطوير. إحدى الآليات التي تحقق بها البرمجة الكائنية هذا الهدف هي مفهوم الوراثة (inheritance)، التي بفضلها يمكن لصنفٍ فرعي (subclass) استخدام الشيفرة الخاصة بصنف أساسي (base class، ويطلق عليه «صنف أب» أيضًا) موجود مسبقًا. سيستعرض هذا الدرس بعض الجوانب الرئيسية لمفهوم الوراثة في بايثون، بما في ذلك كيفية إنشاء الأصناف الأساسية (parent classes) والأصناف الفرعية (child classes)، وكيفية إعادة تعريف (override) التوابع والخاصيات، وكيفية استخدام التابع ‎super()‎، وكيفية الاستفادة من الوراثة المتعددة (multiple inheritance). ما هي الوراثة؟ تقوم الوراثة على استخدام شيفرة صنف معين في صنف آخر أي يرث صنف يراد إنشاؤه شيفرة صنف آخر. يمكن تمثيل مفهوم الوراثة في البرمجة بالوراثة في علم الأحياء تمامًا، فالأبناء يرثون خاصيات معينة من آبائهم. ويمكن لطفل أن يرث طول والده أو لون عينيه بالإضافة إلى خاصيات أخرى جديدة خاصة فيه. كما يتشارك الأطفال نفس اسم العائلة الخاصة بآبائهم. ترث الأصناف الفرعية (subclasses، تُسمى أيضًا *الأصناف الأبناء [child classes]) التوابع والمتغيرات من *الأصناف الأساسية* (base classes، تسمى أيضًاالأصناف الآباء [parent classes]). مثلًا، قد يكون لدينا صنف أساسي يسمى ‎Parent‎ يحتوي متغيرات الأصناف ‎last_name‎ و ‎height‎ و ‎eye_color‎، والتي سيرثها الصنف الابن ‎Child‎. لمَّا كان الصنف الفرعي ‎Child‎ يرث الصنف الأساسي ‎Parent‎، فبإمكانه إعادة استخدام شيفرة ‎Parent‎، مما يسمح للمبرمج بكتابة شيفرة أوجز، وتقليل التكرار. الأصناف الأساسية تشكل الأصناف الأساسية أساسًا يمكن أن تستند إليه الأصناف الفرعية المُتفرِّعة منها، إذ تسمح الأصناف الأساسية بإنشاء أصناف فرعية عبر الوراثة دون الحاجة إلى كتابة نفس الشيفرة في كل مرة. يمكن تحويل أي صنف إلى صنف أساسي، إذ يمكن استخدامه لوحده، أو جعله قالبًا (نموذجًا). لنفترض أّنّ لدينا صنفًا أساسيًا باسم ‎Bank_account‎، وصنفين فرعيين مُشتقين منه باسم ‎Personal_account‎ و ‎Business_account‎. ستكون العديد من التوابع مشتركة بين الحسابات الشخصية (Personalaccount) والحسابات التجارية (Businessaccount)، مثل توابع سحب وإيداع الأموال، لذا يمكن أن تنتمي تلك التوابع إلى الصنف الأساسي ‎Bank_account‎. سيكون للصنف ‎Business_account‎ توابع خاصة به، مثل تابع مخصص لعملية جمع سجلات ونماذج الأعمال، بالإضافة إلى متغير ‎employee_identification_number‎ موروث من الصنف الأب. وبالمثل، قد يحتوي الصنف ‎Animal‎ على التابعين ‎eating()‎ و ‎sleeping()‎، وقد يتضمن الصنف الفرعي ‎Snake‎ تابعين إضافيين باسم ‎hissing()‎ و ‎slithering()‎ خاصين به. دعنا ننشئ صنفًا أساسيًا باسم ‎Fish‎ لاستخدامه لاحقًا أساسًا لأصناف فرعية تمثل أنواع الأسماك. سيكون لكل واحدة من تلك الأسماك أسماء أولى وأخيرة، بالإضافة إلى خصائص مميزة خاصة بها. سننشئ ملفًا جديدًا يسمى ‎fish.py‎ ونبدأ بالباني، والذي سنعرّف داخله متغيري الصنف ‎first_name‎ و ‎last_name‎ لكل كائنات الصنف ‎Fish‎، أو أصنافه الفرعية. class Fish: def __init__(self, first_name, last_name="Fish"): self.first_name = first_name self.last_name = last_name القيمة الافتراضية للمتغير ‎last_name‎ هي السلسلة النصية ‎"Fish"‎، لأننا نعلم أنّ معظم الأسماك سيكون هذا هو اسمها الأخير. لنُضف بعض التوابع الأخرى: class Fish: def __init__(self, first_name, last_name="Fish"): self.first_name = first_name self.last_name = last_name def swim(self): print("The fish is swimming.") def swim_backwards(self): print("The fish can swim backwards.") لقد أضفنا التابعين ‎swim()‎ و ‎swim_backwards()‎ إلى الصنف ‎Fish‎ حتى يتسنى لكل الأصناف الفرعية استخدام هذه التوابع. ما دام أنّ معظم الأسماك التي ننوي إنشاءها ستكون عظمية (أي أنّ لها هيكلا عظميًا) وليس غضروفية (أي أن لها هيكلًا غضروفيًا)، فيمكننا إضافة بعض الخاصيات الإضافية إلى التابع ‎__init__()‎: class Fish: def __init__(self, first_name, last_name="Fish", skeleton="bone", eyelids=False): self.first_name = first_name self.last_name = last_name self.skeleton = skeleton self.eyelids = eyelids def swim(self): print("The fish is swimming.") def swim_backwards(self): print("The fish can swim backwards.") لا يختلف بناء الأصناف الأساسية عن بناء أي صنف آخر، إلا أننا نصممها لتستفيد منها الأصناف الفرعية المُعرّفة لاحقًا. الأصناف الفرعية الأصناف الفرعية هي أصناف ترث كل شيء من الصنف الأساسي. هذا يعني أنّ الأصناف الفرعية قادرة على الاستفادة من توابع ومتغيرات الصنف الأساسي. على سبيل المثال، سيتمكن الصنف الفرعي ‎Goldfish‎ المشتق من الصنف ‎Fish‎ من استخدام التابع ‎swim()‎ المُعرّف في ‎Fish‎ دون الحاجة إلى التصريح عنه. يمكننا النظر إلى الأصناف الفرعية على أنها أقسام من الصنف الأساسي. فإذا كان لدينا صنف فرعي يسمى ‎Rhombus‎ (معيّن)، وصنف أساسي يسمى ‎Parallelogram‎ (متوازي الأضلاع)، يمكننا القول أنّ المعين (‎Rhombus‎) هو متوازي أضلاع (‎Parallelogram‎). يبدو السطر الأول من الصنف الفرعي مختلفًا قليلًا عن الأصناف غير الفرعية، إذ يجب عليك تمرير الصنف الأساسي إلى الصنف الفرعي كمعامل: class Trout(Fish): الصنف ‎Trout‎ هو صنف فرعي من ‎Fish‎. يدلنا على هذا الكلمةُ ‎Fish‎ المُدرجة بين قوسين. يمكننا إضافة توابع جديدة إلى الأصناف الفرعية، أو إعادة تعريف التوابع الخاصة بالصنف الأساسي، أو يمكننا ببساطة قبول التوابع الأساسية الافتراضية باستخدام الكلمة المفتاحية ‎pass‎، وهو ما سنفعله في المثال التالي: ... class Trout(Fish): pass يمكننا الآن إنشاء كائن من الصنف ‎Trout‎ دون الحاجة إلى تعريف أي توابع إضافية. ... class Trout(Fish): pass terry = Trout("Terry") print(terry.first_name + " " + terry.last_name) print(terry.skeleton) print(terry.eyelids) terry.swim() terry.swim_backwards() لقد أنشأنا كائنًا باسم ‎terry‎ من الصنف ‎Trout‎، والذي سيستخدم جميع توابع الصنف ‎Fish‎ وإن لم نعرّفها في الصنف الفرعي ‎Trout‎. يكفي أن نمرر القيمة ‎"Terry"‎ إلى المتغير ‎first_name‎، أما المتغيرات الأخرى فقد جرى تهيئتها سلفًا. عند تنفيذ البرنامج، سنحصل على المخرجات التالية: Terry Fish bone False The fish is swimming. The fish can swim backwards. لننشئ الآن صنفًا فرعيًا آخر يعرّف تابعًا خاصا به. سنسمي هذا الصنف ‎Clownfish‎. سيسمح التابع الخاص به بالتعايش مع شقائق النعمان البحري: ... class Clownfish(Fish): def live_with_anemone(self): print("The clownfish is coexisting with sea anemone.") دعنا ننشئ الآن كائنًا آخر من الصنف ‎Clownfish‎: ... casey = Clownfish("Casey") print(casey.first_name + " " + casey.last_name) casey.swim() casey.live_with_anemone() عند تنفيذ البرنامج، سنحصل على المخرجات التالية: Casey Fish The fish is swimming. The clownfish is coexisting with sea anemone. تُظهر المخرجات أنّ الكائن ‎casey‎ المستنسخ من الصنف ‎Clownfish‎ قادر على استخدام التابعين ‎__init__()‎ و ‎swim()‎ الخاصين بالصنف ‎Fish‎، إضافة إلى التابع ‎live_with_anemone()‎ الخاص بالصنف الفرعي. إذا حاولنا استخدام التابع ‎live_with_anemone()‎ في الكائن ‎Trout‎، فسوف يُطلق خطأ: terry.live_with_anemone() AttributeError: 'Trout' object has no attribute 'live_with_anemone' ذلك أنَّ التابع ‎live_with_anemone()‎ ينتمي إلى الصنف الفرعي ‎Clownfish‎ فقط، وليس إلى الصنف الأساسي ‎Fish‎. ترث الأصناف الفرعية توابع الصنف الأساسي الذي اشتُقَّت منه، لذا يمكن لكل الأصناف الفرعية استخدام تلك التوابع. إعادة تعريف توابع الصنف الأساسي في المثال السابق عرّفنا الصنف الفرعي ‎Trout‎ الذي استخدم الكلمة المفتاحية ‎pass‎ ليرث جميع سلوكيات الصنف الأساسي ‎Fish‎، وعرّفنا كذلك صنفًا آخر ‎Clownfish‎ يرث جميع سلوكيات الصنف الأساسي، ويُنشئ أيضًا تابعًا خاصًا به. قد نرغب في بعض الأحيان في استخدام بعض سلوكيات الصنف الأساسي، ولكن ليس كلها. يُطلَق على عملية تغيير توابع الصنف الأساسي «إعادة التعريف» (Overriding). عند إنشاء الأصناف الأساسية أو الفرعية، فلا بد أن تكون لك رؤية عامة لتصميم البرنامج حتى لا تعيد تعريف التوابع إلا عند الضرورة. سننشئ صنفًا فرعيًا ‎Shark‎ مشتقًا من الصنف الأساسي ‎Fish‎، الذي سيمثل الأسماك العظمية بشكل أساسي، لذا يتعين علينا إجراء تعديلات على الصنف ‎Shark‎ المخصص في الأصل للأسماك الغضروفية. من منظور تصميم البرامج، إذا كانت لدينا أكثر من سمكة غير عظمية واحدة، فيُستحب أن ننشئ صنفًا خاصًا بكل نوع من هذين النوعين من الأسماك. تمتلك أسماك القرش، على عكس الأسماك العظمية، هياكل مصنوعة من الغضاريف بدلاً من العظام. كما أنّ لديها جفونًا، ولا تستطيع السباحة إلى الوراء، كما أنها قادرة على المناورة للخلف عن طريق الغوص. على ضوء هذه المعلومات، سنعيد تعريف الباني ‎__init__()‎ والتابع ‎swim_backwards()‎. لا نحتاج إلى تعديل التابع ‎swim()‎ لأنّ أسماك القرش يمكنها السباحة. دعنا نلقي نظرة على هذا الصنف الفرعي: ... class Shark(Fish): def __init__(self, first_name, last_name="Shark", skeleton="cartilage", eyelids=True): self.first_name = first_name self.last_name = last_name self.skeleton = skeleton self.eyelids = eyelids def swim_backwards(self): print("The shark cannot swim backwards, but can sink backwards.") لقد أعدنا تعريف المعاملات التي تمت تهيئتها في التابع ‎__init__()‎، فأخذ المتغير ‎last_name‎ القيمة ‎"Shark"‎، كما أُسنِد إلى المتغير ‎skeleton‎ القيمة ‎"cartilage"‎، فيما أُسنِدَت القيمة المنطقية ‎True‎ إلى المتغير ‎eyelids‎. يمكن لجميع نُسخ الصنف إعادة تعريف هذه المعاملات. يطبع التابع ‎swim_backwards()‎ سلسلة نصية مختلفة عن تلك التي يطبعها في الصنف الأساسي ‎Fish‎، لأنّ أسماك القرش غير قادرة على السباحة للخلف كما تفعل الأسماك العظمية. يمكننا الآن إنشاء نسخة من الصنف الفرعي ‎Shark‎، والذي سيستخدم التابع ‎swim()‎ الخاص بالصنف الأساسي ‎Fish‎: ... sammy = Shark("Sammy") print(sammy.first_name + " " + sammy.last_name) sammy.swim() sammy.swim_backwards() print(sammy.eyelids) print(sammy.skeleton) عند تنفيذ هذه الشيفرة، سنحصل على المخرجات التالية: Sammy Shark The fish is swimming. The shark cannot swim backwards, but can sink backwards. True cartilage لقد أعاد الصنف الفرعي ‎Shark‎ تعريف التابعين ‎__init__()‎ و ‎swim_backwards()‎ الخاصين بالصنف الأساسي ‎Fish‎، وورث في نفس الوقت التابع ‎swim()‎ الخاص بالصنف الأساسي. الدالة ‎super()‎ يمكنك باستخدام الدالة ‎super()‎ الوصول إلى التوابع الموروثة التي أُعيدت كتابتها. عندما نستخدم الدالة ‎super()‎، فإننا نستدعي التابع الخاص بالصنف الأساسي لاستخدامه في الصنف الفرعي. على سبيل المثال، قد نرغب في إعادة تعريف جانب من التابع الأساسي وإضافة وظائف معينة إليه، ثم بعد ذلك نستدعي التابع الأساسي لإنهاء بقية العمل. في برنامج خاص بتقييم الطلاب مثلًا، قد نرغب في تعريف صنف فرعي ‎Weighted_grade‎ يرث الصنف الأساسي ‎Grade‎، ونعيد فيه تعريف التابع ‎calculate_grade()‎ الخاص بالصنف الأساسي من أجل تضمين شيفرة خاصة بحساب التقدير المرجّح (weighted grade)، مع الحفاظ على بقية وظائف الصنف الأساسي. عبر استدعاء التابع ‎super()‎، سنكون قادرين على تحقيق ذلك. عادة ما يُستخدم التابع ‎super()‎ ضمن التابع ‎__init__()‎، لأنّه المكان الذي ستحتاج فيه على الأرجح إلى إضافة بعض الوظائف الخاصة إلى الصنف الفرعي قبل إكمال التهيئة من الصنف الأساسي. لنضرب مثلًا لتوضيح ذلك، دعنا نعدّل الصنف الفرعي ‎Trout‎. نظرًا لأنّ سمك السلمون المرقَّط من أسماك المياه العذبة، فلنضف متغيرًا اسمه ‎water‎ إلى التابع ‎__init__()‎، ولنُعطه القيمة ‎"freshwater"‎، ولكن مع الحفاظ على باقي متغيرات ومعاملات الصنف الأساسي: ... class Trout(Fish): def __init__(self, water = "freshwater"): self.water = water super().__init__(self) ... لقد أعدنا تعريف التابع ‎__init__()‎ في الصنف الفرعي ‎Trout‎، وغيرنا سلوكه موازنةً بالتابع ‎__init__()‎ المُعرَّف سلفًا في الصنف الأساسي ‎Fish‎. لاحظ أننا استدعينا التابع ‎__init__()‎ الخاص بالصنف ‎Fish‎ بشكل صريح ضمن التابع ‎__init__()‎ الخاص بالصنف ‎Trout‎،. بعد إعادة تعريف التابع، لم نعد بحاجة إلى تمرير ‎first_name‎ كمعامل إلى ‎Trout‎، وفي حال فعلنا ذلك، فسيؤدي ذلك إلى إعادة تعيين ‎freshwater‎ بدلاً من ذلك. سنُهيِّئ بعد ذلك الخاصية ‎first_name‎ عن طريق استدعاء المتغير في الكائن خاصتنا. الآن يمكننا استدعاء متغيرات الصنف الأساسي التي تمت تهيئتها، وكذلك استخدام المتغير الخاص بالصنف الفرعي: ... terry = Trout() # تهيئة الاسم الأول terry.first_name = "Terry" # super() الخاص بالصنف الأساسي عبر __init__() استخدام print(terry.first_name + " " + terry.last_name) print(terry.eyelids) # المعاد تعريفها في الصنف الفرعي __init__() استخدام print(terry.water) # الخاص بالصنف الأساسي swim() استخدام التابع terry.swim() سنحصل على المخرجات التالية: Terry Fish False freshwater The fish is swimming. تُظهر المخرجات أنّ الكائن ‎terry‎ المنسوخ من الصنف الفرعي ‎Trout‎ قادر على استخدام المتغير ‎water‎ الخاص بتابع الصنف الفرعي ‎__init__()‎، إضافة إلى استدعاء المتغيرات ‎first_name‎ و ‎last_name‎ و ‎eyelids‎ الخاصة بالتابع ‎__init__()‎ المُعرَّف في الصنف الأساسي ‎Fish‎. يسمح لنا التابع ‎super()‎ المُضمن في بايثون باستخدام توابع الصنف الأساسي حتى بعد إعادة تعريف تلك التوابع في الأصناف الفرعية. الوراثة المُتعدِّدة (Multiple Inheritance) المقصود بالوراثة المتعددة هي قدرة الصنف على أن يرث الخاصيات والتوابع من أكثر من صنف أساسي واحد. هذا من شأنه تقليل التكرار في البرامج، ولكنه يمكن أيضًا أن يُعقِّد العمل، لذلك يجب استخدام هذا المفهوم بحذر. لإظهار كيفية عمل الوراثة المتعددة، دعنا ننشئ صنفًا فرعيًا ‎Coral_reef‎ يرث من الصنفين ‎Coral‎ و ‎Sea_anemone‎. يمكننا إنشاء تابع في كل صنف أساسي، ثم استخدام الكلمة المفتاحية ‎pass‎ في الصنف الفرعي ‎Coral_reef‎: class Coral: def community(self): print("Coral lives in a community.") class Anemone: def protect_clownfish(self): print("The anemone is protecting the clownfish.") class CoralReef(Coral, Anemone): pass يحتوي الصنف ‎Coral‎ على تابع يسمى ‎community()‎، والذي يطبع سطرًا واحدًا، بينما يحتوي الصنف ‎Anemone‎ على تابع يسمى ‎protect_clownfish()‎، والذي يطبع سطرًا آخر. سنُمرِّر الصنفين كلاهما بين قوسين في تعريف الصنف CoralReef، ما يعني أنه سيرث الصنفين معًا. دعنا الآن ننشئ كائنًا من الصنف CoralReef: ... great_barrier = CoralReef() great_barrier.community() great_barrier.protect_clownfish() الكائن ‎great_barrier‎ مُشتقٌ الصنف ‎CoralReef‎، ويمكنه استخدام التوابع من كلا الصنفين الأساسيين. عند تنفيذ البرنامج، سنحصل على المخرجات التالية: Coral lives in a community. The anemone is protecting the clownfish. تُظهِر المخرجات أنَّ التوابع من كلا الصنفين الأساسيين استُخدِما بفعالية في الصنف الفرعي. تسمح لنا الوراثة المُتعدِّدة بإعادة استخدام الشيفرات البرمجية المكتوبة في أكثر من صنف أساسي واحد. وإذا تم تعريف التابع نفسه في أكثر من صنف أساسي واحد، فإنّ الصنف الفرعي سيستخدم التابع الخاص بالصنف الأساسي الذي ظهر أولًا في قائمة الأصناف المُمرَّرة إليه عند تعريفه. رغم فوائدها الكثيرة وفعاليتها، إلا أنَّ عليك توخي الحذر في استخدام الوراثة المُتعدِّدة، حتى لا ينتهي بك الأمر بكتابة برامج مُعقَّدة وغير مفهومة للمبرمجين الآخرين. خلاصة تعلمنا في هذا الدرس كيفية إنشاء أصناف أساسية وفرعية، وكيفية إعادة تعريف توابع وخاصيات الأصناف الأساسية داخل الأصناف الفرعية باستخدام التابع ‎super()‎، إضافة إلى مفهوم الوراثة المتعددة. الوراثة هي إحدى أهم ميزات البرمجة الكائنية التي تجعلها متوافقة مع مبدأ DRY (لا تكرر نفسك)، وهذا يحسن إنتاجية المبرمجين، ويساعدهم على تصميم برامج فعالة وواضحة. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Class Inheritance in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف المقالة السابقة: فهم متغيرات الأصناف والنسخ في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  5. تسمح البرمجة الكائنية باستخدام متغيرات على مستوى الصنف، أو على مستوى النسخة (instance). المتغيرات هي رموز (symbols) تدل على قيمة تستخدمها في برنامجك. يشار إلى المتغيرات على مستوى الصنف باسم متغيرات الصنف (class variables)، في حين تسمى المتغيرات الموجودة على مستوى النسخة متغيرات النسخة (instance variables). إذا توقعت أن يكون المتغير متسقًا في جميع نسخ الصنف، أو عندما تود تهيئة المتغير، فالأفضل أن تُعرِّف ذلك المتغير على مستوى الصنف. أما إن كنت تعلم أن المتغير سيختلف من نسخة إلى أخرى، فالأفضل أن تعرفه على مستوى النسخة. يسعى أحد مبادئ تطوير البرمجيات هو مبدأ DRY (اختصارًا للعبارة don’t repeat yourself، والذي يعني لا تكرر نفسك) إلى الحد من التكرار في الشيفرة. أي تلتزم البرمجة الكائنية بمبدأ DRY على تقليل التكرار في الشيفرة. ستتعلم في هذا الدرس كيفية استخدام متغيرات الصنف والنسخة في البرمجة الكائنية في بايثون. متغيرات الصنف تٌعرَّف متغيرات الصنف داخل الصنف وخارج كل توابعه وعادةً ما توضع مباشرة أسفل ترويسة الصنف، وقبل الباني (constructor) والتوابع الأخرى. ولمَّا كانت مملوكة للصنف نفسه، فستُشارَك مع جميع نُسَخ ذلك الصنف. وبالتالي، سيكون لها نفس القيمة بغض النظر عن النسخة، إلا إن كنت ستستخدم متغير الصنف لتهيئة متغير معيَّن. متغير الصنف يبدو كما يلي: class Shark: animal_type = "fish" في الشيفرة أعلاه أحلنا القيمة "fish" إلى المتغير animal_type. يمكننا إنشاء نسخة من الصنف Shark (سنطلق عليها new_shark)، ونطبع المتغير باستخدام الصياغة النقطية (dot notation): class Shark: animal_type = "fish" new_shark = Shark() print(new_shark.animal_type) لننفذ البرنامج: python shark.py سيعيد البرنامج قيمة المتغير: fish دعنا نضيف مزيدًا من متغيرات الصنف، ونطبعها: class Shark: animal_type = "fish" location = "ocean" followers = 5 new_shark = Shark() print(new_shark.animal_type) print(new_shark.location) print(new_shark.followers) يمكن أن تتألف متغيرات الصنف من أي نوع من البيانات المتاحة في بايثون تمامًا مثل أي متغير آخر. استخدمنا في هذا البرنامج السلاسل النصية والأعداد الصحيحة. لننفذ البرنامج مرة أخرى باستخدام الأمر python shark.py ونرى المخرجات: fish ocean 5 يمكن للنسخة new_shark الوصول إلى جميع متغيرات الصنف وطباعتها عند تنفيذ البرنامج. تُنشَأ متغيرات الصنف عند إنشاء الصنف مباشرةً (وليس عند إنشاء نسخة منه) وتحتل موضعًا لها في الذاكرة ويمكن لأي كائن مُشتَق (نسخة) من الصنف نفسه أن يصل إليها ويقرأ قيمتها. متغيرات النسخة تختلف متغيرات النسخة عن متغيرات الصنف أن النسخة المشتقة من الصنف هي من تملكها وليس الصنف نفسه أي تكون على مستوى النسخة وسيُنشَأ متغير مستقل في الذاكرة عند إنشاء كل نسخة. هذا يعني أنّ متغيرات النسخة ستختلف من كائن إلى آخر. تُعرَّف متغيرات النسخة ضمن التوابع على خلاف متغيرات الصنف. في مثال الصنف Shark أدناه، عّرفنا متغيري النسخة name و age: class Shark: def __init__(self, name, age): self.name = name self.age = age عندما ننشئ كائنًا من الصنف Shark، سيتعيّن علينا تعريف هذه المتغيرات، عبر تمريرها كمعاملات ضمن الباني (constructor)، أو أي تابع آخر. class Shark: def __init__(self, name, age): self.name = name self.age = age new_shark = Shark("Sammy", 5) كما هو الحال مع متغيرات الأصناف، يمكننا بالمثل طباعة متغيرات النسخة: class Shark: def __init__(self, name, age): self.name = name self.age = age new_shark = Shark("Sammy", 5) print(new_shark.name) print(new_shark.age) عند تنفيذ البرنامج أعلاه باستخدام python shark.py، سنحصل على المخرجات التالية: Sammy 5 تتألف المخرجات التي حصلنا عليها من قيم المتغيرات التي هيّأناها لأجل الكائن new_shark. لننشئ كائنًا آخر من الصنف Shark يسمى stevie: class Shark: def __init__(self, name, age): self.name = name self.age = age new_shark = Shark("Sammy", 5) print(new_shark.name) print(new_shark.age) stevie = Shark("Stevie", 8) print(stevie.name) print(stevie.age) يمرِّر الكائن stevie المعاملات إلى الباني لتعيين قيم متغيرات النسخة الخاصة به. تسمح متغيرات النسخة، المملوكة لكائنات الصنف، لكل كائن أو نسخة أن تكون لها متغيرات خاصة بها ذات قيم مختلفة عن بعضها بعضًا. العمل مع متغيرات الصنف والنسخة معًا غالبًا ما تُستخدم متغيرات الصنف ومتغيرات النسخة في نفس الشيفرة، ويوضح المثال التالي يستخدم الصنف Shark الذي أنشأناه سابقًا هذا الأمر. تشرح التعليقات في البرنامج كل خطوة من خطوات العملية. class Shark: # متغيرات الصنف animal_type = "fish" location = "ocean" # name و age باني مع متغيري النسخة def __init__(self, name, age): self.name = name self.age = age # followers تابع مع متغير النسخة def set_followers(self, followers): print("This user has " + str(followers) + " followers") def main(): # الكائن الأول، إعداد متغيرات النسخة في الباني sammy = Shark("Sammy", 5) # name طباعة متغير النسخة print(sammy.name) # location طباعة متغير الصنف print(sammy.location) # الكائن الثاني stevie = Shark("Stevie", 8) # name طباعة متغير النسخة print(stevie.name) # followers لتمرير متغير النسخة set_followers استخدام التابع stevie.set_followers(77) # animal_type طباعة متغير الصنف print(stevie.animal_type) if __name__ == "__main__": main() عند تنفيذ البرنامج باستخدام python shark.py، سنحصل على المخرجات التالية: Sammy ocean Stevie This user has 77 followers fish خلاصة في البرمجة الكائنية، يشار إلى المتغيرات المُعرَّفة على مستوى الصنف بمتغيرات الصنف، في حين تسمى المتغيرات المُعرّفة على مستوى الكائن بمتغيرات النسخة. يتيح لنا هذا التمييز استخدام متغيرات ذات قيم واحدة بينها عبر متغيرات الصنف، أو استخدام متغيرات مختلفة لكل كائن على حدة عبر متغيرات النسخة. كما يضمن استخدام المتغيرات الخاصة بالصنف أو النسخة أن تكون الشيفرة متوافقة مع مبدأ DRY. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال Understanding Class and Instance Variables in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضا المقالة التالية: وراثة الأصناف في بايثون 3 المقالة السابقة: كيفية إنشاء الأصناف وتعريف الكائنات في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  6. بايثون لغةٌ برمجة كائنية (object-oriented programming language). تركز البرمجة الكائنية (OOP) على كتابة شيفرات قابلة لإعادة الاستخدام، على عكس البرمجة الإجرائية (procedural programming) التي تركز على كتابة تعليمات صريحة ومتسلسلة. تتيح البرمجة الكائنية لمبرمجي بايثون كتابة شيفرات سهلة القراءة والصيانة، وهذا مفيد للغاية عند تطوير البرامج المُعقَّدة. التمييز بين الأصناف والكائنات أحدُ المفاهيم الأساسية في البرمجة الكائنية، ويوضح التعريفان التاليان الفرق بين المفهومين: الصنف - نموذج عام تُنسج على منواله كائنات يُنشِئها المبرمج. يُعرِّف الصنف مجموعةً من الخاصيات التي تميز أي كائن يُستنسَخ (instantiated) منه. الكائن - نسخةٌ (instance) من الصنف، فهو تجسيد عملي للصنف داخل البرنامج. تُستخدَم الأصناف لإنشاء أنماط، ثم تُستعمَل تلك الأنماط لإنشاء كائنات منها. ستتعلم في هذا الدرس كيفيَّة إنشاء الأصناف والكائنات، وتهيئة الخاصيات باستخدام تابعٍ بانٍ (constructor method)، والعمل على أكثر من كائن من نفس الصنف. الأصناف الأصناف هي نماذج عامة تُستخدم لإنشاء كائنات وسبق أن عرَّفناها آنفًا. تُنشَأ الأصناف باستخدام الكلمة المفتاحية ‎class‎، بشكل مشابه [لتعريف الدوال](رابط المقالة 34) الذي يكون باستخدام الكلمة المفتاحية ‎def‎. دعنا نعرّف صنفًا يسمى ‎Shark‎، ونجعل له تابعين مرتبطين به، swim و be_awesome: class Shark: def swim(self): print("The shark is swimming.") def be_awesome(self): print("The shark is being awesome.") تُسمَّى مثل هذه الدوال «توابعًا» (methods) لأنهما معرفتان داخل الصنف ‎Shark‎؛ أي أنهما دالتان تابعتان للصنف ‎Shark‎. الوسيط الأول لهاتَين الدالتين هو ‎self‎، وهو مرجع إلى الكائنات التي يتم بناؤها من هذا الصنف. للإشارة إلى نُسخ (أو كائنات) من الصنف، يوضع ‎self‎ دائمًا في البداية، لكن يمكن أن تكون معه وسائط أخرى. لا يؤدي تعريف الصنف ‎Shark‎ إلى إنشاء كائنات منه، وإنما يعرّف فقط النمط العام لتلك الكائنات، والتي يمكننا تعريفها لاحقًا. لذا، إذا نفّذت البرنامج أعلاه الآن، فلن يُعاد أي شيء. الكائنات الكائن هو نسخةٌ (instance) من صنف. ويمكن أن نأخذ الصنف ‎Shark‎ المُعرَّف أعلاه، ونستخدمه لإنشاء كائن يعدُّ نسخةً منه. سننشئ كائنًا ‎Shark‎ يسمى ‎sammy‎: sammy = Shark() لقد أحلنا على الكائن ‎sammy‎ ناتج الباني ‎Shark()‎، والذي يعيد نسخةً من الصنف. سنستخدم في الشيفرة التالية التابعين الخاصين بالكائن ‎sammy‎: sammy = Shark() sammy.swim() sammy.be_awesome() يستخدم الكائن ‎sammy‎ التابعين ‎swim()‎ و ‎be_awesome()‎، وقد استدعينَاهما باستعمال المعامل النقطي (‎.‎)، والذي يُستخدم للإشارة إلى خاصيات أو توابع الكائنات. في هذه الحالة، استدعينا تابعًا، لذلك استعملنا قوسين مثلما نفعل عند استدعاء دالة. الكلمة ‎self‎ هي معامل يُمرّر إلى توابع الصنف ‎Shark‎، في المثال أعلاه، يمثّل ‎self‎ الكائن ‎sammy‎. يتيح المعامل ‎self‎ للتوابع الوصول إلى خاصيات الكائن الذي استُدعيت معه. لاحظ أننا لم نمرر شيئًا داخل القوسين عند استدعاء التابع أعلاه، ذلك أنّ الكائن ‎sammy‎ يُمرّر تلقائيًا مع العامل النقطي. البرنامج التالي يوضح لنا الأمر: class Shark: def swim(self): print("The shark is swimming.") def be_awesome(self): print("The shark is being awesome.") def main(): sammy = Shark() sammy.swim() sammy.be_awesome() if __name__ == "__main__": main() لننفذ البرنامج لنرى ما سيحدث: python shark.py ستُطبع المخرجات التالية: The shark is swimming. The shark is being awesome. في الشيفرة أعلاه، استدعى الكائن ‎sammy‎ التابعين ‎swim()‎ و ‎be_awesome()‎ في الدالة الرئيسية ‎main()‎. الباني يٌستخدم الباني (Constructor Method) لتهيئة البيانات الأولية، ويُنفَّذ لحظة إنشاء الكائن. في تعريف الصنف، يأخذ الباني الاسم ‎__init__‎، وهو أول تابع يُعرّف في الصنف، ويبدو كما يلي: class Shark: def __init__(self): print("This is the constructor method.") إذا أضفت التابع ‎__init__‎ إلى الصنف ‎Shark‎ في البرنامج أعلاه، فسيَطبع البرنامجُ المخرجات التالية: This is the constructor method. The shark is swimming. The shark is being awesome. يُنفَّذ الباني تلقائيًا، لذا يستخدمه مطورو بايثون لتهيئة أصنافهم. سنُعدِّل الباني أعلاه، ونجعله يستخدم متغيرًا اسمه ‎name‎ سيمثّل اسم الكائن. في الشيفرة التالية، سيكون المتغير ‎name‎ المعامل المُمرَّر إلى الباني، ونحيل قيمته إلى الخاصية ‎self.name‎: class Shark: def __init__(self, name): self.name = name بعد ذلك، يمكننا تعديل السلاسل النصية في دوالنا للإشارة إلى اسم الصنف، على النحو التالي: class Shark: def __init__(self, name): self.name = name def swim(self): # الإشارة إلى الاسم print(self.name + " is swimming.") def be_awesome(self): # الإشارة إلى الاسم print(self.name + " is being awesome.") أخيرًا، يمكننا تعيين اسم الكائن ‎sammy‎ عند القيمة ‎"Sammy"‎ (أي قيمة الخاصية name) بتمريره إلى ‎Shark()‎ عند إنشائه: class Shark: def __init__(self, name): self.name = name def swim(self): print(self.name + " is swimming.") def be_awesome(self): print(self.name + " is being awesome.") def main(): # Shark تعيين اسم كائن sammy = Shark("Sammy") sammy.swim() sammy.be_awesome() if __name__ == "__main__": main() عرّفنا التابع ‎__init__‎، والذي يقبل مُعاملين ‎self‎ و name (تذكر أن المعامل ‎self‎ يُمرر تلقائيا إلى التابع)، ثم عرّفنا متغيرًا فيه. عند تنفيذ البرنامج: python shark.py سنحصل على: Sammy is swimming. Sammy is being awesome. لقد طُبع الاسم الذي مرّرناه إلى الكائن. ونظرًا لأنّ الباني يُنفّذ تلقائيًا، فلست بحاجة إلى استدعائه بشكل صريح، فيكفي تمرير الوسائط بين القوسين التاليين لاسم الصنف عند إنشاء نسخة جديدة منه. إذا أردت إضافة معامل آخر، مثل ‎age‎، فيمكن ذلك عبر تمريره إلى التابع ‎__init__‎: class Shark: def __init__(self, name, age): self.name = name self.age = age عند إنشاء الكائن ‎sammy‎، سنمرر عُمره أيضًا بالإضافة إلى اسمه: sammy = Shark("Sammy", 5) إذًا، تتيح البانيات تهيئة خاصيات الكائن لحظة إنشائه. العمل مع عدة كائنات تتيح لنا الأصناف إنشاء العديد من الكائنات المتماثلة التي تتبع نفس النمط. لتفهم ذلك بشكل أفضل، دعنا نضيف كائنًا آخر من الصنف ‎Shark‎ إلى برنامجنا: class Shark: def __init__(self, name): self.name = name def swim(self): print(self.name + " is swimming.") def be_awesome(self): print(self.name + " is being awesome.") def main(): sammy = Shark("Sammy") sammy.be_awesome() stevie = Shark("Stevie") stevie.swim() if __name__ == "__main__": main() لقد أنشأنا كائنًا ثانيًا من الصنف ‎Shark‎ يسمى ‎stevie‎، ومرّرنا إليه الاسم ‎"Stevie"‎. في هذا المثال، استدعينا التابع ‎be_awesome()‎ مع الكائن ‎sammy‎، والتابع ‎swim()‎ مع الكائن ‎stevie‎. لننفذ البرنامج: python shark.py سنحصل على المخرجات التالية: Sammy is being awesome. Stevie is swimming. يبدو ظاهرًا في المخرجات أننا نستخدم كائنين مختلفين، الكائن ‎sammy‎ والكائن ‎stevie‎، وكلاهما من الصنف ‎Shark‎. تتيح لنا الأصناف إنشاء عدة كائنات تتبع كلها نفس النمط دون الحاجة إلى بناء كل واحد منها من البداية. خلاصة تطرَّقنا في هذا الدرس إلى عِدَّة مفاهيم، مثل إنشاء الأصناف، وإنشاء الكائنات، وتهيئة الخاصيات باستخدام البانيات، والعمل مع أكثر من كائن من نفس الصنف. تُعدُّ البرمجة الكائنية أحد المفاهيم الضرورية التي ينبغي أن يتعلمها كل مبرمجي بايثون، لأنها تساعد على كتابة شيفرات قابلة لإعادة الاستخدام، إذ أنَّ الكائنات التي تُنشَأ في برنامج ما يمكن استخدامها في برامج أخرى. كما أنّ البرامج الكائنية عادة ما تكون أوضح وأكثر مقروئية، خصوصًا في البرامج المعقدة التي تتطلب تخطيطًا دقيقًا، وهذا بدوره يسهل صيانة البرامج مستقبلًا. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Construct Classes and Define Objects in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: فهم متغيرات الأصناف والنسخ في بايثون 3 المقالة السابقة: كيفية استخدام ‎args و ‎*kwargs في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  7. تعدُّ المعاملات في تعاريف الدوال كيانات مسماة تُحدِّد وسيطًا (argument) يمكن أن يُمرَّر إلى الدالة المُعرَّفة. أثناء البرمجة، قد لا تدرك جميع حالات الاستخدام الممكنة للشيفرة، لذا قد ترغب في توسيع خيارات المبرمجين المستقبليين الذين سيستخدمون الوحدة التي طورتها. سنتعلم في هذا الدرس كيفيَّة تمرير عدد متغير من الوسائط إلى دالة ما باستخدام الصياغتين ‎*args‎ و ‎**kwargs‎. الوسيط ‎*args في بايثون، يمكن استخدام الشكل أحادي النجمة ‎*args‎ كمعامل لتمرير قائمة غير محددة الطول من الوسائط غير المسماة (non-keyworded argument) إلى الدوال. تجدر الإشارة إلى أنّ النجمة (‎*‎) عنصر ضروري هنا، إذ رغم أنّ الكلمة ‎args‎ متعارف عليها بين المبرمجين، إلا أنها غير رسمية. لنلقِ نظرة على مثال لدالة تستخدم وسيطين: def multiply(x, y): print (x * y) عرّفنا في الشفرة أعلاه دالة تقبل وسيطين ‎x‎ و ‎y‎، عندما نستدعي هذه الدالة، سنحتاج إلى تمرير عددين موافقين للوسيطين ‎x‎ و ‎y‎. في هذا المثال، سنمرّر العدد الصحيح ‎5‎ إلى ‎x‎، والعدد الصحيح ‎4‎ إلى ‎y‎: def multiply(x, y): print (x * y) multiply(5, 4) عند تنفيذ الشفرة أعلاه: python lets_multiply.py سنحصل على المخرجات التالية: 20 ماذا لو قررنا لاحقًا أننا نود حساب ناتج ضرب ثلاثة أعداد بدلًا من عددين فقط؟ إذا حاولت تمرير عدد إضافي إلى الدالة، كما هو موضح أدناه: def multiply(x, y): print (x * y) multiply(5, 4, 3) فسيُطلَق الخطأ التالي: TypeError: multiply() takes 2 positional arguments but 3 were given إذا شككت أنك ستحتاج إلى استخدام المزيد من الوسائط لاحقًا، فالحل هو استخدام ‎*args‎ كمعامل. سنزيل المُعاملين ‎x‎ و ‎y‎ من الشفرة في المثال الأول، ونضع مكانهما ‎*args‎: def multiply(*args): z = 1 for num in args: z *= num print(z) multiply(4, 5) multiply(10, 9) multiply(2, 3, 4) multiply(3, 5, 10, 6) عندما ننفّذ هذه الشفرة، سنحصل على ناتج استدعاءات الدالة أعلاه: 20 90 24 900 يمكننا باستخدام الوسيط ‎*args‎ تمرير أي عدد نحب من الوسائط عند استدعاء الدالة بالإضافة إلى كتابة شيفرة أكثر مرونة، وإنشاء دوال تقبل عددًا غير محدد مسبقًا من الوسائط غير المسماة. الوسيط ‎**kwargs يُستخدَم الشكل ذو النجمتين ‎**kwargs‎ لتمرير قاموس متغير الطول من الوسائط المسماة إلى الدالة المعرّفة. مرة أخرى، النجمتان (‎**‎) ضروريتان، فمع أنّ استخدام الكلمة ‎kwargs‎ متعارف عليه لدى المبرمجين، إلا أنها غير رسمية. يمكن أن تأخذ ‎**kwargs‎، كما هو شأن ‎*args‎، أيّ عدد من الوسائط التي ترغب في تمريرها إلى الدالة بيْد أنّ ‎**kwargs‎ تختلف عن ‎*args‎ في أنها تستوجب تعيين أسماء المعاملات (keywords). في المثال التالي، ستطبع الدالة الوسيط ‎**kwargs‎ الممرر إليها. def print_kwargs(**kwargs): print(kwargs) سنستدعي الآن الدالة ونمرر إليها بعض الوسائط المسماة: def print_kwargs(**kwargs): print(kwargs) print_kwargs(kwargs_1="Shark", kwargs_2=4.5, kwargs_3=True) لننفذ البرنامج أعلاه: python print_kwargs.py سنحصل على المخرجات التالية: {'kwargs_3': True, 'kwargs_2': 4.5, 'kwargs_1': 'Shark'} اعتمادًا على إصدار بايثون 3 الذي تستخدمه، فقد لا يكون القاموس مرتبًا. في بايثون 3.6 وما بعده، ستحصل على أزواج قيمة-مفتاح (key-value) مرتبة، ولكن في الإصدارات السابقة، سيكون ترتيب الأزواج عشوائيًا. سيُنشَأ قاموس يسمى ‎kwargs‎، والذي يمكننا التعامل معه مثل أي قاموس عادي داخل الدالة. لننشئ برنامجًا آخر لإظهار كيفية استخدام ‎**kwargs‎. سننشئ دالة تطبع قاموسًا من الأسماء. أولاً، سنبدأ بقاموس يحتوي اسمين: def print_values(**kwargs): for key, value in kwargs.items(): print("The value of {} is {}".format(key, value)) print_values(my_name="Sammy", your_name="Casey") بعد تنفيذ البرنامج: python print_values.py سنحصل على مايلي: The value of your_name is Casey The value of my_name is Sammy قد لا تكون القواميس مرتَّبة، لذلك قد يظهر الاسم ‎Casey‎ أولاً، وقد يظهر ثانيًا. سنمرر الآن وسائط إضافية إلى الدالة لنرى كيف يمكن أن تقبل ‎**kwargs‎ أيّ عدد من الوسائط: def print_values(**kwargs): for key, value in kwargs.items(): print("The value of {} is {}".format(key, value)) print_values( name_1="Alex", name_2="Gray", name_3="Harper", name_4="Phoenix", name_5="Remy", name_6="Val" ) إذا نفّذنا البرنامج الآن، فسنحصل على المخرجات التالية، والتي قد تكون غير مرتبة: The value of name_2 is Gray The value of name_6 is Val The value of name_4 is Phoenix The value of name_5 is Remy The value of name_3 is Harper The value of name_1 is Alex يتيح لك استخدام ‎**kwargs‎ مرونةً كبيرةً في استخدام الوسائط المسماة. فعند استخدامها، لن نحتاج إلى معرفة مسبقة بعدد الوسائط التي ستمرر إلى الدالة. ترتيب الوسائط عند الخلط بين عدة أنواع من الوسائط داخل دالة، أو داخل استدعاء دالة، يجب أن تظهر الوسائط وفق الترتيب التالي: الوسائط العادية ‎*args‎ الوسائط المسمّاة ‎**kwargs‎ عمليًا، عند الجمع بين المعاملات العادية، والوسيطين ‎*args‎ و ‎**kwargs‎، فينبغي أن تكون وفق الترتيب التالي: def example(arg_1, arg_2, *args, **kwargs): ... وعند الجمع بين المعاملات العادية والمعاملات المسماة و ‎*args‎ و ‎**kwargs‎، ينبغي أن تكون وفق الترتيب التالي: def example2(arg_1, arg_2, *args, kw_1="shark", kw_2="blobfish", **kwargs): ... من المهم أن تأخذ في الحسبان ترتيب الوسائط عند إنشاء الدوال حتى لا تتسبب في إطلاق خطأٍ متعلقٍ بالصياغة. استخدام ‎*args و ‎**kwargs في استدعاءات الدوال يمكننا أيضًا استخدام ‎*args‎ و ‎**kwargs‎ لتمرير الوسائط إلى الدوال. أولاً، دعنا ننظر إلى مثال يستخدم ‎*args‎: def some_args(arg_1, arg_2, arg_3): print("arg_1:", arg_1) print("arg_2:", arg_2) print("arg_3:", arg_3) args = ("Sammy", "Casey", "Alex") some_args(*args) في الدالة أعلاه، هناك ثلاثة معاملات، وهي ‎arg_1‎ و ‎arg_‎ و ‎arg_3‎. ستطبع الدالة كل هذه الوسائط. بعد ذلك أنشأنا متغيرًا، وأَحلنا عليه عنصرًا تكراريًا (في هذه الحالة، صف)، ثم مرَّرنا ذلك المتغير إلى الدالة باستخدام الصياغة النجمية (asterisk syntax). عندما ننفّذ البرنامج باستخدام الأمر ‎python some_args.py‎، سنحصل على المخرجات التالية: arg_1: Sammy arg_2: Casey arg_3: Alex يمكننا أيضًا تعديل البرنامج أعلاه، واستخدام قائمة. سندمج أيضًا ‎*args‎ مع وسيط مسمى: def some_args(arg_1, arg_2, arg_3): print("arg_1:", arg_1) print("arg_2:", arg_2) print("arg_3:", arg_3) my_list = [2, 3] some_args(1, *my_list) إذا نفذنا البرنامج أعلاه، فسنحصل على المخرجات التالية: arg_1: 1 arg_2: 2 arg_3: 3 وبالمثل، يمكن استخدام الوسائط المسماة ‎**kwargs‎ لاستدعاء دالة. سننشئ متغيرًا، ونسند إليه قاموسًا من 3 أزواج مفتاح-قيمة (سنستخدم ‎kwargs‎ هنا، ولكن يمكنك تسميته ما تشاء)، ثم نُمرِّره إلى دالة ذات 3 وسائط: def some_kwargs(kwarg_1, kwarg_2, kwarg_3): print("kwarg_1:", kwarg_1) print("kwarg_2:", kwarg_2) print("kwarg_3:", kwarg_3) kwargs = {"kwarg_1": "Val", "kwarg_2": "Harper", "kwarg_3": "Remy"} some_kwargs(**kwargs) عند تنفيذ البرنامج أعلاه باستخدام الأمر ‎python some_kwargs.py‎، سنحصل على المخرجات التالية: kwarg_1: Val kwarg_2: Harper kwarg_3: Remy خلاصة يمكنك استخدام الصياغتين الخاصتين ‎*args‎ و ‎**kwargs‎ ضمن تَعاريف الدوال لتمرير أيّ عدد تشاء من الوسائط إليها. يُستحسن استخدام ‎*args‎ و ‎**kwargs‎ في المواقف التي تتوقع أن يظل فيها عدد المدخلات في قائمة الوسائط صغيرًا نسبيًا. وضع في ذهنك أن استخدام ‎*args‎ و ‎**kwargs‎ يحسِّن مقروئية الشيفرة، ويسهِّل على المبرمجين، ولكن ينبغي استخدامهما بحذر. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Use *args and **kwargs in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيفية إنشاء الأصناف وتعريف الكائنات في بايثون 3 المقالة السابقة: كيفية تعريف الدوال في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  8. الدالة (funtion) هي كتلة من التعليمات التي تنفِّذ إجراءً ما، ويمكن، بعد تعريفها، إعادة استخدامها في أكثر من موضع. تجعل الدوال الشيفرة تركيبية (modular)، مما يسمح باستخدام نفس الشفرة مرارًا وتكرارًا. تضم بايثون عددًا من الدوال المُضمّنة الشائعة، مثل: ‎print()‎: تطبع كائنًا في الطرفية. ‎int()‎: تحوّل أنواع البيانات النصية أو العددية إلى أعداد صحيحة. ‎len()‎: تعيد طول كائن، وغيرها من الدوال. تتضمن أسماء الدوال الأقواس، وقد تتضمن معاملات أيضًا. في هذا الدرس، سنتعلم كيفية تعريف الدوال، وكيفية استخدامها في البرامج. تعريف الدالة لنبدأ بتحويل البرنامج "مرحبًا بالعالم!" إلى دالة. أنشئ ملفًا نصيًا جديدًا، وافتحه في محرر النصوص المفضل عندك، ثم استدع البرنامج ‎hello.py‎. تُعرَّف الدالة باستخدام الكلمة المفتاحية ‎def‎، متبوعة باسم من اختيارك، متبوعًا بقوسين يمكن أن يَحتويا المعاملات التي ستأخذها الدالة، ثم ينتهي التعريف بنقطتين. في هذه الحالة، سنعرّف دالة باسم ‎hello()‎: def hello(): في الشفرة أعلاه، أعددنا السطر الأول من تعريف الدالة. بعد هذا، سنضيف سطرًا ثانيًا مُزاحًا بأربع مسافات بيضاء، وفيه سنكتب التعليمات التي ستنفّذها الدالة. في هذه الحالة، سنطبع العبارة مرحبا بالعالم في سطر الأوامر: def hello(): print("مرحبا بالعالم") لقد أتممنا تعريف دالتنا، غير أننا إن نَفَّذنا البرنامج الآن، فلن يحدث أيّ شيء، لأننا لم نستدع الدالة؛ لذلك، سنستدع الدالة عبر التعبير ‎hello()‎ خارج كتلة تعريف الدالة: def hello(): print("مرحبا بالعالم") hello() الآن، لننفّذ البرنامج: python hello.py يجب أن تحصل على المخرجات التالية: مرحبا بالعالم! بعض الدوال أكثر تعقيدًا بكثير من الدالة ‎hello()‎ التي عرّفناها أعلاه. على سبيل المثال، يمكننا استخدام for والتعليمات الشرطية، وغيرها داخل كتلة الدالة. على سبيل المثال، تستخدم الدالة المُعرّفة أدناه تعليمة شرطية للتحقق مما إذا كانت المدخلات الممرّرة إلى المتغير ‎name‎ تحتوي على حرف علة (vowel)، ثم تستخدم الحلقة ‎for‎ للمرور (iterate) على الحروف الموجودة في السلسلة النصية ‎name‎. # names() تعريف الدالة def names(): # وإحالة المدخلات عليه name إعداد المتغير name = str(input('أدخل اسمك:')) # يحتوي حرف علة name التحقق من أن if set('aeiou').intersection(name.lower()): print('اسمك يحوي حرف علة') else: print('اسمك لا يحوي حرف علة') # name المرور على حروف for letter in name: print(letter) # استدعاء الدالة names() تستخدم الدالة ‎names()‎ التي عرّفناها أعلاه تعليمة شرطية، وحلقة for، وهذا توضيح لكيفية تنظيم الشفرة البرمجية ضمن تعريف الدالة. يمكننا أيضًا جعل التعليمة الشرطية والحلقة ‎for‎ دالتين منفصلتين. إنّ تعريف الدوال داخل البرامج يجعل الشفرة البرمجية تركيبية (modular)، وقابلة لإعادة الاستخدام، وذلك سيتيح لنا استدعاء نفس الدالة دون إعادة كتابة شيفرتها كل مرة. المعاملات حتى الآن، عرّفنا دالة ذات قوسين فارغين لا تأخذ أيّ وسائط (arguments)، سنتعلم في هذا القسم كيفية تعريف المعاملات (parameters) وتمرير البيانات إلى الدوال. المعامل (parameter) هو كيان مُسمًّى يوضع في تعريف الدالة، ويعرّف وسيطًا (arguments) يمكن أن تقبله الدالة عند استدعائها. دعنا ننشئ برنامجًا صغيرًا يأخذ 3 معاملات ‎x‎ و ‎y‎ و ‎z‎. سننشئ دالة تجمع تلك المعاملات وفق عدة مجموعات ثم تطبع تلك حاصل جمعها. def add_numbers(x, y, z): a = x + y b = x + z c = y + z print(a, b, c) add_numbers(1, 2, 3) مرّرنا العدد ‎1‎ إلى المعامل ‎x‎، و ‎2‎ إلى المعامل ‎y‎، و ‎3‎ إلى المعامل ‎z‎. تتوافق هذه القيم مع المعاملات المقابلة لها في ترتيب الظهور. يُجرِي البرنامج العمليات الحسابية على المعاملات على النحو التالي: a = 1 + 2 b = 1 + 3 c = 2 + 3 تطبع الدالة أيضًا ‎a‎ و ‎b‎ و ‎c‎، وبناءً على العمليات الحسابية أعلاه، فإنّ قيمة ‎a‎ ستساوي العدد ‎3‎، و ‎b‎ ستساوي ‎4‎، و ‎c‎ ستساوي العدد ‎5‎. لننفّذ البرنامج: python add_numbers.py سنحصل على المخرجات التالية: 3 4 5 المعاملات هي وسائط يتم تعريفها عادة كمتغيرات ضمن تعريف الدالة. يمكن تعيين قيم إليها عند تنفيذ التابع بتمرير وسائط إلى الدالة. الوسائط المسمّاة تُستدعى المعاملات بحسب ترتيب ظهورها في تعريف الدالة، أما الوسائط المسماة (Keyword Arguments) فتُستخدَم بأسمائها في استدعاء الدالة. عند استخدام الوسائط المسمّاة، يمكنك استخدام المعاملات بأيّ ترتيب تريد، لأنّ مترجم بايثون سيستخدم الكلمات المفتاحية لمطابقة القيم مع المعاملات. سننشئ دالة تعرض معلومات الملف الشخصي للمستخدم، ونمرر إليها المُعامِلين ‎username‎ (سلسلة نصية)، و ‎followers‎ (عدد صحيح). # تعريف دالة ذات معاملات def profile_info(username, followers): print("Username: " + username) print("Followers: " + str(followers)) داخل تعريف الدالة، وضعنا ‎username‎ و ‎followers‎ بين قوسي الدالة ‎profile_info()‎ أثناء تعريفها. تطبع شفرة الدالة المعلومات الخاصة بالمستخدم على هيئة سلسلة نصية باستخدام المعاملين المُمرّرين. الآن، يمكننا استدعاء الدالة وتعيين المعاملات: def profile_info(username, followers): print("Username: " + username) print("Followers: " + str(followers)) # استدعاء الدالة مع تعيين المعاملات profile_info("sammyshark", 945) # استدعاء الدالة مع تمرير الوسائط المسماة إليها profile_info(username="AlexAnglerfish", followers=342) في الاستدعاء الأول للدالة، مرّرنا اسم المستخدم ‎sammyshark‎، وعدد المتابعين ‎945‎ بالترتيب الوارد في تعريف الدالة. أمّا في الاستدعاء الثاني للدالة، فقد استخدمنا الوسائط المسمّاة، وقمنا بتعيين قيم للوسائط ويمكن عكس الترتيب إن شئنا. لننفذ البرنامج: python profile.py سنحصل على المخرجات التالية: Username: sammyshark Followers: 945 Username: AlexAnglerfish Followers: 342 سنحصل في المخرجات على أسماء المستخدمين، وأعداد المتابعين لكلا المستخدمين. يمكننا تغيير ترتيب المعاملات، كما في المثال التالي: def profile_info(username, followers): print("Username: " + username) print("Followers: " + str(followers)) # تغيير ترتيب المعاملات profile_info(followers=820, username="cameron-catfish") عند تنفيذ البرنامج أعلاه، سنحصل على المخرجات التالية: Username: cameron-catfish Followers: 820 يحافظ تعريف الدالة على نفس ترتيب العبارات في ‎print()‎، لذلك يمكننا استخدام الوسائط المسمّاة بأيّ ترتيب نشاء. القيم الافتراضية للوسائط يمكننا إعطاء قيم افتراضية لواحد أو أكثر من المعاملات. في المثال أدناه، سنعطي للمعامل ‎followers‎ القيمة الافتراضية ‎1‎ لاستعمالها إن لم تُمرَّر هذه القيمة للدالة عند استدعائها: def profile_info(username, followers=1): print("Username: " + username) print("Followers: " + str(followers)) الآن، يمكننا استدعاء الدالة مع تعيين اسم المستخدم فقط، وسيُعيّن عدد المتابعين تلقائيًا ويأخذ القيمة 1. لكن يمكننا تغيير عدد المتابعين إن شئنا. def profile_info(username, followers=1): print("Username: " + username) print("Followers: " + str(followers)) profile_info(username="JOctopus") profile_info(username="sammyshark", followers=945) عندما ننفّذ البرنامج باستخدام الأمر ‎python profile.py‎، سنحصل على المخرجات التالية: Username: JOctopus Followers: 1 Username: sammyshark Followers: 945 تمرير قيم إلى المعاملات الافتراضية سيتخطى القيمة الافتراضية المعطاة في تعريف الدالة. إعادة قيمة كما يمكن تمرير قيم إلى الدالة، فيمكن كذلك أن تنتج الدالة قيمة وتعيدها لم استدعاها. يمكن أن تنتج الدالة قيمة، ويكونُ ذلك عبر استخدام التعليمة ‎return‎، هذه التعليمة اختيارية، وفي حال استخدامها، فستُنهِي الدالة مباشرةً عملها وتوقف تنفيذها، وتُمرَّر قيمة التعبير الذي يعقُبها إلى المُستدعي (caller). إذا لم يلي التعليمة ‎return‎ أي شيء، فستُعيد الدالة القيمةَ ‎None‎. حتى الآن، استخدمنا الدالة ‎print()‎ بدلاً من ‎return‎ في دوالنا لطباعة شيء بدلًا من إعادته. لننشئ برنامجًا يعيد متغيرًا بدلًا من طباعته الآن. في ملف نصي جديد يسمى ‎square.py‎، سننشئ برنامجًا يحسب مربع المعامل ‎x‎، ويُحيل الناتج إلى المتغير ‎y‎، ثم يعيده. سنطبع المتغير ‎result‎، والذي يساوي ناتج تنفيذ الدالة ‎square(3)‎. def square(x): y = x ** 2 return y result = square(3) print(result) لننفّذ البرنامج: python square.py سنحصل على المخرجات التالية: 9 مخرجات البرنامج هي العدد الصحيح ‎9‎ الذي أعادته الدالة وهو ما نتوقعه لو طلبنا من بايثون حساب مربع العدد 3. لفهم كيفية عمل التعليمة ‎return‎، يمكننا تعليق التعليمة ‎return‎: def square(x): y = x ** 2 # return y result = square(3) print(result) الآن، لننفّذ البرنامج مرة أخرى: python square.py سنحصل على الناتج التالي: None بدون استخدام التعليمة ‎return‎، لا يمكن للبرنامج إعادة أيّ قيمة، لذلك تُعاد القيمة الافتراضية ‎None‎. إليك مثال آخر، في برنامج ‎add_numbers.py‎ أعلاه، سنستبدل بالتعليمة ‎return‎ الدالة ‎print()‎. def add_numbers(x, y, z): a = x + y b = x + z c = y + z return a, b, c sums = add_numbers(1, 2, 3) print(sums) خارج الدالة، أحلنا إلى المتغير ‎sums‎ نتيجة استدعاء الدالة بالوسائط ‎1‎ و ‎2‎ و ‎3‎ كما فعلنا أعلاه ثم طبعنا قيمته. فلننفّذ البرنامج مرة أخرى: python add_numbers.py والناتج سيكون: (3, 4, 5) لقد حصلنا على الأعداد ‎3‎ و ‎4‎ و ‎5‎ وهي نفس المخرجات التي تلقيناها سابقًا عندما استخدمنا الدالة ‎print()‎ في الدالة. هذه المرة تمت إعادتها على هيئة صف لأنّ التعبير المرافق للتعليمة ‎return‎ يحتوي على فاصلة واحدة على الأقل. تُوقَف الدوال فورًا عندما تصل إلى التعليمة ‎return‎، سواء أعادت قيمة، أم لم تُعِد. def loop_five(): for x in range(0, 25): print(x) if x == 5: # x == 5 إيقاف الدالة عند return print("This line will not execute.") loop_five() يؤدي استخدام التعليمة ‎return‎ داخل الحلقة ‎for‎ إلى إنهاء الدالة، وبالتالي لن يتم تنفيذ السطر الموجود خارج الحلقة. لو استخدمنا بدلًا من ذلك break، فسيُنفّذ السطر ‎print()‎ الأخير من المثال السابق. نعيد التذكير أنَّ التعليمة ‎return‎ تنهي عمل الدالة، وقد تعيد قيمة إذا أعقبها تعبير. استخدام ‎main()‎ دالةً رغم أنه يمكنك في بايثون استدعاء الدالة في أسفل البرنامج، وسيتم تنفيذها (كما فعلنا في الأمثلة أعلاه)، فإنّ العديد من لغات البرمجة (مثل C++‎ و Java) تتطلب الدالة ‎main‎. إنّ تضمين دالة ‎main()‎، وإن لم يكن إلزاميًا، يمكن أن يهيكل برامج بيثون بطريقة منطقية، بحيث تضع أهم مكونات البرنامج في دالة واحدة. كما يمكن أن يجعل البرنامج أكثر مقروئية للمبرمجين غير البايثونيِّين. سنبدأ بإضافة دالة ‎main()‎ إلى برنامج ‎hello.py‎ أعلاه. سنحتفظ بالدالة ‎hello()‎، ثم نعرّف دالة ‎main()‎: def hello(): print("مرحبا بالعالم") def main(): ضمن الدالة ‎main()‎، سندرج الدالة ‎print()‎، والتي ستعُلِمنا بأننا في الدالة ‎main()‎. أيضًا سنستدعي الدالة ‎hello()‎ داخل ‎main()‎: def hello(): print("مرحبا بالعالم") def main(): print("هذه هي الدالة الرئيسية") hello() أخيرًا، في أسفل البرنامج، سنستدعي الدالة ‎main()‎: def hello(): print("مرحبا بالعالم") def main(): print("هذه هي الدالة الرئيسية.") hello() main() الآن يمكننا تنفيذ برنامجنا: python hello.py وسنحصل على المخرجات التالية: هذه هي الدالة الرئيسية. مرحبا بالعالم! لمّا استدعينا الدالة ‎hello()‎ داخل ‎main()‎، ثم نفّذنا الدالة ‎main()‎ وحدها، فقد طُبع النص مرحبا بالعالم مرة واحدة فقط، وذلك عقب السلسلة النصية التي أخبرتنا بأننا في الدالة الرئيسية. سنعمل الآن مع دوال مُتعدِّدة، لذلك من المستحسن أن تراجع نطاقات المتغيرات في المقالة: كيفية استخدام المتغيرات في بايثون. إذا عرّفت متغيرًا داخل دالة، فلا يمكنك أن تستخدم ذلك المتغير إلا ضمن تلك الدالة. لذا، إن أردت استخدام متغير ما في عدة دوال، فقد يكون من الأفضل الإعلان عنه متغيرًا عامًا (global variable). في بايثون، يعدُّ ‎'__main__'‎ اسم النطاق الذي ستُنفَّذ فيه الشيفرة العليا (top-level code). عند تنفيذ برنامج من الدخل القياسي (standard input)، أو من سكربت، أو من سطر الأوامر، سيتم ضبط ‎__name__‎ عند القيمة ‎'__main__'‎. لهذا السبب، اصطلح مطورو بايثون على استخدام الصياغة التالية: if __name__ == '__main__': # الشفرة التي ستُنفّذ لو كان هذا هو البرنامج الرئيسي هذه الصياغة تتيح استخدام ملفات بايثون إما: برامج رئيسية، مع تنفيذ ما يلي التعليمة ‎if‎، أو وحدات عادية، مع عدم تنفيذ ما يتبع التعليمة ‎if‎. سيتم تنفيذ الشفرة غير المُتضمّنة في العبارة if __name__ == '__main__'‎:‎ عند التنفيذ. إذا كنت تستخدم ملف بايثون كوحدة، فسيتم أيضًا تنفيذ الشفرة البرمجية غير المُتضمّنة في هذه العبارة عند استيراد ذلك الملف. دعنا نوسع البرنامج ‎names.py‎ أعلاه، سننشئ ملفا جديدًا يسمى ‎more_names.py‎. سنعلن في هذا البرنامج عن متغير عام، ونعدِّل الدالة ‎names()‎ الأصليَّة بشكل نقسِّم فيه التعليمات إلى دالّتين منفصلتين. ستتحقق الدالة الأولى ‎has_vowel()‎ مما إذا كانت السلسلة النصية ‎name‎ تحتوي على حرف علة (vowel). وتطبع الدالة الثانية ‎print_letters()‎ كل حرف من السلسلة النصية ‎name‎. # الإعلان عن متغير عام لاستخدامه في جميع الدوال name = str(input('أدخل اسمك:')) # يحتوي حرف علة name تعريف دالة للتحقق من أن def has_vowel(): if set('aeiou').intersection(name.lower()): print('اسمك يحتوي حرف علة') else: print('اسمك لا يحتوي حرف علة') # name المرور على حروف def print_letters(): for letter in name: print(letter) بعد ذلك، دعنا نعرّف الدالة ‎main()‎ التي سَتستدعي كلا الدّالتين ‎has_vowel()‎ و ‎print_letters()‎. # الإعلان عن متغير عام لاستخدامه في جميع الدوال name = str(input('أدخل اسمك:')) # يحتوي حرف علة name تعريف دالة للتحقق من أنّ def has_vowel(): if set('aeiou').intersection(name.lower()): print('اسمك يحتوي حرف علة') else: print('اسمك لا يحتوي حرف علة') # name المرور على حروف def print_letters(): for letter in name: print(letter) # التي ستستدعي بقية الدوال main تعريف الدالة def main(): has_vowel() print_letters() أخيرًا، سنضيف العبارة ‎if __name__ == '__main__':‎ في أسفل الملف. لقد وضعنا جميع الدوال التي نودّ تنفيذها في الدالة ‎main()‎، لذا سنستدعي الدالة ‎main()‎ بعد العبارة ‎if‎. # الإعلان عن متغير عام لاستخدامه في جميع الدوال name = str(input('أدخل اسمك:')) # يحتوي حرف علة name تعريف دالة للتحقق من أن def has_vowel(): if set('aeiou').intersection(name.lower()): print('اسمك يحتوي حرف علة') else: print('اسمك لا يحتوي حرف علة') # name المرور على حروف def print_letters(): for letter in name: print(letter) # التي ستستدعي بقية الدوال main تعريف الدالة def main(): has_vowel() print_letters() # main() تنفيذ الدالة if __name__ == '__main__': main() يمكننا الآن تنفيذ البرنامج: python more_names.py سيعرض هذا البرنامج نفس المخرجات التي عرضها البرنامج ‎names.py‎، بيْد أنّ الشفرة هنا أكثر تنظيمًا، ويمكن استخدامها بطريقة تركيبية (modular). إذا لم ترغب في الإعلان عن الدالة ‎main()‎، يمكنك بدلاً من ذلك إنهاء البرنامج كما يلي: ... if __name__ == '__main__': has_vowel() print_letters() يؤدي استخدام ‎main()‎ كدالة، واستخدام العبارة ‎if __name__ == '__main__':‎ إلى تنظيم الشيفرة البرمجية بطريقة منطقية، وجعلها أكثر مقروئية وتراكبية. خلاصة الدوال هي كتل من التعليمات البرمجية التي تُنفِّذ إجراءات معيّنة داخل البرنامج، كما تساعد على جعل الشفرة تركيبية، وقابلة لإعادة الاستخدام بالإضافة إلى أنها تنظمها وتسهل من قراءتها. لمعرفة المزيد حول كيفية جعل الشفرة تركيبية، يمكنك قراءة المقالة التالية: كيفية كتابة الوحدات في بايثون 3. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة -وبتصرّف- للمقال How To Define Functions in Python 3 لصاحبته Lisa Tagliaferri اقرأ أيضا المقالة التالية: كيفية استخدام ‎args و ‎*kwargs في بايثون 3 المقالة السابقة: كيفية استخدام تعابير break و continue و pass عند التعامل مع حلقات التكرار في بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  9. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (scripting) والأتمتة وتحليل البيانات وتعلم الآلة (machine learning) والتطوير الخلفي (back-end development). ظهرت بايثون سنة 1991، واستوحي اسمها من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وبسيطة الإعداد، وجعل طريقة كتابتها مباشرة، مع توفير تقرير مباشر عند حدوث أخطاء. وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعدُّ مستقبل بايثون. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 في ويندوز 10، وتثبيت بيئة برمجة عبر سطر الأوامر. المتطلبات المسبقة لمتابعة هذه المقالة، يجب أن تملك جهازًا عليه نظام ويندوز 10 متصل بالشبكة مع صلاحيات مدير (administrative access). الخطوة الأولى: فتح وإعداد PowerShell سنجري معظم أطوار التثبيت والإعدادات عبر سطر الأوامر، والذي هو طريقةٌ غيرُ رسوميةٍ للتعامل مع الحاسوب، فبدلًا من الضغط على الأزرار، ستكتب نصًّا وتعطيه للحاسوب لينفذه، وسيُظهِر لك ناتجًا نصيًا أيضًا. يمكن أن يساعدك سطر الأوامر على تعديل أو أتمتة مختلف المهام التي تنجزها على الحاسوب يوميًا، وهو أداةٌ أساسيةٌ لمطوري البرمجيات. PowerShell هي برنامج من ميكروسوفت يوفر واجهة سطر الأوامر. يمكن إجراء المهام الإدارية عبر تنفيذ الأصناف cmdlets، والتي تُنطَق "command-lets"، وهي أصناف متخصصة من الإطار ‎.NET يمكنها تنفيذ العمليات. جُعِلت PowerShell مفتوحة المصدر منذ أغسطس 2016، وصارت متوفرة الآن عبر ويندوز و أنظمة يونكس (بما في ذلك ماك ولينكس). ستعثر على PowerShell بالنقر الأيمن على أيقونة Start في الركن الأيسر السفلي من الشاشة. عندما تنبثق القائمة، انقر على "Search"، ثم اكتب "PowerShell" في شريط البحث. عند تقديم خيارات لك، انقر بالزر الأيمن على تطبيق سطح المكتب "Windows PowerShell". اختر "Run as Administrator". عندما يظهر مربع حوار يسألك "Do you want to allow this app to make changes to your PC?"، انقر على "Yes". بمجرد إتمام ذلك، سترى واجهة نصية تبدو كما يلي: يمكننا تبديل مجلد النظام عن طريق كتابة الأمر التالي: cd ~ بعد ذلك سننتقل إلى المجلد PS C:\Users\Sammy. لمتابعة عملية التثبيت، سنعدّ بعض الأذونات من خلال PowerShell. تم إعداد PowerShell لتعمل في الوضع الأكثر أمانًا بشكل افتراضي، هناك عدة مستويات للأذونات، والتي يمكنك إعدادها باعتبارك مديرًا (administrator): Restricted: تمثل سياسة التنفيذ الافتراضية، وبموجب هذا الوضع، لن تتمكن من تنفيذ السكربتات، وستعمل PowerShell كصدفة تفاعلية (interactive shell) وحسب. AllSigned: ستمكّنك من تنفيذ جميع السكربتات وملفات الإعداد المُوقّعة من قبل جهة موثوقة، مما يعني أنه من المحتمل أن تعرّض جهازك لخطر تنفيذ سكربتات ضارة إن كانت موقعة من قبل جهة موثوقة. RemoteSigned: ستمكّنك من تنفيذ السكربتات وملفات الإعداد المُنزّلة من الشبكة، والمُوقعة من قبل جهة موثوقة، مما يعني أنه من المحتمل أن تعرّض جهازك لخطر تنفيذ سكربتات ضارة إن كانت تلك السكربتات الموثوقة ضارة. Unrestricted: تسمح بتنفيذ جميع السكربتات وملفات الإعداد المُنزّلة من الشبكة بمجرد أن تؤكد أنك تدرك أنّ الملف مُنزّل من الشبكة. في هذه الحالة، التوقيعات الرقمية غير لازمة، مما يعني أنه من المحتمل أن تعرّض جهازك لخطر تنفيذ سكربتات غير موثوقة منزلة من الشبكة قد تكون ضارة. سنستخدم سياسة التنفيذ RemoteSigned لتعيين الإذن للمستخدم الحالي، وهكذا سنسمح لبرنامج PowerShell بقبول السكربتات المُنزّلة التي نثق بها، ودون خفض كل دفاعاتنا وجعل الأذونات هشة كما هو الحال مع سياسة التنفيذ Unrestricted. سنكتب في PowerShell: Set-ExecutionPolicy -Scope CurrentUser ستطالبك PowerShell بتحديد سياسة التنفيذ، وبما أننا نريد استخدام RemoteSigned، فسنكتب: RemoteSigned بمجرد الضغط على الزر enter، ستُسأل عما إن كنت نريد تغيير سياسة التنفيذ. اكتب الحرف y لاختيار "نعم"، واعتماد التغييرات. يمكننا التحقق من نجاح العملية عن طريق طلب الأذونات الحالية في الجهاز عبر كتابة: Get-ExecutionPolicy -List ستحصل على مخرجات مشابهة لما يلي: Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Undefined CurrentUser RemoteSigned LocalMachine Undefined هذا يؤكد أنّ المستخدم الحالي يمكنه تنفيذ السكربتات الموثوقة التي تم تنزيلها من الشبكة. يمكننا الآن تنزيل الملفات التي سنحتاج إليها لإعداد بيئة برمجة بايثون. الخطوة الثانية: تثبيت Chocolatey مدير الحزم (package manager) هو مجموعة من أدوات البرمجيات التي تعمل على أتمتة عمليات التثبيت، بما في ذلك التثبيت الأولي للبرامج، وترقيتها، وإعدادها، وإزالتها عند الحاجة. تحفظ هذه الأدوات التثبيتات في موقع مركزي، ويمكنها صيانة جميع حزم البرامج على النظام وفق تنسيقات (formats) معروفة. Chocolatey هي مدير حزم تعمل من سطر الأوامر، تم تصميمها لنظام ويندوز، وتحاكي apt-get الخاصة بلينكس. متوفرة كإصدار مفتوح المصدر، ويمكنها مساعدتك Chocolatey على تثبيت التطبيقات والأدوات بسرعة. سنستخدمها لتنزيل ما نحتاج إليه لبيئتنا التطويرية. قبل تثبيت السكربت، دعنا نقرأه للتأكد من أنّ التغييرات التي سيجريها على الجهاز مقبولة. سنستخدم إطار العمل ‎.NET لتنزيل وعرض السكربت Chocolatey في نافذة الطرفية. سننشئ كائنًا WebClient يُسمى ‎$script‎‎ (يمكنك تسميته كما تريد طالما ستستخدم المحرف $ في البداية)، والذي يشارك إعدادات الاتصال بالشبكة مع المتصفح Internet Explorer: $script = New-Object Net.WebClient دعنا نلقي نظرة على الخيارات المتاحة لنا من خلال توصيل الكائن إلى الصنف Get-Member لإعادة جميع الأعضاء (الخاصيات والتوابع) الخاصة بكائن WebClient: $script | Get-Member سنحصل على المخرجات التالية: . . . DownloadFileAsync Method void DownloadFileAsync(uri address, string fileName), void DownloadFileAsync(ur... DownloadFileTaskAsync Method System.Threading.Tasks.Task DownloadFileTaskAsync(string address, string fileNa... DownloadString Method string DownloadString(string address), string DownloadString(uri address) # التابع الذي سنستخدمه DownloadStringAsync Method void DownloadStringAsync(uri address), void DownloadStringAsync(uri address, Sy... DownloadStringTaskAsync Method System.Threading.Tasks.Task[string] DownloadStringTaskAsync(string address), Sy… . . . عند النظر إلى المخرجات، يمكننا تحديد التابع DownloadString الذي يمكننا استخدامه لعرض محتوى السكربت والتوقيع في نافذة PowerShell كما يلي: $script.DownloadString("https://chocolatey.org/install.ps1") بعد مطالعة السكربت، يمكننا تثبيت Chocolatey عن طريق كتابة ما يلي في PowerShell: iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex تسمح لنا iwr أو Invoke-WebRequest التي تخص cmdlet باستخراج البيانات من الشبكة. سيؤدي هذا إلى تمرير السكربت إلى iex أو Invoke-Expression، والذي سينفذ محتويات السكربت، وتنفيذ سكربت التثبيت لمدير الحزم Chocolatey. اسمح لبرنامج PowerShell بتثبيت Chocolatey. بمجرد تثبيته بالكامل، يمكننا البدء في تثبيت أدوات إضافية باستخدام الأمر choco. إن احتجت إلى ترقية Chocolatey مستقبلًا، يمكنك تنفيذ الأمر التالي: choco upgrade chocolatey بعد تثبيت مدير الحزم، يمكننا متابعة تثبيت ما نحتاجه لبيئة البرمجة خاصتنا. المرحلة الثالثة: تثبيت محرر النصوص nano (اختياري) سنثبّت الآن nano، وهو محرر نصوص يستخدم واجهة سطر الأوامر، والذي يمكننا استخدامه لكتابة البرامج مباشرة داخل PowerShell. هذه ليست خطوة إلزامية، إذ يمكنك بدلاً من ذلك استخدام محرر نصوص بواجهة مستخدم رسومية مثل Notepad، لكن ميزة nano أنه سيُعوِّدك على استخدام PowerShell. دعنا نستخدم Chocolatey لتثبيت nano: choco install -y nano الخيار ‎-y يعني أنَّك توافق على تنفيذ السكربت تلقائيًا دون الحاجة إلى تأكيد. بعد تثبيت nano، سنكون قادرين على استخدام الأمر nano لإنشاء ملفات نصية جديدة، وسنستخدمه بعد حين لكتابة أول برامجنا في بايثون. المرحلة الرابعة: تثبيت بايثون 3 مثلما فعلنا مع nano أعلاه، سنستخدم Chocolatey لتثبيت بايثون 3: choco install -y python3 ستثبّت PowerShell الآن بايثون 3، مع عرض بعض المخرجات أثناء العملية. بعد اكتمال العملية، سترى المخرجات التالية: Environment Vars (like PATH) have changed. Close/reopen your shell to See the changes (or in powershell/cmd.exe just type 'refreshenv'). The install of python3 was successful. Software installed as 'EXE', install location is likely default. Chocolatey installed 1/1 packages. 0 packages failed. See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log). بعد الانتهاء من التثبيت، ستحتاج إلى التحقق من أنّ بايثون مثبّتة وجاهزة للعمل. لرؤية التغييرات، استخدم الأمر refreshenv أو أغلق PowerShell ثم أعد فتحها بصلاحيات مدير النظام، ثم تحقق من إصدار بايثون على جهازك: python -V ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون المثبّت. Python 3.7.0 سيتم تثبيت، إلى جانب بايثون، الأداة pip، وهي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تعلم المزيد عن الوحدات والحزم التي يمكنك تثبيتها بالأداة pip بقراءة المقالة كيفية استيراد الوحدات في بايثون 3 من هذه السلسلة. سنحدّث pip عبر الأمر التالي: python -m pip install --upgrade pip يمكننا استدعاء بايثون من Chocolatey عبر الأمر python. سنستخدم الراية ‎-m لتنفيذ الوحدة كأنها سكربت، وإنهاء قائمة الخيارات، ومن ثمّ نستخدم pip لتثبيت الإصدار الأحدث. بعد تثبيت بايثون وتحديث pip، فنحن جاهزون لإعداد بيئة افتراضية لمشاريع التطوير خاصتنا. الخطوة الخامسة: إعداد بيئة افتراضية الآن بعد تثبيت Chocolatey و nano وبايثون، يمكننا المضي قدمًا لإنشاء بيئة البرمجة خاصتنا عبر الوحدة venv. تُمكِّنك البيئات الافتراضية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه ستكون له اعتماديّاته (dependencies) الخاصة به، والتي لن تؤثِّر على غيره من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون، وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. يمكنك ضبط أيّ عددٍ تشاء من البيئات الافتراضية، وكل بيئة ستكون ممثلة بمجلد في حاسوبك يحتوي على عدد من السكربتات. اختر المجلد الذي تريد أن تضع فيه بيئات بايثون، أو يمكنك إنشاء مجلد جديد باستخدام الأمر mkdir كما يلي: mkdir environments cd environments بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، تستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر التالي: python -m venv my_env باستخدام الأمر python، سننفّذ الوحدة venv لإنشاء البيئة الافتراضية التي أطلقنا عليها في هذه الحالة my_env. ستنشئ venv مجلدًا جديدًا يحتوي على بعض العناصر التي يمكن عرضها باستخدام الأمر ls: ls my_env سنحصل على المخرجات التالية: Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 8/22/2016 2:20 PM Include d----- 8/22/2016 2:20 PM Lib d----- 8/22/2016 2:20 PM Scripts -a---- 8/22/2016 2:20 PM 107 pyvenv.cfg تعمل هذه الملفات مع بعضها لضمان أنَ تكون مشاريعك معزولةٌ عن سياق الآلة المحلية، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى الحزمٍ التي يحتاجها. عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر التالي الذي سيُنفِّذ سكربت التفعيل في المجلد Scripts: my_env\Scripts\activate يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها my_env. (my_env) PS C:\Users\Sammy\Environments> تتيح لنا هذه البادئة معرفة أنّ البيئة my_env مفعّلة حاليًا، وهذا يعني أننا لن سنستخدم إلا إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة. الخطوة الثالثة: إنشاء برنامج بسيط بعد أن أكملنا ضبط بيئتنا الافتراضية، لننشِئ برنامجًا بسيطًا يعرض العبارة «مرحبا بالعالم!»، وبهذا سنتحقق من أنَّ البيئة تعمل بالشكل الصحيح، ولكي تتعوّد على إنشاء برامج بايثون إن كنتَ وافدًا جديدًا على اللغة. علينا أولًا تشغيل المحرر nano وإنشاء ملف جديد: (my_env) PS C:\Users\Sammy> nano hello.py بعد فتح الملف في نافذة الطرفية، سنكتب البرنامج الخاص بنا: print("مرحبا بالعالم!") أغلق محرر nano بالضغط على Ctrl+x ثم اضغط على y عندما يسألك عن حفظ الملف. بعد أن يُغلَق المحرر nano وتعود إلى سطر الأوامر، حاول تنفيذ البرنامج: (my_env) PS C:\Users\Sammy> python hello.py سيؤدي برنامج hello.py الذي أنشأتَه إلى طباعة الناتج التالي في الطرفية: مرحبا بالعالم! للخروج من البيئة، اكتب الأمر deactivate وستعود إلى مجلدك الأصلي. الخلاصة تهانينا! لقد ضبطتَ الآن بيئة تطويرٍ للغة بايثون 3 في نظام ويندوز 10، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق. ترجمة -وبتصرّف- للمقال How To Install Python 3 and Set Up a Local Programming Environment on windows 10 لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيف تكتب أول برنامج لك المقالة السابقة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  10. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (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 اقرأ أيضًا المقالة التالية: كيف تكتب أول برنامج لك المقالة السابقة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  11. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (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 اقرأ أيضًا المقالة التالية: كيف تكتب أول برنامج لك المقالة السابقة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  12. بايثون هي لغةٌ سهلة القراءة ومتنوعة ومتعددة الاستخدامات، وغالبًا ما تُستخدم في كتابة السكربتات (scripting) والأتمتة وتحليل البيانات وتعلم الآلة (machine learning) والتطوير الخلفي (back-end development). ظهرت بايثون سنة 1991، واستوحي اسمها من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وبسيطة الإعداد، وجعل طريقة كتابتها مباشرة، مع توفير تقرير مباشر عند حدوث أخطاء. وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. إصدار بايثون 3 هو الإصدار الحالي من اللغة ويُعدُّ مستقبل بايثون. سيُرشِدُك هذا الدرس خطوةً بخطوة إلى كيفية تثبيت بايثون 3 على CentOS 7، وتثبيت بيئة برمجة عبر سطر الأوامر. المتطلبات المسبقة لمتابعة هذه المقالة، يجب أن تملك صلاحيات مستخدم أساسي غير جذري (non-root superuser) على نظام CentOS 7 متصل بالشبكة. إذا لم تكن لك خبرة في التعامل مع بيئة النافذة الطرفية، فيمكنك مطالعة المقالة "مدخل إلى طرفيّة لينكس Linux Terminal". الخطوة الأولى: تحضير النظام سنُثبِّت ونضبط بايثون عبر سطر الأوامر، إن كان نظام CentOS 7 يبدأ بسطح مكتب ذي واجهة مستخدم رسومية (GUI)، فيمكنك الدخول إلى سطر الأوامر بفتح القائمة، والدخول إلى Applications ثم Utilities ثم النقر على Terminal. هنالك مقالات في أكاديمية حسوب (كدرس مدخل إلى طرفيّة لينكس Linux Terminal) ستعلمك أساسيات سطر الأوامر، وهنالك كتاب «سطر أوامر لينكس» الذي يُعدُّ مرجعًا لطريقة التعامل مع سطر الأوامر. سنستخدم أداة إدارة الحزم مفتوحة المصدر yum (اختصار للعبارة Yellowdog Updater Modified). هذه أداة شائعة الاستخدام لإدارة الحزم على أنظمة لينكس المستندة إلى Red Hat، مثل CentOS. ستتيح لك هذه الأداة تثبيت الحزم وتحديثها بسهولة، وكذلك إزالة الحزم من الجهاز. قبل أن نبدأ التثبيت، دعنا نتأكد من أنّ لدينا أحدث إصدار من yum عبر تنفيذ الأمر التالي: sudo yum -y update الخيار ‎-y يعني أنَّك تدرك أنّك تحدث تغييرات، وذلك لمنع الطرفية من طلب تأكيد قبل تنفيذ الأمر. سنثبّت الآن yum-utils، وهي حزمة من الأدوات والإضافات التي توسّع yum وتكمّلها: sudo yum -y install yum-utils أخيرًا، سنثبّت أدوات التطوير الخاصة بنظام CentOS، والتي تُستخدم لإنشاء وتصريف (compile) البرامج من الشيفرة المصدرية: sudo yum -y groupinstall development بمجرد تثبيت كل شيء، فنحن جاهزون لتثبيت بايثون 3. المرحلة الثانية: تثبيت وإعداد بايثون 3 نظام CentOS مشتق من RHEL (اختصار للجملة Red Hat Enterprise Linux) ، والذي يركز على الثبات والاستقرار. ولهذا السبب، فلن تجد في هذا النظام إلا الإصدارات المستقرة والمُختبرة من التطبيقات والحزم القابلة للتنزيل، لذلك لن تجد على CentOS إلا الإصدار بايثون 2. نظرًا لأننا نرغب في تثبيت أحدث إصدار مستقر من بايثون 3، فسنحتاج إلى تثبيت IUS (اختصار للعبارة Inline with Upstream Stable)، وهو مشروع مفتوح المصدر. يوفر IUS حزم Red Hat Package Manager ‏(RPM) لبعض الإصدارات الحديثة من البرامج المحددة. سنثبت IUS عبر yum: sudo yum -y install https://centos7.iuscommunity.org/ius-release.rpm بعد الانتهاء من تثبيت IUS، يمكننا تثبيت أحدث إصدار من بايثون: sudo yum -y install python36u بعد إكمال العملية، يمكننا التحقق من نجاح عملية التثبيت بطلب إصدار بايثون بكتابة: python3.6 -V ستحصل على مخرجات في نافذة الطرفية والتي ستريك إصدار بايثون المثبّت. قد يختلف الرقم بناءً على النسخة المثبتة في توزيعتك، لكن يجب أن يكون شبيهًا بما يلي: Python 3.6.1 لإدارة الحزم البرمجية الخاصة ببايثون، سنثبّت pip، وهي أداةٌ تعمل مع لغة بايثون تُثَبِّت وتدير الحزم البرمجية التي قد نحتاج إلى استخدامها في تطوير مشاريعنا. يمكنك تعلم المزيد عن الوحدات والحزم التي يمكنك تثبيتها بالأداة pip بقراءة المقالة كيفية استيراد الوحدات في بايثون 3 من هذه السلسلة: sudo yum -y install python36u-pip يمكن تثبيت حزم بايثون بكتابة ما يلي: sudo pip3.6 install package_name حيث عليك وضع اسم الحزمة أو المكتبة التابعة لبايثون مكان package_name مثل Django لتطوير الويب، أو NumPy لإجراء الحسابات العلمية. لذا، إن شئتَ تنزيل NumPy فيمكنك تنفيذ الأمر pip3.6 install numpy. أخيرًا، سنحتاج إلى تثبيت الحزمة python36u-devel الخاصة بـ IUS، والتي توفر لنا مكتبات وملفات ترويسية (header files) ضرورية للتطوير على بايثون 3: sudo yum -y install python36u-devel سنستخدم الوحدة venv لإعداد «بيئة افتراضية» (virtual environment) لمشاريعنا. الخطوة الثالثة: إعداد بيئة افتراضية الآن بعد أن ثبّتنا بايثون وأعددنا النظام، يمكننا المضي قدمًا لإنشاء بيئة البرمجة التي سنعمل فيها باستخدام venv. تُمكِّنك البيئات الافتراضية من إنشاء مساحة معزولة في حاسوبك مخصصة لمشاريع بايثون، مما يعني أنَّ كل مشروع تعمل عليه ستكون له اعتماديّاته (dependencies) الخاصة به، والتي لن تؤثِّر على غيره من المشاريع. يوفِّر لنا ضبط بيئةٍ برمجيةٍ تحكمًا أكبر بمشاريع بايثون، وإمكانية التعامل مع إصداراتٍ مختلفةٍ من حزم بايثون. وهذا مهمٌ كثيرًا عندما تتعامل مع الحزم الخارجية. يمكنك ضبط أيّ عددٍ تشاء من البيئات الافتراضية، وكل بيئة ستكون ممثلة بمجلد في حاسوبك يحتوي على عدد من السكربتات. بعد إتمام التثبيت، فنحن جاهزون لإنشاء البيئات الافتراضية، يمكننا الآن إما اختيار مجلد نضع فيه بيئات بايثون، أو إنشاء مجلد جديد باستخدام الأمر mkdir كما يلي: mkdir environments cd environments بعد أن انتقلتَ إلى المجلد الذي تريد احتواء البيئات فيه، تستطيع الآن إنشاء بيئة جديدة بتنفيذ الأمر الآتي: python3.6 -m venv my_env سيُنشِئ الأمر pyvenv مجلدًا جديدًا فيه بعض الملفات التي يمكن عرضها باستخدام الأمر ls: ls my_env ستظهر لك مخرجات شبيهة بالمخرجات التالية: bin include lib lib64 pyvenv.cfg تعمل هذه الملفات مع بعضها لضمان أنَ تكون مشاريعك معزولةٌ عن سياق الآلة المحلية، لكي لا تختلط ملفات النظام مع ملفات المشاريع. وهذا أمرٌ حسنٌ لإدارة الإصدارات ولضمان أنَّ كل مشروع يملك وصولًا إلى الحزمٍ التي يحتاجها. عليك تفعيل البيئة لاستخدامها، وذلك بكتابة الأمر التالي الذي سيُنفِّذ سكربت التفعيل: source my_env/bin/activate يجب أن تظهر الآن سابقةٌ (prefix) في المِحث (prompt) والتي هي اسم البيئة المستخدمة، وفي حالتنا هذه يكون اسمها my_env: (my_env) sammy@locahost:~/environments$ ستسمح لك السابقة بمعرفة أنَّ البيئة my_env مفعلة حاليًا، وهذا يعني أننا سنستخدم إعدادات وحزم هذه البيئة عند إنشاء مشاريع جديدة. ملاحظة: يمكنك داخل البيئة الافتراضية أن تستخدم الأمر python بدلًا من python3.6 والأمر pip بدلًا من pip3.6 إن شئتَ. أما إذا كنتَ تستخدم بايثون 3 خارج البيئة الافتراضية، فيجب عليك حينها استخدام python3.6 و pip3.6 حصرًا. يجب أن تكون بيئتك الافتراضية جاهزةً للاستخدام بعد اتباعك للخطوات السابقة. الخطوة الرابعة: إنشاء برنامج بسيط بعد أن أكملنا ضبط بيئتنا الافتراضية، لننشِئ برنامجًا بسيطًا يعرض العبارة «مرحبا بالعالم!»، وبهذا سنتحقق من أنَّ البيئة تعمل بالشكل الصحيح، ولكي تتعوّد على إنشاء برامج بايثون إن كنتَ وافدًا جديدًا على اللغة. علينا أولًا تشغيل محرر ملفات نصية لإنشاء ملف جديد، وليكن المحرر vim: (my_env) sammy@localhost:~/environments$ nano hello.py بعد فتح الملف في نافذة الطرفية، اكتب الحرف i للدخول إلى وضع الإدراج (insert mode)، بعدها يمكننا كتابة البرنامج: print("مرحبا بالعالم!") الآن اضغط على الزر ESC للخروج من وضع الإدراج. بعد ذلك ، اكتب ‎ ثم ENTER لحفظ الملف وإغلاقه. نحن جاهزون الآن لتنفيذ البرنامج: (my_env) sammy@localhost:~/environments$ python hello.py سيؤدي برنامج hello.py الذي أنشأتَه إلى طباعة الناتج التالي في الطرفية: مرحبا بالعالم! للخروج من البيئة، اكتب الأمر deactivate وستعود إلى مجلدك الأصلي. الخلاصة تهانينا! لقد ضبطتَ الآن بيئة تطويرٍ للغة بايثون 3 في CentOS 7، حان الآن الوقت للتعمق بلغة بايثون وإنشاء برامج رائعة! بالتوفيق. ترجمة -وبتصرّف- للمقال How To Install Python 3 and Set Up a Local Programming Environment on CentOS 7‎ لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: كيف تكتب أول برنامج لك المقالة السابقة: اعتبارات عملية للاختيار ما بين بايثون 2 و بايثون 3 المرجع الشامل إلى تعلم لغة بايثون
  13. Python هي لغةٌ سهلة القراءة للغاية ومتنوعة ومتعددة الاستخدامات، واسمها مستوحى من مجموعة كوميدية بريطانية باسم «Monty Python»، وكان أحد الأهداف الأساسية لفريق تطوير بايثون هو جعل اللغة مرحةً وسهلة الاستخدام، وإعدادها بسيطٌ، وطريقة كتابتها مباشرة وتعطيك تقريرًا مباشرًا عند حدوث أخطاء، وهي خيارٌ ممتازٌ للمبتدئين والوافدين الجدد على البرمجة. لغة بايثون هي لغة متعددة الاستعمالات، وتدعم مختلف أنماط البرمجة مثل كتابة السكربتات والبرمجة كائنية التوجه (object-oriented)، وهي مناسبةٌ للأغراض العامة، واستعمالها يتزايد في سوق العمل إذ تعتمدها منظماتٌ مثل «United Space Alliance» (شركة في مجال إرسال مركبات فضائية وتتعاقد معها ناسا) و «Industrial Light & Magic» (أستوديو للتأثيرات السينمائية وللرسوم المتحركة)، وتوفِّر بايثون قدراتٍ كثيرةٍ لمن يريد تعلم لغة برمجة جديدة. طوِّرَت اللغة في نهاية الثمانينات من القرن الماضي، ونُشِرَت أوّل مرة في عام 1991، طُوِّرَت بايثون من قِبل Guido van Rossum، وهو عضوٌ نشطٌ للغاية في المجتمع. وتعتبر بايثون على أنَّها بديلٌ عن لغة ABC، وأوّل إصدار منها كان يتضمن التعامل مع الاستثناءات (exception handling) والدوال والأصناف (classes) مع إمكانية الوراثة فيها. وعدما أُنشِئ منتدى محادثة في Usenet باسم comp.lang.python في 1994، فبدأت قاعدة مستخدمي بايثون بالنمو، مما مهّد الطريق لها لتصبح واحدة من أكثر لغات البرمجة شيوعًا وخصوصًا لتطوير البرمجيات مفتوحة المصدر. لمحة عامة قبل أن ننظر إلى إمكانيات إصدارَي بايثون 2 وبايثون 3 (مع الاختلافات البرمجية الرئيسية بينهما)، فلننظر إلى لمحة تاريخية عن الإصدارات الرئيسية الحديثة من بايثون. بايثون 2 نُشِرَ هذا الإصدار في أواخر عام 2000، وأصبحت بايثون 2 لغة برمجة شاملة مقارنةً بالإصدارات التي تسبقها وذلك بعد تطبيق اقتراح PEP ‏(Python Enhancement Proposal)، وهو مواصفةٌ (specification) تقنيةٌ التي توفِّر معلومات إلى أعضاء مجتمع بايثون أو تصف ميزاتٍ جديدة في اللغة. بالإضافة إلى ذلك، تضمنت بايثون 2 ميزاتٍ برمجية جديدة مثل «cycle-detecting garbage collector» لأتمتة عملية إدارة الذاكرة، وزيادة دعم يونيكود لتدعم اللغة جميع المحارف المعيارية …إلخ. وأثناء عملية تطوير بايثون 2 أضيفت ميزات جديدة بما في ذلك توحيد الأنواع والأصناف في بايثون في بنية هيكلية وحيدة (وذلك في إصدار 2.2 من بايثون). بايثون 3 تُعتَبر بايثون 3 هي مستقبل لغة بايثون وهي النسخة قيد التطوير من اللغة، وهذا إصدارٌ رئيسيٌ نُشِر في أواخر عام 2008 لإصلاح بعض المشاكل الجوهرية في تصميم الإصدارات السابقة من اللغة، وكان التركيز أثناء تطوير بايثون 3 هو تحسين الشيفرات التي تبنى عليها اللغة وحذف التكرارات، مما يعني أنَّ هنالك طريقة وحيدة فقط لإنجاز مهمّة معيّنة. التعديلات الأساسية التي حدثت في بايثون 3.0 تتضمن تغير العبارة print إلى دالة مُضمَّنة باللغة، وتحسين قسمة الأعداد الصحيحة، وتوفير دعم إضافي ليونيكود. في البداية، انتشرت بايثون 3 ببطء نتيجةً لعدم توافقيتها مع بايثون 2، مما يعني أنَّ على المستخدمين اختيار ما هو الإصدار الذي عليهم استخدامه. بالإضافة إلى ذلك، كانت الكثير من المكتبات البرمجية متاحةً فقط لبايثون 2، لكن بعد تقرير فريق تطوير بايثون 3 أنَّه يجب أن التخلي عن دعم بايثون 2، فبدأت عملية تحويل المكتبات إلى بايثون 3. يمكننا معرفة زيادة الاعتماد على بايثون 3 من خلال عدد الحزم البرمجية التي تدعم بايثون 3، والتي هي (في وقت كتابة هذا المقال) 339 من أصل 360 من أشهر الحزم. بايثون 2.7 بعد إصدار بايثون 3.0 في 2008، أُصدِرَت نسخة بايثون 2.7 في تموز 2010 وهي آخر إصدار من سلسلة ‎2.x، الغرض من إصدار بايثون 2.7 هو جعل الطريق ممهدًا أمام مستخدمي بايثون ‎2.x لتحويل برامجهم إلى بايثون 3 بتوفير بعض التوافقية بينهما. وهذه التوافقية تضمنت دعم بعض الوحدات المُحسّنة في 2.7 مثل unittest لأتمتة الاختبارات، و argparse لتفسير خيارات سطر الأوامر، وبعض الفئات في collections. ولخصوصية بايثون 2.7 ولكونها جسرًا واصلًا بين الإصدارات القديمة من بايثون 2 وبين بايثون 3.0، فأصبحت خيارًا شائعًا بين المبرمجين بسبب توافقيتها مع الكثير من المكتبات. عندما نتحدث اليوم عن بايثون 2، فنحن نشير عادةً إلى إصدار بايثون 2.7 لأنَّه أكثر إصدار مستخدم؛ لكنه يُعتَبَر أنَّه إصدارٌ قديم، وسيتوقف تطويره (التطوير الحالي هو إصلاح العلل فقط) تمامًا في 2020. الاختلافات الأساسية بغض النظر أنَّ بايثون 2.7 وبايثون 3 تتشاركان في الكثير من الأشياء، لكن لا يجدر بك أن تظن أنَّهما متماثلتان ويمكن تبديل الشيفرات بينهما. وعلى الرغم من أنَّك تستطيع كتابة شيفرات جيدة وبرامج مفيدة في أيّ إصدار منهما، لكن من المهم أن تفهم أنَّ هنالك بعض الاختلافات في بنية الشيفرات وفي طريقة تفسيرها. سأعرض هنا بعض الأمثلة، لكن عليك أن تعلم أنَّك ستواجه المزيد من الاختلافات أثناء مسيرة تعلمك لبايثون. print في بايثون 2، تُعامَل print كتعبيرٍ برمجيٍ بدلًا من كونها دالة، وهذا كان يثير ارتباكًا لأنَّ الكثير من الأمور داخل بايثون تتطلب تمرير وسائط (arguments) بين قوسين، إذا فتحتَ مُفسِّر بايثون 2 لطباعة «Sammy the Shark is my favorite sea creature»، فستكتب تعبير print الآتي: print "Sammy the Shark is my favorite sea creature" أما في بايثون 3، فستُعامَل print()‎ كدالة، لذا لطباعة السلسلة النصية السابقة، فيمكننا استخدام شكل استدعاء الدوال التقليدي كما يلي: print("Sammy the Shark is my favorite sea creature") هذا التعديل جعل من البنية اللغوية في بايثون موحدةً وسهَّلَ من التبديل بين مختلف دوال الطباعة فيها. يجدر بالذكر أنَّ الدالة print()‎ متوافقة مع بايثون 2.7، لذا ستعمل شيفرات بايثون التي تستعمل print()‎ بشكلٍ صحيحٍ في أيّ الإصدارَين. قسمة الأعداد الصحيحة في بايثون 2، أيُّ عددٍ تكتبه دون فواصل عشرية سيُعامَل على أنَّه من النوع integer، تأتي الإشكالية عندما تحاول قسمة الأعداد الصحيحة على بعضها، فتتوقع في بعض الأحيان حصولك على عددٍ عشري (تسمى أيضًا بالأعداد ذات الفاصلة العائمة float) كما في التعبير الرياضي: 5 / 2 = 2.5 لكن الأعداد الصحيحة في بايثون 2 لن تتحول إلى أعداد عشرية عندما تتطلب العملية التي تُجرى عليها ذلك. عندما يكون العددان الموجودان على جانبَي معامل القسمة / عددين صحيحين، فإن بايثون 2 ستجري عملية القسم وستُنتِج عددًا عشريًا إلا أنها ستُعيد العدد الصحيح الأصغر أو المساوي للناتج، وهذا يعني أنَّه لو كتبتَ ‎5 / 2 فستُعيد بايثون 2.7 العدد الصحيح الأصغر أو المساوي للعدد 2.5، وهو في هذه الحالة 2: a = 5 / 2 print a 2 لإعادة عدد عشري، فيجب إضافة فواصل عشرية إلى الأرقام التي ستُجري عليها عملية القسمة كما في ‎5.0 / 2.0 لكي تحصل على النتيجة المنطقية 2.5. أما في بايثون 3، فقسمة الأعداد الصحيحة أصبحت كما نتوقع: a = 5 / 2 print a 2.5 يمكنك استخدام ‎5.0 / 2.0 لإعادة 2.5، لكن إن أردتَ تقريب ناتج القسمة فاستخدم المعامل // الموجود في بايثون 3، كالآتي: a = 5 // 2 print a 2 هذا التعديل في بايثون 3 جعل من قسمة الأعداد الصحيحة أمرًا سهلًا، لكن هذه الميزة غير متوافقة مع بايثون 2.7. دعم محارف يونيكود عندما تتعامل لغات البرمجة مع السلاسل النصية (strings، والتي هي سلسلةٌ من المحارف)، فهي تفعل ذلك بطرائق مختلفة لكي تتمكن الحواسيب من تحويل الأعداد إلى أحرف ورموز. تستعمل بايثون 2 محارف ASCII افتراضيًا، لذا عندما تكتب "Hello, Sammy!‎" فستتعامل بايثون 2 مع السلسلة النصية كمجموعة من محارف ASCII، والتي هي محدودةٌ لحوالي مئتَي محرف، أي أنَّ محارف ASCII هي طريقة غير عملية لترميز المحارف خصوصًا المحارف غير اللاتينية (كالعربية مثلًا). لاستخدام ترميز محارف يونيكود (Unicode) الذي يدعم أكثر من 128000 محرف تابع للكثير من اللغات والرموز، فعليك أن تكتب u"Hello, Sammy!‎"‎ حيث تُشير السابقة u إلى Unicode. تستعمل بايثون 3 محارف يونيكود (Unicode) افتراضيًا، مما يوفِّر عليك بعض الوقت أثناء التطوير، ويمكنك كتابة وعرض عدد أكبر بكثير من المحارف في برنامجك بسهولة. يدعم يونيكود الكثير من المحارف بما في ذلك الوجوه التعبيرية (emojis)، واستعمالها كترميز محارف افتراضي يعني أنَّ الأجهزة المحمولة ستكون مدعومةً في مشاريعك تلقائيًا. إذا كنت تحب أنَّ تكون شيفرات بايثون 3 التي تكتبها متوافقةً مع بايثون 2، فأبقِ على حرف u قبل السلاسل النصية. استمرار التطوير الفارق الرئيسي بين بايثون 3 وبايثون 2 ليس في البنية اللغوية وإنما في أنَّ إصدار بايثون 2.7 سيتوقف دعمه في 2020، وسيستمر تطوير بايثون 3 بميزاتٍ جديدة وإصلاحٍ لمزيدٍ من العلل. التطويرات الأخيرة في اللغة تتضمن تخصيصًا أبسط لإنشاء الأصناف، وطريقةً أوضح للتعامل مع المصفوفات… الاستمرار بتطوير بايثون 3 يعني أنَّ المطورين يمكن أن يعتمدوا على اللغة، وسيطمئنون أنَّ المشاكل التي قد تحدث فيها ستُحَل في فترةٍ قريبة، ويمكن أن تصبح البرامج أكثر كفاءة بإضافة المزيد من الميزات للغة. نقاطٌ أخرى يجب أخذها بالحسبان عليك أن تضع النقاط الآتية بعين الاعتبار عندما تبدأ مشوارك كمبرمج بلغة بايثون، أو عندما تبدأ بتعلم لغة بايثون بعد تعلمك لغيرها. إذا كنتَ تأمل بتعلم اللغة دون أن تفكِّر بمشروعٍ معيّن، فأنصحك بالتفكير بمستقبل بايثون، فسيستمر تطوير ودعم بايثون 3 بينما سيوقف دعم بايثون 2.7 عمّا قريب. أما إذا كنتَ تُخطِّط للانضمام لفريق تطوير أحد المشاريع، فعليك أن تنظر ما هو إصدار بايثون المستخدم فيه، وكيف يؤدي اختلاف الإصدار إلى اختلاف طريقة تعاملك مع الشيفرات، وإذا ما كانت المكتبات البرمجية المستعملة في المشروع مدعومةً في مختلف الإصدارات، وما هي تفاصيل المشروع نفسه… إذا كنت تُفكّر ببدء أحد المشاريع، فيجدر بك أن تنظر ما هي المكتبات المتوفرة وما هي إصدارات بايثون المدعومة. وكما قلنا سابقًا، الإصدارات الأوليّة من بايثون 3 لها توافقية أقل مع المكتبات المبنية لبايثون 2، لكن الكثير منها قد جرى تحويله إلى بايثون 3، وسيستمر ذلك في السنوات الأربع المقبلة. الخلاصة لغة بايثون كبيرة جدًا وموثقة توثيقًا ممتازًا وسهلة التعلم، ومهما كان اختيارك (بايثون 2 أو بايثون 3) فستتمكن من العمل على المشاريع الموجودة حاليًا. صحيحٌ أنّ هنالك بعض الاختلافات المحورية، لكن ليس من الصعب الانتقال من بايثون 3 إلى بايثون 2، وستجد عادةً أنَّ بايثون 2.7 قادرة على تشغيل شيفرات بايثون 3، خصوصًا في بدايات تعلمك للغة. من المهم أن تبقي ببالك أنَّ تركيز المطورين والمجتمع أصبح منصبًّا على بايثون 3، وسيصبح هذه اللغة رائدةً في المستقبل وستلبي الاحتياجات البرمجية المطلوبة، وأنَّ دعم بايثون 2.7 سيقل مع مرور الزمن إلى أن يزول في 2020. ترجمة -وبتصرّف- للمقال Python 2 vs Python 3: Practical Considerations لصاحبته Lisa Tagliaferri اقرأ أيضًا المقالة التالية: تثبيت بايثون على مختلف أنظمة التشغيل وإعداد بيئتها البرمجية المرجع الشامل إلى تعلم لغة بايثون
  14. بعد أن أخذت فكرة عامة عن لغة البرمجة بايثون وتعرف على تاريخها والفرق بين أهم إصدارين لها، الإصدار 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 المرجع الشامل إلى تعلم لغة بايثون
  15. كتابة برنامج يطبع العبارة "مرحبا بالعالم!‎" وتنفيذه هو أحد التقاليد الأساسية في مجال البرمجة، ويشكل أول برنامج بسيط وكامل للمبتدئين، وكذلك يُعدُّ اختبارًا لأنظمة وبيئات البرمجة، كما يعطي البرنامج فكرة عن الصياغة الأساسية للغات البرمجة. ستتعلم في هذه المقالة كيفية كتابة برنامج "مرحبا بالعالم!" في بايثون 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 وإعداد بيئتها البرمجية المرجع الشامل إلى تعلم لغة بايثون
  16. التعليقات هي عبارات دخيلة على الشيفرات البرمجية وليست جزءًا منها، إذ تتجاهلها المصرّفات (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 اقرأ أيضًا المقالة التالية: فهم أنواع البيانات المقالة السابقة: كيفية استخدام سطر أوامر بايثون التفاعلي المرجع الشامل إلى تعلم لغة بايثون
  17. تُستخدم في بايثون، كما هو الحال في جميع لغات البرمجة، أنواع البيانات لتصنيف البيانات. هذا مهم لأنّ نوع البيانات الذي تستخدمه سيحدد القيم التي يمكن تعيينها لها، وما الذي يمكن فعله بها (بما في ذلك العمليات التي يمكن تنفيذها عليها). سنتعرف في هذه المقالة على أهم أنواع البيانات الأصلية لبايثون. هذا ليس استقصاءً شاملًا لأنواع البيانات، ولكنه سيساعدك على التعرف على الخيارات المتاحة لك في بايثون. مدخل أنواع البيانات في بايثون مشابهة إلى حد ما لأنواع البيانات التي نستخدمها في العالم الحقيقي. من أمثلة أنواع البيانات في العالم الحقيقي الأعداد، مثل: الأعداد الصحيحة الطبيعية (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 المرجع الشامل إلى تعلم لغة بايثون
  18. «السلسلة النصية» (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 اقرأ أيضًا المقالة التالي: كيفية تنسيق النصوص المقال السابق: فهم أنواع البيانات المرجع الشامل إلى تعلم لغة بايثون
  19. تتألف السلاسل النصية عادةً من النص المكتوب، وهنالك عدِّة حالات نحتاج فيها إلى تحكمٍ أكبر بكيفية إظهار النص وجعلها أسهل قراءةً للبشر عبر وضع علامات الترقيم والسطور الجديدة والمحاذاة. سنشرح في هذا الدرس كيفية التعامل مع السلاسل النصية في بايثون لكي يظهر النص الناتج بتنسيقٍ صحيح. القيم الحرفية لنفرِّق أولًا بين القيم الحرفية للسلاسل النصية (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 اقرأ أيضًا المقال التالي: مقدمة إلى دوال التعامل مع السلاسل النصية المقال السابق: مدخل إلى التعامل مع السلاسل النصية المرجع الشامل إلى تعلم لغة بايثون
  20. لدى بايثون عدِّة دوال مبنية فيها للتعامل مع السلاسل النصية. تسمح هذه الدوال لنا بتعديل وإجراء عمليات على السلاسل النصية بسهولة. يمكنك أن تتخيل الدوال على أنها «أفعال» يمكننا تنفيذها على عناصر موجودة في الشيفرة. الدوال المبنية في اللغة هي الدوال المُعرَّفة داخل لغة بايثون وهي جاهزة مباشرةً للاستخدام. سنشرح في هذا الدرس مختلف الدوال التي نستطيع استخدامها للتعامل مع السلاسل النصية في بايثون 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 اقرأ أيضًا المقال التالي: آلية فهرسة السلاسل النصية وطريقة تقسيمها المقال السابق: كيفية تنسيق النصوص المرجع الشامل إلى تعلم لغة بايثون
  21. السلاسل النصية في بايثون هي مجموعةٌ مُنشأةٌ من المحارف المنفصلة والتي تُمثِّل الأحرف والأرقام والفراغات والرموز. ولأنَّ السلسلة النصية هي «سلسلة»، فيمكن الوصول إليها كغيرها من أنواع البيانات المتسلسلة، عبر الفهارس والتقسيم. سيشرح لك هذا الدرس كيفية الوصول إلى السلاسل النصية بفهارسها، وتقسيمها إلى مجموعات من المحارف، وسيُغطي طرائق إحصاء المحارف وتحديد مواضعها. آلية فهرسة السلاسل النصية وكما في نوع البيانات 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. اقرأ أيضًا المقال التالي: كيفية التحويل بين أنواع البيانات المقال السابق: مقدمة إلى دوال التعامل مع السلاسل النصية المرجع الشامل إلى تعلم لغة بايثون
  22. تُستخدَم أنواع البيانات في بايثون لتصنيف نوع معيَّن من البيانات، وتحديد القيم التي يمكنك تعيينها لذلك النوع، والعمليات التي يمكنك إجراؤها عليها. هناك أوقات نحتاج إلى تحويل القيم من نوع إلى آخر لأجل معالجتها بطريقة مختلفة. على سبيل المثال، قد نحتاج إلى ضم (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 اقرأ أيضًا المقالة التالية: كيفية استخدام المتغيرات المقالة السابقة: آلية فهرسة السلاسل النصية وطريقة تقسيمها المرجع الشامل إلى تعلم لغة بايثون
  23. المتغيرات هي مفهوم برمجي مهم. إنَّها رموز تدل على القيم التي تستخدمها في برنامجك. 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 اقرأ أيضًا المقالة التالية: كيفية استخدام آلية تنسيق السلاسل النصية المقالة السابقة: كيفية التحويل بين أنواع البيانات المرجع الشامل إلى تعلم لغة بايثون
  24. الدالة 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. اقرأ أيضًا المقالة التالية: كيفية إجراء العمليات الحسابية المقالة السابقة: كيفية استخدام المتغيرات المرجع الشامل إلى تعلم لغة بايثون
  25. الأعداد شائعةٌ جدًا في البرمجة، إذ تُستخدم لتمثيل مختلف القيم، مثل أبعاد حجم الشاشة، والمواقع الجغرافية، والمبالغ المالية، ومقدار الوقت الذي مر منذ بداية فيديو، والألوان وغير ذلك. 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 المقالة السابقة: كيفية استخدام آلية تنسيق السلاسل النصية المرجع الشامل إلى تعلم لغة بايثون