أهم 9 أخطاء يرتكبها مبرمجو بايثون وكيفية تجنبها

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

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

في هذه المقالة، سنتعمق في تعقيدات لغة بايثون. و نكشف عن الأخطاء الشائعة التي غالبًا ما يجد المبرمجون، وخاصة المبتدئين، أنفسهم متورطين فيها. الهدف ليس التثبيط، بل التنوير، وليس الانتقاد، بل الصقل.

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

من سوء فهم نظام الكتابة الديناميكي في بايثون إلى عدم استخدام عبارة “with” عند التعامل مع الملفات؛ بدءًا من إهمال أسلوب البرمجة في بايثون، PEP8، وحتى عدم التعامل مع الاستثناءات بشكل صحيح – هذه بعض من بين مجموعة واسعة من الأخطاء الشائعة. إن اتساع نطاق هذه الأخطاء يسلط الضوء على مدى سهولة تعثر المرء، ولكن لا داعي للقلق. من خلال الفهم الصحيح يمكن تجنب هذه الأخطاء، مما يجعل رحلة البرمجة أكثر سلاسة ومتعة.

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

1 سوء فهم الكتابة الديناميكية في بايثون

أحد الأسباب العديدة التي تجعل بايثون تجذب المطورين حول العالم هو طبيعتها المكتوبة ديناميكيًا. على عكس اللغات المكتوبة بشكل ثابت مثل C أو Java، لا تتطلب Python منك الإعلان عن نوع بيانات المتغير عند إنشائه. يعتبر سطر مثل x = 5 صالحًا تمامًا، دون الحاجة إلى كتابة شيء مثل int x = 5. تعمل هذه الميزة بشكل كبير على تحسين مرونة وسهولة البرمجة في Python.

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

دعونا نلقي نظرة على مثال. لنفترض أن لديك متغير x مخصصًا لعدد صحيح، وقررت القيام بعملية الجمع بسلسلة. قد يبدو الأمر منطقيًا تمامًا في رأسك:

x = 5
print("The number is " + x)

سيؤدي تشغيل هذا الكود إلى خطأ TypeError:

TypeError: can only concatenate str (not "int") to str

ينشأ هذا الخطأ لأنه على الرغم من كتابة لغة Python ديناميكيًا، إلا أنها لا تزال تلتزم بقواعد محددة حول كيفية تفاعل أنواع البيانات المختلفة. في هذه الحالة، لا يمكنك ربط سلسلة وعدد صحيح دون تحويل العدد الصحيح بشكل صريح إلى سلسلة.

لتجنب هذا الخطأ، يجب أن تكون على دراية كاملة بنوع البيانات التي تتعامل معها. و هذا هو المكان الذي تصبح فيه دالة type() المدمجة في Python مفيدة.

x = 5
print(type(x))  # الناتج : <class 'int'>

تقوم هذه الدالة بإرجاع نوع الكائن الذي تمرره إليه، مما يسمح لك بمعرفة بياناتك والتعامل معها بشكل أفضل. بمعرفة أن x عدد صحيح، يمكنك بعد ذلك تحويله إلى سلسلة باستخدام الدالة str() :

x = 5
print("The number is " + str(x))  # الناتج : The number is 5

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

كيفية تسمية واستخدام المتغيرات في بايثون

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

2 تجاهل أسلوب البرمجة في بايثون (PEP8)

في عالم بايثون، PEP8 ليس مجرد اختصار آخر. إنه بمثابة منارة، وضوء إرشادي يحدد المسار نحو تعليمات برمجية أكثر قابلية للقراءة، وقابلية للصيانة، ومتسقة. يمثل PEP8، وهو اختصار لـ “Python Enhancement Proposal 8″، دليل الأسلوب الرسمي لـ Python، حيث يضع القانون لكيفية تنسيق كود Python وتصميمه.

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

خذ بعين الاعتبار المثال التالي:

def calculateSum(a,b):return a+b
result=calculateSum(5,3)

على الرغم من أن هذا الكود يعمل بشكل جيد، إلا أنه لا يتبع دليل نمط PEP8. لا يلتزم اسم الدالة باتفاقية lowercase_with_underscore، ولا توجد مسافة بعد الفاصلة التي تفصل بين المعلمات، ولا توجد مسافة حول عامل التشغيل في الدالة، ويفتقر إلى مسافة بادئة مناسبة.

