مقدمة إلى بايثون

مقدمة

مرحبًا بك في البرنامج التعليمي على الإنترنت بلغة بايثون من Google. يعتمد على دورة بايثون التمهيدية المقدمة داخليًا. كما ورد في صفحة الإعداد، تغطي هذه المادة لغة Python 3.

إذا كنت تبحث عن دورة تدريبية مصاحبة للدورة التدريبية الطويلة المفتوحة على الإنترنت (MOOC)، يمكنك تجربة الدورات المتوفرة من Udacity وCoursera (مقدمة عن البرمجة [المبتدئين] أو مقدمة عن Python). وأخيرًا، إذا كنت تسعى إلى التعلّم بالوتيرة التي تناسبك على الإنترنت بدون مشاهدة فيديوهات، يمكنك تجربة الدروس الواردة في نهاية هذه المشاركة والتي تتضمّن محتوى تعليميًا لكل ميزة بالإضافة إلى مترجم Python تفاعلي يمكنك التدرّب عليه. ما هذا "المترجم" الذي نذكره؟ يمكنك معرفة ذلك في القسم التالي.

مقدمة عن اللغة

بايثون لغة ديناميكية مفسَّرة (تم تجميع رمز بايت). لا تتوفّر إعلانات لأنواع المتغيرات أو المعلَمات أو الدوال أو الطرق في رمز المصدر. ويؤدي هذا إلى جعل التعليمة البرمجية قصيرة ومرنة، وتفقد التحقق من نوع وقت التجميع في رمز المصدر. تتعقب بايثون أنواع جميع القيم في وقت التشغيل وتضع علامات على التعليمات البرمجية التي لا معنى لها أثناء تشغيلها.

الطريقة الممتازة لمعرفة طريقة عمل كود Python هي تشغيل مترجم Python وكتابة الرمز فيه مباشرةً. إذا كان لديك سؤال مثل "ماذا يحدث لو أضفت int إلى list؟" فإن مجرد كتابته في أداة الترجمة الفورية بلغة Python هي طريقة سريعة على الأرجح لمعرفة ما يحدث. (يمكنك الاطّلاع أدناه على ما يحدث.)

$ python3        ## Run the Python interpreter
Python 3.X.X (XXX, XXX XX XXXX, XX:XX:XX) [XXX] on XXX
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 6       ## set a variable in this interpreter session
>>> a           ## entering an expression prints its value
6
>>> a + 2
8
>>> a = 'hi'    ## 'a' can hold a string just as well
>>> a
'hi'
>>> len(a)      ## call the len() function on a string
2
>>> a + len(a)  ## try something that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
TypeError: can only concatenate str (not "int") to str
>>> a + str(len(a))  ## probably what you really wanted
'hi2'
>>> foo         ## try something else that doesn't work
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'foo' is not defined
>>> ^D          ## type CTRL-d to exit (CTRL-z in Windows/DOS terminal)

تتم طباعة السطرين من Python بعد كتابة python وقبل المطالبة >>> بإخبارك عن إصدار بايثون الذي تستخدمه ومكان إنشائه. طالما أن أول شيء مطبوع هو "Python 3."، فمن المفترض أن تكون هذه الأمثلة مناسبة لك.

كما ترى أعلاه، من السهل تجربة المتغيرات وعوامل التشغيل. وأيضًا، يعرض المترجم اللغوي أو "يرفع" في لغة بايثون خطأ وقت تشغيل إذا حاول الكود قراءة متغير لم يتم تعيين قيمة له. مثل C++ وJava، تعتبر بايثون حساسة لحالة الأحرف لذا فإن "a" و "A" متغيران مختلفان. تمثل نهاية السطر نهاية العبارة، ولذلك على عكس C++ وJava، لا تتطلب بايثون فاصلة منقوطة في نهاية كل عبارة. تبدأ التعليقات بعلامة "#" وتمتد إلى نهاية السطر.

رمز مصدر Python

تستخدم الملفات المصدر في لغة بايثون الامتداد ".py" ويُطلق عليها "الوحدات". مع وحدة بايثون hello.py، تتمثل أسهل طريقة لتشغيلها في استخدام أمر واجهة المستخدم "python hello.py Alice" الذي يستدعي مترجم Python لتنفيذ الرمز في hello.py، مع تمرير وسيطة سطر الأوامر "Alice" إليه. يمكنك الاطّلاع على صفحة المستندات الرسمية في جميع الخيارات المختلفة التي تمتلكها عند تشغيل Python من سطر الأوامر.

