if x > 5
print("x")
Cell In[1], line 1 if x > 5 ^ SyntaxError: expected ':'
ينقسم الخطأ لثلاثة أنواع:
نتحدث في هذا الفصل عن الخطأ النحوي والمنطقي، ونستكمل الحديث عن خطأ وقت التشغيل في حديثنا عن الاستثناء.
الأخطاء النحوية تتعلق بتركيب اللغة لا أكثر ولا أقل. إليك ثلاثة أمثلة.
:
لاحظ عدم النقطيتن بعد الشرط (if x > 5
).
if x > 5
print("x")
Cell In[1], line 1 if x > 5 ^ SyntaxError: expected ':'
لاحظ عدم علامة الاقتباس ("
) للنص.
print("x
Cell In[2], line 1 print("x ^ SyntaxError: unterminated string literal (detected at line 1)
لاحظ أن بايثون تسمح بالشرطة السفلية (_
) لكن هنا ستعملنا الشرطة (-
) التي يظنها علامة طرح.
-variable = 10 my
Cell In[3], line 1 my-variable = 10 ^ SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='?
من الأخطاء النحوية الشائعة في بايثون: خطأ المحاذاة (Indentation Error).
وذلك أن بايثون تقبل نوعين من المسافات البادئة للسطر:
\s
\t
ويحصل الخلط بينهما من غير قصد عند النسخ واللصق من هنا وهناك. وهذا مما لا تقبله بايثون. لذلك تضبط محررات النصوص عملية النسخ واللصق فتوحِّد المسافة البادئة بأحدهما، حتى لا نهتم لذلك نحن. فهي حروف خفيَّة.
وإليك بعض الأمثلة لما يحصل من أخطاء في المحاذاة:
if True:
print("x")
Cell In[4], line 2 print("x") ^ IndentationError: expected an indented block after 'if' statement on line 1
if True:
print("x")
print('y')
Cell In[5], line 3 print('y') ^ IndentationError: unexpected indent
من تجويد العبارة تسمية المتغيرات بما يدل على وظيفتها، مثل:
= 50
rate = 6
hours_per_day = 5
days = rate * hours_per_day * days
pay print(pay)
1500
وإن كان ليس من الخطأ النحوي كتابتها بطريقة مختلفة وبأسماء غير معبِّرة، إلا أنه فعلٌ غير مستحسن:
= 50, 6, 5
r, hpd, d = r * hpd * d
p print(p)
1500
وفي هذا نصائح كثيرة، يراجع فيها دليل أسلوب الكتابة في بايثون.
وهي التي نقصدها حين نقول: بَق (Bug) بمعنى: مشكلة في البرنامج. ويسمى البرنامج الذي يساعد في إصلاح المشاكل البرمجية: المدقق (Debugger). وتسمى وعملية البحث عنها وإصلاحها: التدقيق (Debugging).
الأخطاء المنطقية صامتة. إذ لا يكتشفها المترجم، وتتسبب في تصرف البرنامج بشكل غير صحيح. الأخطاء المنطقية هي الأصعب في التتبع والإصلاح لأنها ليست واضحة. يمكن أن تكون ناجمة عن:
وإليك بعض الأمثلة ..
هنا يريد المبرمج استعمال دالَّة التربيع (Square) فظنَّها math.sqrt
لكن هذه (Square Root) أي: الجذر التربيعي. والصحيح أن يختار: math.pow(4, 2)
لرفع 4
للقوة 2
.
import math
= math.sqrt(4) square
هنا تمَّت المقارنة بين نوعين مختلفين أصلاً: int
و str
لكنَّ المبرمج لم يستوعِب ذلك، فحصل الخطأ وهو لا يدري لماذا x
لا تساوي y
عندما يكون كلاهما 16
؟ وهذا قد يبدو لك واضحًا وذلك لأننا عزلنا المثال عن غيره من التفاصيل فظهر جليًّا.
= 16
x = "16"
y if (x == y):
print('equal')
هنا كانت النية تقتضي أن تكون print(j)
داخل الحلقة الداخلية. لكن إن كانت النيَّة كما كُتب فليس بخطأ طبعًا.
for i in range(2):
for j in range(3):
print(i)
print(j)
0
0
0
2
1
1
1
2
خطأ الحافَّة (Off-by-one error)، يكاد يكون أشهر الأخطاء في البرمجة.
نشرحه بمثال: النية هنا هي طباعة الأرقام بالعكس من الرقم الأعلى (5) إلى (0) بما في ذلك (0)، ولكن الحلقة تتوقف عند (1). وذلك أن آلية عمل النطاق (range
) عدم شمول النهاية.
for i in range(5, 0, -1):
print(i)
5
4
3
2
1
لكونها جملاً صحيحة في ذاتها؛ لا يستطيع البرنامج كشف هذه الأخطاء لوحده. بل يجب على من يُدركُ حقيقة المطلوب من البرنامج أن يتكفل بذلك. وهنا تكون الحاجة ماسَّة لجمل التوكيد: assert
وقد رأيناها كثيرًا.
والتدقيق؛ إذْ أفضل طريقة لحل الأخطاء المنطقية هي تنفيذ القطعة البرمجية والنظر في الناتج، وتتبع المنطق مرة أخرى إلى النص البرمجي سطرًا بسطر. يمكنك استخدام عبارات الطباعة print
لتصحيح الأخطاء وفهم تدفق البرنامج. وقد يكون الأفضل من ذلك استعمال المدقق (Debugger).
ومراجعة الأقران: بحيث يطلع على النص البرمجي شخص آخر، فإنه قد يرى منه ما تعذر عليك رؤيته. وقد يتم تنظيمه بين أعضاء الفريق الواحد بأحد برمجيات التعاون مثل: GitHub وGitLab وBitbucket وغيرها. لكن ليس شرطًا أن يكون بطريقة منظَّمة حتى تستفيد منه.