و بإتباع نمط PEP8، سيبدو الكود كما يلي:

def calculate_sum(a, b):
    return a + b

result = calculate_sum(5, 3)

الفرق واضح. يعد نمط PEP8 أسهل في القراءة والفهم. القواعد المنصوص عليها في PEP8 موجودة لسبب ما: فهي تجعل التعليمات البرمجية أكثر وضوحًا وأكثر سهولة في الوصول إليها أنت والآخرين الذين قد يحتاجون إلى العمل مع التعليمات البرمجية الخاصة بك في المستقبل.

إذًا، كيف تتأكد من أن الكود الخاص بك يتبع PEP8؟ أولاً، تعرف على قواعد PEP8 الأساسية. فهم اصطلاحات التسمية الموصى بها، وقواعد المسافة البادئة، والإرشادات حول طول السطر، والتباعد حول عوامل التشغيل، وغيرها.

ثانيا، استخدم الأدوات لصالحك. فكر في استخدام أداة linter، وهي أداة تقوم تلقائيًا بفحص التعليمات البرمجية مقابل دليل نمط PEP8. هناك العديد من الفلاتر المتوفرة مثل pylint وflake8 والألياف المدمجة في العديد من بيئات التطوير المتكاملة (IDEs) مثل PyCharm أو Visual Studio Code.

يمكن لـ Linters تمييز المناطق التي ينحرف فيها الكود الخاص بك عن PEP8 تلقائيًا، مما يساعدك على الالتزام بدليل النمط دون قضاء الكثير من الوقت في التحقق من الكود يدويًا.

إليك مثال باستخدام flake8:

$ flake8 example.py

example.py:1:16: E231 missing whitespace after ','
example.py:1:18: E701 multiple statements on one line (colon)
example.py:2:8: E225 missing whitespace around operator

يشير هذا الناتج إلى المكان الذي تنتهك فيه PEP8 في التعليمات البرمجية الخاصة بك، وما هي القاعدة المحددة التي تنتهكها. يمكن أن تساعدك هذه التعليقات في تصحيح التعليمات البرمجية الخاصة بك لتكون أكثر توافقًا مع PEP8.

ومع ذلك، تذكر أن هذه الأدوات هي مجرد أدوات. يمكنهم مساعدتك، لكن مسؤولية كتابة تعليمات برمجية واضحة وقابلة للقراءة ومتسقة تقع على عاتقك في النهاية. لا تحفظ قواعد PEP8 فقط؛ فهمها وأهميتها في الحفاظ على قاعدة تعليمات برمجية صحية وقابلة للقراءة. احتضن طريقة Pythonic في كتابة التعليمات البرمجية، ليس فقط من حيث بناء الجملة، ولكن أيضًا من حيث الأسلوب.

في الختام، PEP8 ليس مجرد دليل أسلوب – إنه التزام بكود Python القابل للصيانة والقراءة والنظيف. إنها شهادة على فلسفة بايثون الشاملة – سهولة القراءة مهمة، والبساطة أفضل من التعقيد. كمطورين لـ Python، يعد الالتزام بـ PEP8 جزءًا مهمًا من مساهمتنا في هذه الفلسفة.

3 الاستخدام غير الصحيح للمسافة البادئة

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

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

خذ بعين الاعتبار هذا المثال:

x = 1
if x > 0:
print("x is positive")

قد تتوقع أن يُطبع هذا الكود “x موجب” لأن x أكبر بالفعل من 0. ولكن بدلاً من ذلك، ستحصل على خطأ المسافة البادئة:

IndentationError: expected an indented block

يحدث هذا الخطأ لأن Python تتوقع أن يتم وضع مسافة بادئة للتعليمة البرمجية التي يجب تنفيذها إذا كان الشرط صحيحًا (أي الكود الموجود داخل عبارة if). تصحيح المسافة البادئة يحل الخطأ:

x = 1
if x > 0:
    print("x is positive")  # This line is indented

المسافة البادئة المتسقة ليست مهمة فقط داخل كتل التعليمات البرمجية، ولكن أيضًا بين الكتل المختلفة. لننظر إلى مثال آخر:

x = 1
if x > 0:
    print("x is positive")
      print("This is a good number")  # This line is over-indented