إليك برنامج hello.py بسيط جدًا (لاحظ أنّ مجموعات الرموز يتم الفصل بينها بصرامة باستخدام المسافة البادئة بدلاً من الأقواس المعقوفة، وسنتعرّف أكثر على هذا البرنامج لاحقًا):

#!/usr/bin/python3

# import modules used here -- sys is a very standard one
import sys

# Gather our code in a main() function
def main():
    print('Hello there', sys.argv[1])
    # Command line args are in sys.argv[1], sys.argv[2] ...
    # sys.argv[0] is the script name itself and can be ignored

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
    main()

يبدو تشغيل هذا البرنامج من سطر الأوامر كما يلي:

$ python3 hello.py Guido
Hello there Guido
$ ./hello.py Alice  ## without needing 'python3' first (Unix)
Hello there Alice

عمليات الاستيراد ووسيطات سطر الأوامر وlen()

تُجرى العبارات الخارجية في ملف بايثون، أو "وحدة"، إعدادًا لمرة واحدة، حيث يتم تشغيل تلك العبارات من أعلى إلى أسفل عند استيراد الوحدة في مكان ما لأول مرة، مما يؤدي إلى إعداد متغيراتها ودوالها. يمكن تشغيل وحدة بايثون مباشرةً - كما هو الحال أعلاه - python3 hello.py Bob - أو يمكن استيرادها واستخدامها بواسطة وحدة أخرى. عند تشغيل ملف بايثون مباشرةً، يتم تعيين المتغير الخاص "__name__" على "__main__". وبالتالي، من الشائع أن تكون الدالة if __name__ ==... النموذجية المعروضة أعلاه لاستدعاء دالة main() عند تشغيل الوحدة مباشرةً، ولكن ليس عند استيراد الوحدة بواسطة وحدة أخرى.

في برنامج بايثون عادي، تحتوي القائمة sys.argv على وسيطات سطر الأوامر بالطريقة القياسية، حيث يكون sys.argv[0] هو البرنامج نفسه، والوسيطة الأولى sys.argv[1]، وهكذا. إذا كنت تعرف عن argc، أو عدد الوسيطات، يمكنك ببساطة طلب هذه القيمة من Python باستخدام len(sys.argv)، تمامًا كما فعلنا في رمز الترجمة الفورية التفاعلي أعلاه عند طلب طول سلسلة. بشكل عام، بإمكان len() إخبارك بطول السلسلة وعدد العناصر في القوائم والصفوف (هيكل بيانات آخر يشبه الصفيف) وعدد أزواج المفتاح/القيمة في القاموس.

الدوال التي يحددها المستخدم

يتم تعريف الدوال في بايثون على النحو التالي:

# Defines a "repeat" function that takes 2 arguments.
def repeat(s, exclaim):
    """
    Returns the string 's' repeated 3 times.
    If exclaim is true, add exclamation marks.
    """

    result = s + s + s # can also use "s * 3" which is faster (Why?)
    if exclaim:
        result = result + '!!!'
    return result

لاحظ أيضًا كيف يتم تجميع الأسطر التي تشكل الدالة أو العبارة الشرطية حسب كل ما له نفس مستوى المسافة البادئة. قدمنا أيضًا طريقتين مختلفتين لتكرار السلاسل، باستخدام عامل التشغيل + الذي يسهل استخدامه أكثر، لكن * يعمل أيضًا لأنه عامل "تكرار" في بايثون، مما يعني أن '-' * 10 يعطي '----------'، وهي طريقة أنيقة لإنشاء "خط" على الشاشة. في تعليق التعليمة البرمجية، لمحنا إلى أن * يعمل بشكل أسرع من +، والسبب هو أن * تحسب حجم الكائن الناتج مرة واحدة بينما مع +، يتم إجراء هذه العملية الحسابية في كل مرة يتم فيها استدعاء +. يطلق على كل من + و * عاملي التشغيل "التحميل الزائد" لأنهما يعنيان أشياء مختلفة للأرقام مقابل للسلاسل (وأنواع البيانات الأخرى).

