Table of Contents
دستهبندی خطاهای رایج مبتدیان
در این بخش روی الگوهای اشتباهی تمرکز میکنیم که تقریباً همهٔ برنامهنویسهای مبتدی با آنها روبهرو میشوند. هدف این است که آنها را بشناسید، سریعتر تشخیصشان دهید و بدانید چطور از تکرارشان جلوگیری کنید.
در مثالها فرض میکنیم قبلاً میدانید خطا چیست و پیام خطا را چطور بهطور کلی میخوانیم؛ اینجا سراغ مصداقهای پرتکرار میرویم.
۱. جا انداختن دونقطه (:) و مشکل تورفتگی (Indentation)
۱.۱. فراموش کردن `:` بعد از ساختارهای کنترلی
در if, elif, else, for, while, def, class باید در انتهای خط، : بگذارید.
مثال اشتباه:
if x > 10
print("بزرگتر از ۱۰ است")
پیام معمول: SyntaxError: expected ':'
نسخهٔ درست:
if x > 10:
print("بزرگتر از ۱۰ است")
همین اشتباه برای for, while, def, class هم تکرار میشود.
۱.۲. تورفتگیهای نامنظم
پایتون روی فاصلهٔ ابتدای خط (indentation) بسیار حساس است. قاطیکردن فاصلهها (space) و تب (tab) یا تورفتگی نامساوی باعث خطا میشود.
مثال اشتباه:
if x > 10:
print("خط ۱")
print("خط ۲")
پیام معمول: IndentationError: unexpected indent یا IndentationError: unindent does not match any outer indentation level
نکات پیشگیری:
- از یک نوع فاصله استفاده کنید (ترجیحاً فقط space، مثلاً ۴ space برای هر سطح).
- در ویرایشگر، گزینهٔ «نمایش فاصله و تب» را فعال کنید.
- اگر خط کدی را کپی میکنید، مطمئن شوید تورفتگیاش با بقیه یکی است.
۲. اشتباه در نامها: حروف کوچک/بزرگ و غلطنوشتن متغیرها
۲.۱. استفاده از نام اشتباه متغیر یا تابع
پایتون به حروف کوچک و بزرگ حساس است (case-sensitive). NameError وقتی رخ میدهد که پایتون متغیر/تابع را نمیشناسد.
مثال اشتباه:
age = 20
print(Age)
پیام: NameError: name 'Age' is not defined
نسخهٔ درست:
age = 20
print(age)یا:
userName = "Ali"
print(username) # اشتباه در املای نام۲.۲. تعریفنکردن متغیر قبل از استفاده
گاهی اسم را درست نوشتهاید، اما اصلاً قبلش تعریفش نکردهاید.
print(total)
total = 100
پیام: NameError: name 'total' is not defined
ترتیب درست:
total = 100
print(total)۳. قاطیکردن `=` با `==`
=برای نسبتدادن مقدار به متغیر است.==برای مقایسهٔ برابری.
مثال اشتباه (در شرط):
x = 5
if x = 5:
print("x پنج است")
پیام: SyntaxError: invalid syntax
نسخهٔ درست:
x = 5
if x == 5:
print("x پنج است")
برعکسش هم اتفاق میافتد: بعضیها میخواهند مقدار بدهند ولی از == استفاده میکنند و برنامه رفتار مورد انتظار را ندارد.
x == 10 # فقط مقایسه است، مقداردهی نمیکند۴. نوع دادهٔ نامناسب در عملگرها
این دستهٔ خطا معمولاً TypeError میدهد.
۴.1. جمعکردن عدد و رشته
age = 20
text = "سن شما: " + age
پیام: TypeError: can only concatenate str (not "int") to str
نسخهٔ درست (تبدیل به رشته):
age = 20
text = "سن شما: " + str(age)
print(text)یا با قالببندی (که در فصل ورودی/خروجی بیشتر دیدهاید):
age = 20
print(f"سن شما: {age}")۴.۲. تبدیل ورودی کاربر بدون توجه به نوع
تابع input() همیشه رشته برمیگرداند. اگر آن را مستقیم با عدد جمع کنید:
x = input("عدد را وارد کنید: ")
result = x + 10
پیام: TypeError: can only concatenate str (not "int") to str
برای حل، ورودی را به عدد تبدیل کنید (اگر انتظار عدد دارید):
x = int(input("عدد را وارد کنید: "))
result = x + 10
print(result)۵. اشتباه در استفاده از پرانتز، کروشه و آکولاد
۵.۱. پرانتز بستهنشده یا زیادبستن
مثال اشتباه:
print("سلام"
پیام: SyntaxError: '(' was never closed یا مشابه.
مثال اشتباه دیگر:
print(("سلام"))
)
پیام: SyntaxError: unmatched ')'
برای جلوگیری:
- وقتی
(میگذارید، بلافاصله)را هم بنویسید و وسطشان را بعداً پر کنید. - ویرایشگرهایی انتخاب کنید که پرانتزها را جفتجفت نشان میدهند.
۵.۲. قاطیکردن `()` و `[]` و `{}`
هرکدام کاربرد خودشان را دارند:
[]برای لیست و اندیسدهی()برای فراخوانی تابع و گروهبندی{}برای دیکشنری و مجموعه
مثال اشتباه:
numbers = [1, 2, 3]
print(numbers(0)) # اشتباه
پیام: TypeError: 'list' object is not callable
درست:
numbers = [1, 2, 3]
print(numbers[0])یا:
person = {"name": "Ali"}
print(person("name")) # اشتباهباید بنویسید:
print(person["name"])۶. استفادهٔ اشتباه از اندیسها در لیست و رشته
۶.۱. خارج از محدوده (IndexError)
مثال:
numbers = [10, 20, 30]
print(numbers[3])
اندیسهای معتبر: 0, 1, 2؛ اندیس 3 وجود ندارد.
پیام: IndexError: list index out of range
نسخهٔ درست:
numbers = [10, 20, 30]
print(numbers[2]) # آخرین عنصریا قبل از دسترسی، طول را چک کنید:
index = 3
if index < len(numbers):
print(numbers[index])
else:
print("چنین اندیسی وجود ندارد")۶.۲. فرضگرفتن اینکه رشته/لیست خالی نیست
مثال:
text = ""
print(text[0])
پیام: IndexError: string index out of range
راه حل: قبل از دسترسی، چک کنید خالی نباشد:
if text:
print(text[0])
else:
print("رشته خالی است")۷. اشتباه در حلقهها: حلقهٔ بینهایت و شمارندهٔ اشتباه
۷.۱. حلقهٔ بینهایت ناخواسته
مثال:
x = 0
while x < 5:
print(x)
# فراموش کردهایم x را تغییر دهیماین حلقه هرگز تمام نمیشود.
درست:
x = 0
while x < 5:
print(x)
x = x + 1۷.۲. تغییر دادن لیست هنگام پیمایش با `for`
مثال اشتباه:
numbers = [1, 2, 3, 4]
for n in numbers:
if n % 2 == 0:
numbers.remove(n)
print(numbers)نتیجه معمولاً چیزی است که انتظار ندارید. این خطانمای منطقی است، نه لزوماً خطای اجرایی.
برای حذف امن، یا روی یک کپی حلقه بزنید:
numbers = [1, 2, 3, 4]
for n in numbers[:]:
if n % 2 == 0:
numbers.remove(n)یا از روشهای دیگر (مثل ساختن لیست جدید) استفاده کنید.
۸. اشتباه در شرطها و عملگرهای منطقی
۸.۱. شرط همیشه درست یا همیشه غلط
مثال:
age = 20
if age > 18 or age < 10:
print("شرط برقرار است")
در نگاه اول شاید معنیدار بهنظر برسد، اما برای خیلی از مقادیر، شرط تقریباً همیشه درست است. اغلب از and باید استفاده شود.
اگر میخواستید بگویید «بزرگتر از ۱۸ و کوچکتر از ۱۰ نیست»، باید منطق را دقیق بررسی کنید.
۸.۲. استفاده از `=` بهجای `==` در شرط (که قبلاً گفتیم)
این هم همزمان خط سینتکسی و منطقی است؛ هم اجرا نمیشود، هم به معنی موردنظر نیست.
۹. تکرار نام توابع و متغیرها روی نامهای داخلی
۹.۱. بازنویسی توابع داخلی پایتون
مثال:
print = "سلام"
print("چاپ کن")
پیام: TypeError: 'str' object is not callable
چون حالا print دیگر تابع نیست، یک رشته است.
مشابه این اشتباه با list, str, sum, max و... هم رخ میدهد:
list = [1, 2, 3]
new_list = list("abc") # اینجا دیگر تابع list را نداریمراهحل:
- از نامهای عمومی داخلی برای متغیرهای خود استفاده نکنید.
- اگر اشتباهی نام را خراب کردید، در همان نشست تعاملی میتوانید با
delپاکش کنید:
del print(اما در اسکریپت بهتر است از اول نام مناسبی انتخاب کنید.)
۱۰. فراموشکردن پرانتز در فراخوانی تابع
وقتی تابع را میخواهید اجرا کنید، باید () را اضافه کنید؛ در غیر این صورت فقط به خود شیٔ تابع اشاره میکنید.
مثال:
def say_hello():
print("سلام")
say_hello # هیچچیزی چاپ نمیشوددرست:
say_hello()
این اشتباه در input, print و توابع کتابخانهها هم زیاد رخ میدهد.
۱۱. اشتباه در استفاده از `return` در توابع
۱۱.۱. چاپ به جای بازگرداندن مقدار
مثال:
def add(a, b):
print(a + b)
result = add(2, 3)
print(result)خروجی:
- روی صفحه:
5 - ولی
resultبرابر باNoneاست (چونreturnنکردهایم).
اگر میخواهید مقدار در متغیر ذخیره شود، باید return کنید:
def add(a, b):
return a + b
result = add(2, 3)
print(result)۱۱.۲. فراموشکردن `return` در بعضی مسیرهای تابع
مثال:
def check_positive(x):
if x > 0:
return "مثبت است"
# در غیر این صورت چیزی برنمیگرداند
print(check_positive(-5)) # Noneبهتر است در همهٔ مسیرها مقدار برگردانده شود:
def check_positive(x):
if x > 0:
return "مثبت است"
else:
return "مثبت نیست"۱۲. اشتباه در کار با فایلها
۱۲.۱. فراموشکردن بستن فایل
گرچه در عمل خیلی وقتها برنامه کوچک است و مشکلی ایجاد نمیکند، اما عادت بدی است.
مثال (روش ضعیف):
f = open("data.txt", "r")
content = f.read()
# فراموش کردهایم f.close() را صدا بزنیم
روش استاندارد (با with — توضیح کاملش در فصل فایلها):
with open("data.txt", "r") as f:
content = f.read()۱۲.۲. بازکردن فایل در حالت اشتباه
مثال:
f = open("data.txt", "r")
f.write("سلام")
پیام: io.UnsupportedOperation: not writable
برای نوشتن باید حالت را w یا a بگذارید:
with open("data.txt", "w") as f:
f.write("سلام")۱۳. بدفهمی پیام خطا و نادیدهگرفتن خط آخر
یک خطای تکراری مبتدیان این است که:
- فقط به اولین خط پیام خطا نگاه میکنند،
- یا کل متن را نادیده میگیرند و فقط «کار نمیکند» میگویند.
نکتههای عملی:
- همیشه خط آخر پیام خطا را بخوانید؛ آنجا نوع خطا و جملهٔ توضیحی کوتاه نوشته شده.
- خط قبل از آن معمولاً شمارهٔ خط و نام فایل را نشان میدهد؛ همانجا را بررسی کنید.
- اگر از اینترنت کمک میگیرید، متن کامل خطا را (بدون اطلاعات شخصی) جستوجو کنید.
مثال پیام خطا:
Traceback (most recent call last):
File "test.py", line 3, in <module>
print(x)
NameError: name 'x' is not definedبرای تمرین، سعی کنید:
- نوع خطا را بگویید (
NameError), - در کدام فایل (
test.py), - در کدام خط (
line 3), - دلیل کوتاه (
name 'x' is not defined).
۱۴. راهبردهای ساده برای جلوگیری از خطاهای رایج
در کنار فصل «راهبردهای اشکالزدایی»، چند توصیه مخصوصِ همین خطاهای مبتدیانه:
- کد را تکهتکه بنویسید و اجرا کنید
بهجای نوشتن ۵۰ خط و بعد اجرا، هر ۳–۵ خط یک بار برنامه را اجرا کنید. - از چاپ (
print) برای فهمیدن وضعیت استفاده کنید
وقتی نتیجه عجیب است، در بخشهای مهم مقدار متغیرها را چاپ کنید. - به پیامهای خطا احترام بگذارید
قبل از هر کاری، آرام پیام را بخوانید و کلمههای کلیدیاش را ترجمه یا جستوجو کنید. - نام متغیرها و توابع را معنیدار انتخاب کنید
این کار هم جلویNameErrorمیگیرد، هم خوانایی را بالا میبرد. - از ویرایشگر مناسب استفاده کنید
ویرایشگری که: - تورفتگی را نشان دهد،
- پرانتزها را جفت کند،
- کلمات کلیدی را رنگی کند،
کمک زیادی برای جلوگیری از خطاهای نحوی میکند.
با شناختن این الگوهای تکراری، بهمرور قبل از اینکه خطا رخ دهد، آن را در ذهنتان تشخیص میدهید و کد شما تمیزتر و پایدارتر میشود.