سيؤدي تشغيل هذا الكود إلى خطأ آخر في المسافة البادئة:

IndentationError: unexpected indent

تم وضع مسافة بادئة زائدة في السطر “This is a good number”، مما يؤدي إلى تعطيل اتساق التعليمات البرمجية وتسبب في قيام بايثون بإلقاء خطأ. لإصلاح هذه المشكلة، تأكد من وضع مسافة بادئة لجميع الأسطر داخل نفس الكتلة بشكل متسق:

x = 1
if x > 0:
    print("x is positive")
    print("This is a good number")  # The indentation is now consistent

كما ترون، يعد استخدام المسافة البادئة بشكل صحيح أمرًا بالغ الأهمية في بايثون. ولكن ما مقدار المسافة البادئة التي يجب أن تستخدمها؟ التوصية الرسمية، وفقًا لـ PEP8، هي أربع مسافات لكل مستوى مسافة بادئة.

def my_function():
    # This is the correct indentation level
    pass

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

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

4 استخدام قوائم بايثون بشكل غير فعال

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

فكر في موقف يكون لديك فيه قائمة أرقام وتريد إنشاء قائمة جديدة تحتوي على مربعات هذه الأرقام. قد يبدو نهج المبتدئين كما يلي:

numbers = [1, 2, 3, 4, 5]
squares = []
for n in numbers:
    squares.append(n ** 2)

على الرغم من عدم وجود أي خطأ جوهري في هذه التعليمات البرمجية، إلا أنها أطول قليلاً من اللازم ولا تستفيد بشكل كامل من إمكانات Python.

توفر Python طريقة أكثر كفاءة للقيام بذلك باستخدام list comprehensions. حيث تسمح لك بإنشاء قوائم بسرعة وبطريقة موجزة وسهلة القراءة. إليك كيفية إعادة كتابة الكود أعلاه باستخدام list comprehensions:

numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]

في سطر واحد تكون قد حققت ما استغرق ثلاثة أسطر في المثال السابق. وهذا لا يجعل التعليمات البرمجية أكثر وضوحًا فحسب، بل يمكنه أيضًا تقديم فوائد الأداء، خاصة مع القوائم الكبيرة.

تحتوي بايثون أيضًا على دوال مدمجة يمكنها أن تجعل معالجة القائمة أكثر كفاءة، مثل map() و filter(). تطبق الدالة Map() دالة معينة على كل عنصر من العناصر القابلة للتكرار (مثل القائمة) وتقوم بإرجاع قائمة بالنتائج.

numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))

كيفية استخدام قوائم بايثون

في هذه الحالة، تطبق map() دالة lambda x: x ** 2 على كل عنصر بالأرقام، مما يؤدي إلى نفس قائمة المربعات كما كان من قبل.

في الختام، تعلم كيفية استخدام list comprehensions في بايثون و الدوال المضمنة مثل map() و filter() يمكن أن يحسن بشكل كبير من كفاءة التعليمات البرمجية وسهولة قراءتها. تذكر أن كتابة تعليمات برمجية لا تتعلق فقط بإنجاز المهمة، بل بإنجازها بأناقة وكفاءة. لذا، لا تستخدم لغة بايثون فحسب، بل استخدمها بطريقة بايثونية.

عدم استخدام عبارة “with” الخاصة ببايثون عند التعامل مع الملفات

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

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

خذ بعين الاعتبار الكود التالي:

file = open("example.txt", "r")
content = file.read()
# forgot to close the file

في هذا المثال، يتم فتح الملف، وتتم قراءة محتوياته في متغير content. ومع ذلك، لا يتم إغلاق الملف أبداً. إذا حدث هذا في حلقة أو برنامج كبير، فقد يؤدي ذلك إلى فتح عدد كبير من الملفات دون إغلاقها، مما يؤدي إلى تسرب الموارد.

إذًا، كيف يمكنك تجنب هذا الخطأ؟ الحل هو مع عبارة with حيث تضمن إغلاق الملف بشكل صحيح بعد اكتمال العمليات، حتى لو ظهر استثناء داخل الكتلة.

إليك كيفية إعادة كتابة المثال السابق باستخدام عبارة with:

with open("example.txt", "r") as file:
    content = file.read()
# the file is automatically closed here