تحدد الكلمة الرئيسية def الدالة بمعلماتها بين قوسين، ويتم وضع مسافة بادئة لرمزها. يمكن أن يكون السطر الأول من الدالة سلسلة وثائق ("docstring") تصف وظيفة الدالة. يمكن أن تكون سلسلة المستند سطرًا واحدًا أو وصفًا متعدد الأسطر كما في المثال أعلاه. (نعم، هذه هي "الاقتباسات الثلاثية"، وهي ميزة فريدة في لغة بايثون!) تعتبر المتغيرات المحددة في الدالة محلية لهذه الدالة، وبالتالي فإن "النتيجة" في الدالة أعلاه منفصلة عن متغير "النتيجة" في دالة أخرى. يمكن أن تستخدم العبارة return وسيطة، وتكون في هذه الحالة هي القيمة التي تم إرجاعها إلى المتصل.

فيما يلي التعليمة البرمجية التي تستدعي دالة rename() أعلاه، وتطبع ما يتم إرجاعه:

def main():
    print(repeat('Yay', False))      ## YayYayYay
    print(repeat('Woo Hoo', True))   ## Woo HooWoo HooWoo Hoo!!!

في وقت التشغيل، يجب تحديد الدوال من خلال تنفيذ "def" قبل استدعائها. من المعتاد تحديد دالة main() باتجاه الجزء السفلي من الملف مع الدوال التي تستدعيها فوقها.

المسافة البادئة

من بين ميزات بايثون غير المعتادة أن المسافة البادئة للمسافة البيضاء لجزء من الرمز تؤثر على معناه. يجب أن يكون للكتلة المنطقية من العبارات مثل تلك التي تشكل دالة نفس المسافة البادئة، وأن يتم تعيينها من المسافة البادئة للدالة الرئيسية أو "if" أو أي شيء. إذا كان أحد الأسطر في المجموعة يحتوي على مسافة بادئة مختلفة، يتم وضع علامة عليه كخطأ في البنية.

بدا استخدام بايثون للمسافة البيضاء غريبًا بعض الشيء في البداية، لكنه منطقي واكتشفت أني اعتدت على ذلك بسرعة كبيرة. تجنب استخدام علامات التبويب لأنها تؤدي إلى تعقيد كبير في مخطط المسافة البادئة (بالإضافة إلى أن علامات TAB قد تعني أشياء مختلفة على أنظمة أساسية مختلفة). اضبط المحرر لإدراج مسافات بدلاً من علامات التبويب لشفرة Python.

من بين الأسئلة الشائعة التي يطرحها المبتدئين "كم عدد المسافات التي يجب وضع مسافة بادئة لها؟" وفقًا لدليل Python الرسمي لأسلوب PEP (PEP 8)، يجب وضع مسافة بادئة بـ 4 مسافات. (حقيقة ممتعة: تحدد إرشادات الأسلوب الداخلي في Google إضافة مسافة بادئة بمقدار مسافتين!)

تم التحقّق من الرمز في وقت التشغيل

تُجري لغة بايثون القليل جدًا من عمليات التحقق في وقت التجميع، وتؤجل تقريبًا جميع عمليات التحقق من الأنواع والاسم وما إلى ذلك في كل سطر حتى يتم تشغيل هذا السطر. افترض أن استدعاء main() أعلاه يكرر() على هذا النحو:

def main():
    if name == 'Guido':
        print(repeeeet(name) + '!!!')
    else:
        print(repeat(name))

تحتوي العبارة if على خطأ واضح، حيث تمت كتابة الدالة rename() عن طريق الخطأ كـ repeeeet(). والشيء المضحك في Python ... فإن هذه التعليمة البرمجية يتم تجميعها وتشغيلها بشكل جيد طالما أن الاسم في وقت التشغيل ليس 'Guido'. فقط عندما تحاول عملية تشغيل تنفيذ repeeeet() فعليًا، ستلاحظ عدم وجود مثل هذه الدالة وترفع خطأ. هناك أيضًا خطأ ثانٍ في هذا المقتطف. قيمة قبل مقارنتها بـ "Guido". سترفع بايثون الخطأ "NameError" إذا حاولت تقييم متغير لم يتم تعيينه. هذه بعض الأمثلة التي توضح أنه عند تشغيل برنامج بايثون لأول مرة، ستكون بعض الأخطاء الأولى التي تراها أخطاء إملائية بسيطة أو متغيرات غير مهيأة مثل هذه. هذه هي إحدى المجالات التي تكون فيها اللغات ذات نظام النوع المطول، مثل Java، لها ميزة ... فيمكنها اكتشاف مثل هذه الأخطاء في وقت التجميع (ولكن بالطبع عليك الاحتفاظ بكل هذه المعلومات ... إنها مقايضة).

قدّمت Python 3 تلميحات الكتابة. تسمح لك تلميحات الكتابة بالإشارة إلى نوع كل وسيطة في الدالة وكذلك نوع الكائن الذي تم إرجاعه بواسطة الدالة. على سبيل المثال، في الدالة التي تتضمّن تعليقات توضيحية def is_positive(n: int) -> bool:، تكون الوسيطة n int والقيمة المعروضة هي bool. سوف نتناول ما تعنيه هذه الأنواع لاحقًا. ومع ذلك، فإن تلميحات الكتابة اختيارية تمامًا على الرغم من ذلك. ستظهر لك تلميحات أكثر عن طريقة استخدام الرموز البرمجية لأنّه في حال استخدامها، يمكن لبعض المحرّرين مثل cider-v وVS.code إجراء عمليات تحقُّق للتحقّق من أنّ الدوال التي يتم استخدامها باستخدام أنواع الوسيطات الصحيحة. ويمكنهم أيضًا اقتراح الوسيطات والتحقق من صحتها أثناء تعديل التعليمات البرمجية. لن يتناول هذا البرنامج التعليمي تلميحات الأنواع ولكننا نريد التأكد من أنك على دراية بها إذا سمعت عنها أو شاهدتها بشكل عام.

أسماء المتغيرات

نظرًا لأن متغيرات بايثون لا تحتوي على أي نوع مكتوب في رمز المصدر، فمن المفيد إعطاء أسماء ذات معنى للمتغيرات لتذكير نفسك بما يحدث. لذلك استخدم "الاسم" إذا كان اسمًا واحدًا، و"الأسماء" إذا كانت قائمة أسماء، و"الصفوف" إذا كانت قائمة بالصفوف. تنتج العديد من أخطاء بايثون الأساسية عن نسيان نوع القيمة في كل متغير، لذلك استخدم أسماء المتغيرات (كل ما لديك من معلومات) للمساعدة في الحفاظ على النص في الوضع الصحيح.

فيما يتعلق بالتسمية الفعلية، تفضل بعض اللغات شرطة سفلية_للأسماء للمتغيرات التي تتكون من "أكثر من كلمة"، لكن تفضل لغات أخرى استخدام CamlCasing. بشكل عام، تفضل لغة البايثون طريقة الشرطة السفلية، ولكنها توجه المطورين إلى تأجيل استخدام CamlCasing في حال الدمج مع رمز Python الحالي الذي يستخدم هذا النمط. أهمية سهولة القراءة. اقرأ المزيد في القسم الخاص باصطلاحات التسمية في PEP 8.

فكما يمكنك التخمين، لا يمكن استخدام كلمات رئيسية مثل "if" و" while" كأسماء متغيرات - ستحصل على خطأ في البنية إذا فعلت ذلك. ومع ذلك، يجب الحرص على عدم استخدام الأسماء المضمنة كأسماء متغيّرات. على سبيل المثال، بينما قد تبدو 'str' و'list' و'print' أسماء جيدة، فستتجاوز متغيرات النظام هذه. لا تكون البيانات المضمّنة كلمات رئيسية وبالتالي فهي عرضة للاستخدام غير المقصود من قِبل مطوري بايثون الجدد.

مزيد من المعلومات حول الوحدات ومساحات الأسماء الخاصة بها

لنفترض أن لديك الوحدة النمطية "binky.py" التي تحتوي على "def foo()". والاسم المؤهل بالكامل لدالة foo هذه هو "binky.foo". وبهذه الطريقة، يمكن لوحدات بايثون مختلفة تسمية الدوال والمتغيرات كما تريد، ولن تتعارض أسماء المتغيرات — حيث تختلف الوحدة unit1.foo عن الوحدة النمطية 2.foo. في مفردات بايثون، قد نقول أن لكل من binky وmodule1 وmodule2 "مساحات أسماء" خاصة بها، والتي يمكنك تخمينها كما يمكنك أن تكون روابط متغيرة من اسم إلى كائن.