في هذا الكود، يفتح السطر with open("example.txt", "r") as file: الملف، ويصبح الملف هو الاسم الذي نستخدمه للإشارة إلى كائن الملف. ثم نقرأ محتويات الملف في متغير content. بعد انتهاء كتلة with، تقوم بايثون تلقائيًا باستدعاء file.close()، حتى لو حدث خطأ داخل الكتلة.

عبارة with هي مثال على بروتوكول إدارة السياق في بايثون. يمكن استخدام الكائنات التي لها أسلوبان  __enter__ و  __exit__ محددان في عبارة with. يتم استدعاء الأسلوب __enter__ في بداية الكتلة، ويتم استدعاء الأسلوب __exit__ في النهاية، مما يسمح بتحديد إجراءات التنظيف الضرورية.

عند التعامل مع الملفات في بايثون، من الممارسات الجيدة استخدام عبارة with دائمًا. فهو يوفر طريقة نظيفة وفعالة لإدارة موارد الملفات ويساعد على منع تسرب الموارد من خلال ضمان إغلاق الملفات بشكل صحيح بعد الاستخدام.

6 عدم استخدام البيئات الافتراضية

تخيل أنك تعمل على عدة مشاريع على نفس النظام، ولكل منها مجموعته الفريدة من التبعيات وإصدارات الحزمة. الآن، تخيل تثبيت كل هذه التبعيات على مستوى النظام. قريبًا، قد تجد نفسك تتعامل مع تعارضات في إصدار الحزمة، ومشاريع معطلة، والكثير من المشاكل.

هذا السيناريو شائع جدًا بين مطوري بايثون، وخاصة المبتدئين الذين قد لا يكونون على دراية بفوائد البيئات الافتراضية. إذا وجدت نفسك في هذا الموقف من قبل، فهذا ليس خطأك، ولكن هناك طريقة أفضل لإدارة مشاريع بايثون.

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

تأتي Python مع وحدة مدمجة لإنشاء بيئات افتراضية: venv. إليك كيفية إنشاء بيئة افتراضية باستخدام venv:

# Create a new virtual environment
python3 -m venv my_env

# Activate the virtual environment
source my_env/bin/activate  # On Unix or MacOS
my_env\Scripts\activate     # On Windows

بعد تنشيط بيئتك الافتراضية، سيتم تثبيت أي حزم Python تقوم بتثبيتها باستخدام pip في البيئة الافتراضية، بشكل منفصل عن بيئة Python لعامة. للعودة إلى البيئة لعامة، يمكنك ببساطة إلغاء تنشيط البيئة الافتراضية:

deactivate  # Deactivate the virtual environment

أداة أخرى شائعة لإدارة البيئات الافتراضية في بايثون هي conda، والتي تم تضمينها في توزيعة Anaconda لبايثون. تحظى conda بشعبية خاصة بين علماء البيانات، لأنها تسهل تثبيت الحزم العلمية وإدارة التبعيات. إليك كيفية إنشاء بيئة افتراضية باستخدام conda:

# Create a new conda environment
conda create --name my_env

# Activate the conda environment
conda activate my_env

لإلغاء تنشيط بيئة conda والعودة إلى البيئة الأساسية، يمكنك استخدام الأمر conda deactivate.

تعد البيئات الافتراضية أداة مهمة لأي مطور بايثون. يمكنها إنقاذك من متاعب تعارضات إصدار الحزمة وتسهيل إدارة مشاريع Python. إذا كنت لا تستخدم البيئات الافتراضية بالفعل، فابدأ اليوم. لم يفت الأوان أبدًا لتبني عادات جيدة، وسوف تشكر نفسك في المستقبل.

7 عدم توثيق الكود

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

إذا لم تكن معتادًا على توثيق التعليمات البرمجية، فأنت لست وحدك. يميل الكثير منا إلى التفكير، “الكود واضح بذاته” أو “سأتذكر ما يفعله هذا”. الحقيقة هي أن التعليمات البرمجية نادرًا ما تكون واضحة بذاتها، وغالبًا ما نبالغ في تقدير قدرتنا على تذكر تفاصيل التعليمات البرمجية.

إذن كيف يمكننا تجنب هذا الخطأ؟ توفر Python العديد من الأدوات لمساعدتنا في توثيق الكود الخاص بنا بشكل فعال:

المستندات

تعد مستندات Python طريقة مضمنة لإرفاق الوثائق بالوحدات النمطية والدوال والفئات والأساليب. سلسلة المستندات هي سلسلة حرفية تظهر كالبيان الأول في تعريف الوحدة النمطية أو الدوال أو الفئة أو الأسلوب. يمكنك تعريف سلسلة مستندية باستخدام علامات الاقتباس الثلاثية، “”” “””.

فيما يلي مثال لكيفية استخدام سلاسل المستندات في دالة:

def add_numbers(a, b):
    """This function adds two numbers and returns the result.
    
    Args:
        a (int): The first number.
        b (int): The second number.
        
    Returns:
        int: The sum of the two numbers.
    """
    return a + b

في هذا المثال، تشرح سلسلة المستندات ما تفعله الدالة، وتصف وسيطات الدالة، وتشرح القيمة المرجعة. يمكنك الوصول إلى سلسلة المستندات هذه باستخدام السمة .__doc__ الخاصة بالدالة أو دالة help() المضمنة.

التعليقات

بينما يتم استخدام سلاسل المستندات للتوثيق عالي المستوى (مثل شرح دالة ما)، يتم استخدام التعليقات لتفسيرات المستوى الأدنى (مثل وصف جزء معقد من التعليمات البرمجية). في بايثون، يمكنك كتابة التعليقات باستخدام الرمز #:

def complex_calculation(x, y):
    # First, we calculate the square of x and y
    x2 = x ** 2
    y2 = y ** 2
    
    # Then, we add the squares
    result = x2 + y2
    
    return result

في هذا المثال، تصف التعليقات ما يفعله كل قسم من الكود. يمكن أن يكون هذا مفيدًا بشكل خاص للمطورين الآخرين الذين قد يحتاجون إلى صيانة التعليمات البرمجية الخاصة بك أو تعديلها في المستقبل.

كمبرمج بايثون، من الضروري أن تتبنى عادات توثيق جيدة. تذكر أن الغرض الأساسي من التوثيق هو شرح “السبب” وراء الكود. بينما يخبرنا الكود بما يحدث، تخبرنا الوثائق عن سبب حدوثه. لذا، كن كريمًا مع نفسك ومع المطورين الآخرين، وقم بتوثيق التعليمات البرمجية.

8 تعديل الأنواع القابلة للتغيير عن غير قصد

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

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

خذ بعين الاعتبار الكود التالي:

# Define a list
original_list = [1, 2, 3]

# Assign the original list to a new variable
new_list = original_list

# Change a value in the new list
new_list[0] = 99

# Print both lists
print(original_list)
print(new_list)

قد تتوقع أن تظل original_list كما هي [1، 2، 3]، ولكن هذا ليس هو الحال. حيث ستقوم كل عبارات print بإخراج [99، 2، 3]. وذلك لأن كلاً من new_list و original_list يشيران إلى نفس القائمة في الذاكرة. وأي تغييرات على أحدهما سوف تنعكس على الآخر.

وبالمثل، إذا قمت بتمرير كائن قابل للتغيير إلى دالة، فيمكن للدالة تعديل هذا الكائن، مما يؤثر على المتغير الأصلي. هنا مثال:

# Define a function to append an element to a list
def append_four(input_list):
    input_list.append(4)
    return input_list

# Define a list
my_list = [1, 2, 3]

# Call the function with the list
new_list = append_four(my_list)

# Print the original list
print(my_list)

في هذا المثال،بعد تنفيذprint(my_list) سيكون الناتج [1, 2, 3, 4] على الرغم من أن التعديل حدث داخل الدالة.

إذًا، كيف يمكننا تجنب تحور الكائنات القابلة للتغيير عن غير قصد؟ المفتاح هو فهم سلوك الكائنات القابلة للتغيير وعمل نسخ عند الضرورة.

في المثال الأول، يمكنك استخدام مُنشئ list() أو copy() لإنشاء قائمة جديدة:

# Create a new list that's a copy of the original
new_list = list(original_list)

# OR

# Create a new list that's a copy of the original
new_list = original_list.copy()
In the function example, if you don’t want append_four() to modify the original list, you could create a copy of the list inside the function:

def append_four(input_list):
    # Create a copy of the input list
    input_list = list(input_list)
    
    input_list.append(4)
    return input_list

من المهم أن نفهم الفرق بين الأنواع القابلة للتغيير والأنواع غير القابلة للتغيير في بايثون وكيف تتصرف. تذكر عمل نسخ من الكائنات القابلة للتغيير عند الضرورة لتجنب الآثار الجانبية غير المرغوب فيها. يمكن أن يساعدك هذا الفهم في كتابة تعليمات برمجية أكثر قوة وخالية من الأخطاء.

9 عدم التعامل مع الاستثناءات بشكل صحيح

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

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

تأتي بايثون، مثل العديد من لغات البرمجة الحديثة، مزودة بآلية مدمجة للتعامل مع الاستثناءات: else و except، try، و عبارة finally.

خذ بعين الاعتبار البرنامج البسيط التالي:

def divide_numbers(x, y):
    return x / y

print(divide_numbers(4, 2))
print(divide_numbers(4, 0))
The above code will crash when it encounters the division by zero. The program’s abrupt termination is not only an issue for the user but also makes debugging difficult. Now, let’s handle the exception:

def divide_numbers(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("You can't divide by zero!")
        return None
    else:
        return result

print(divide_numbers(4, 2))
print(divide_numbers(4, 0))

في التعليمات البرمجية المحدثة، تحتوي كتلة try على التعليمات البرمجية التي قد تؤدي إلى حدوث استثناء. تحتوي كتلة except على الكود الذي سيتم تنفيذه في حالة حدوث استثناء محدد، في هذه الحالة، ZeroDivisionError. يتعامل البرنامج الآن مع الخطأ بأمان، ويتم تزويد المستخدم برسالة مفيدة.

ماذا لو أردنا أن نفعل شيئًا بغض النظر عما إذا حدث استثناء أم لا؟ هنا يأتي دور كتلة finally:

def divide_numbers(x, y):
    try:
        result = x / y
    except ZeroDivisionError:
        print("You can't divide by zero!")
        return None
    finally:
        print("The divide_numbers function was called")

print(divide_numbers(4, 2))
print(divide_numbers(4, 0))

سيتم تنفيذ كتلة finally مهما حدث، مما يجعلها المكان المناسب لوضع أي كود تنظيف أو كود تريد تشغيله بغض النظر عما إذا حدث خطأ ما.

كمطورين لـ Python، من المهم بالنسبة لنا توقع الأخطاء المحتملة والتعامل معها بشكل مناسب. تذكر أن معالجة الاستثناءات في بايثون لا تتعلق فقط بمنع الأعطال؛ يتعلق الأمر أيضًا بتوفير رسائل خطأ واضحة، وهو أمر لا يقدر بثمن لتصحيح الأخطاء والصيانة. إن استخدام آليات معالجة الاستثناءات في Python بحكمة يمكن أن يؤدي إلى برامج أكثر قوة وقابلة للصيانة وسهلة الاستخدام.

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

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

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

أحد مصطلحات Python الأخرى هو الاستخدام الصحيح لعبارة “with” عند التعامل مع الملفات، أو استخدام قوة فهم القائمة و الدوال المضمنة لمعالجة البيانات بكفاءة. ولعل أحد أهم المصطلحات هو الاستخدام الدقيق والمراعي لآليات معالجة الأخطاء مثل try و except للتأكد من أن برنامجك لا يعمل فقط كما هو متوقع في الظروف العادية ولكن يمكنه أيضًا التعامل مع ما هو غير متوقع بأمان.

بينما تستمر في رحلة برمجة بايثون، ضع هذه الأخطاء الشائعة وحلولها في الاعتبار. فكر في عادات وأنماط البرمجة الخاصة بك – هناك دائمًا مجال للتحسين. تذكر أنه لا بأس في ارتكاب الأخطاء طالما أنك تتعلم منها.

لكي تصبح مبرمجًا عظيمًا في لغة بايثون، من الضروري أن تكون أكثر من مجرد عالم باللغة. يفهم مبرمج Python الرائع أفضل الممارسات ويتبعها، ويكتب تعليمات برمجية نظيفة وفعالة وقابلة للصيانة، ويسعى دائمًا إلى التعلم والنمو.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

اكتشاف المزيد من بايثون العربي

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

Continue reading

Scroll to Top