على سبيل المثال، لدينا وحدة "sys" القياسية التي تحتوي على بعض مرافق النظام القياسية، مثل قائمة argv ودالة exit(). باستخدام العبارة "Import sys"، يمكنك بعد ذلك الوصول إلى التعريفات في وحدة النظام وإتاحتها حسب الاسم المؤهل بالكامل، على سبيل المثال sys.exit(). (نعم، تحتوي 'sys' على مساحة اسم أيضًا!)

  import sys

  # Now can refer to sys.xxx facilities
  sys.exit(0)

يوجد نموذج استيراد آخر على النحو التالي: "from sys import argv, exit". هذا يجعل argv وExit() متاحتين من خلال الاسمين المختصرين؛ ومع ذلك، نوصي بالنموذج الأصلي بالأسماء المؤهلة بالكامل لأنه يكون تحديد مصدر الدالة أو السمة أسهل كثيرًا.

هناك العديد من الوحدات والحزم التي تتضمن تثبيتًا قياسيًا لمترجم لغة البايثون الفوري، لذا لن يتعين عليك اتخاذ أي إجراء إضافي لاستخدامها. وتُعرف هذه المكتبات مجتمعةً باسم "مكتبة Python المعيارية". تشمل الوحدات/الحِزم الشائعة الاستخدام ما يلي:

  • sys — الوصول إلى exit() وargv وstdin وstdout و...
  • re — التعبيرات العادية
  • os - واجهة نظام التشغيل، نظام الملفات

يمكنك العثور على مستندات جميع وحدات وحِزم المكتبة العادية على http://docs.python.org/library.

المساعدة على الإنترنت، help() وdir()

هناك عدة طرق للحصول على المساعدة في بايثون.

  • نفِّذ عملية بحث على Google باستخدام كلمة "python"، مثل "python list" أو "python واستهلال سلسلة صغيرة". غالبًا ما تكون النتيجة الأولى هي الإجابة. يبدو أن هذا الأسلوب يعمل بشكل أفضل مع لغة بايثون أكثر منه مع اللغات الأخرى لسبب ما.
  • يحتوي الموقع الرسمي لمستندات Python — docs.python.org — على مستندات عالية الجودة. ومع ذلك، غالبًا ما نجد أن البحث على Google بكلمات قليلة هو الأسرع.
  • هناك أيضًا قائمة بريدية رسمية لـ Tutor، مصممة خصوصًا لمبتدئي استخدام Python و/أو البرمجة.
  • ويمكن الاطّلاع على العديد من الأسئلة (والإجابات) على StackOverflow وQuora.
  • استخدِم الدالتَين help() وdir() (انظر أدناه).

داخل مترجم بايثون، تعرض الدالة help() سلاسل الوثائق للوحدات والدوال والطرق المختلفة. تشبه سلاسل المستندات هذه لغة javadoc. تخبرك الدالة dir() بسمات الكائن. فيما يلي بعض الطرق لاستدعاء help() وdir() من المترجم:

  • help(len) - سلسلة المساعدة لدالة len() المدمجة، مع العلم أنّ القيمة هي "len" وليست "len() "، وهو عبارة عن استدعاء للدالة التي لا نريدها
  • help(sys) - سلسلة المساعدة الخاصة بوحدة sys (يجب إجراء import sys أولاً)
  • dir(sys): يشبه dir() help()، ولكنه يقدّم قائمة سريعة بالرموز التي يتم تعريفها أو "السمات".
  • help(sys.exit): سلسلة المساعدة للدالة exit() في الوحدة sys
  • help('xyz'.split): سلسلة المساعدة لطريقة split() لكائنات السلسلة يمكنك استدعاء help() باستخدام الكائن نفسه أو مثال له بالإضافة إلى سمته. على سبيل المثال، الاتصال بـ help('xyz'.split) مماثل لطلب الرقم help(str.split).
  • help(list) - سلسلة المساعدة لـ list عنصر
  • dir(list) — يعرض سمات الكائن list، بما في ذلك الطرق
  • help(list.append): سلسلة المساعدة لطريقة append() لكائنات list