قد تكتب قائمة في Python، ثم تحاول قراءة عنصر منها، فتظهر لك رسالة مزعجة مثل:
IndexError: list index out of range
هذا الخطأ من أكثر أخطاء القوائم شيوعًا عند المبتدئين. لا يعني أن القائمة غير صحيحة، بل يعني أن الكود طلب عنصرًا برقم فهرس index غير موجود داخلها. يحدث ذلك عادةً لأن الفهرسة تبدأ من الصفر، أو بسبب استخدام len() بطريقة غير صحيحة، أو بسبب حلقة for تتجاوز آخر عنصر، أو لأن القائمة أصبحت فارغة دون أن تنتبه.
في هذا الدرس ستفهم معنى الخطأ خطوة بخطوة، وستتعلم كيف تشخصه بسرعة وتمنعه من الظهور في مشاريعك بدل أن تكتفي بإخفائه.
{alertInfo} الفكرة ببساطة: إذا كانت القائمة تحتوي علىnعناصر، فإن آخر index صالح هوn - 1وليسn. لذلك إذا كان طول القائمة3، فالفهارس الصحيحة هي0و1و2فقط.
{getToc} $title={محتوى المقال}
ما معنى IndexError: list index out of range؟
كلمة IndexError تعني أن Python حاولت الوصول إلى موضع غير موجود داخل تسلسل مرتب مثل list أو tuple أو string. وفي هذه المشكلة تحديدًا، الجزء:
list index out of range
يخبرك أن الرقم الذي استخدمته بين الأقواس المربعة [] أكبر من آخر فهرس موجود في القائمة، أو أن القائمة فارغة.
مثال:
colors = ["red", "blue", "green"]
print(colors[3])
سيظهر الخطأ لأن القائمة تحتوي ثلاثة عناصر فقط، وفهارسها هي 0 و1 و2. لا يوجد عنصر في الموضع 3.
Traceback (most recent call last):
...
IndexError: list index out of range
لماذا تبدأ فهرسة القوائم من الصفر؟
في Python، أول عنصر في القائمة يأخذ الفهرس 0 وليس 1. هذا يسمى zero-based indexing.
languages = ["Python", "JavaScript", "Java", "C++"]
print(languages[0])
print(languages[1])
print(languages[2])
print(languages[3])
Python
JavaScript
Java
C++
| العنصر | الفهرس الصحيح |
|---|---|
"Python" |
0 |
"JavaScript" |
1 |
"Java" |
2 |
"C++" |
3 |
لذلك إذا حاولت الوصول إلى languages[4]، سيظهر الخطأ لأن الرقم 4 خارج نطاق القائمة.
الفرق بين len(list) وآخر index
الدالة len() تعطيك عدد العناصر داخل القائمة، لكنها لا تعطيك آخر index مباشرة.
names = ["Ali", "Sara", "Omar"]
print(len(names))
3
قد يظن البعض أن هذا يعني أن:
print(names[len(names)])
سيطبع العنصر الأخير، لكنه سيظهر خطأ. السبب أن len(names) تساوي 3، بينما آخر index صالح يساوي 2.
إذا أردت آخر عنصر باستخدام الطول، اكتب:
print(names[len(names) - 1])
لكن الطريقة الأبسط والأوضح غالبًا هي استخدام الفهرس السالب -1:
print(names[-1])
Omar
الفهرس -1 يعني آخر عنصر، و-2 يعني العنصر الذي قبله. لكن انتبه: إذا كانت القائمة فارغة، فإن names[-1] سيظهر أيضًا خطأ IndexError.
السبب الأول: طلب عنصر برقم أكبر من آخر index
هذا هو السبب المباشر والأكثر وضوحًا.
مثال خاطئ
fruits = ["apple", "banana"]
print(fruits[2])
الفهارس المتاحة هنا هي 0 و1 فقط.
الحل
استخدم فهرسًا موجودًا:
print(fruits[1])
أو افحص أن الفهرس ضمن المدى قبل الوصول إليه:
index = 2
if 0 <= index < len(fruits):
print(fruits[index])
else:
print("هذا الفهرس غير موجود داخل القائمة.")
السبب الثاني: استخدام range(len(list) + 1) داخل for loop
هذا الخطأ منتشر جدًا. الدالة range() لا تشمل الرقم الأخير، لذلك عندما تريد المرور على الفهارس الصحيحة لقائمة، تكتب:
for index in range(len(items)):
print(items[index])
لكن بعض المبتدئين يكتبون:
for index in range(len(items) + 1):
print(items[index])
دعنا نطبق ذلك على قائمة من ثلاثة عناصر:
items = ["A", "B", "C"]
for index in range(len(items) + 1):
print(items[index])
هنا ستنتج range(4) الأرقام 0 و1 و2 و3. والفهرس 3 غير موجود، لذلك يظهر الخطأ في آخر دورة.
الحل الأول: احذف + 1
for index in range(len(items)):
print(items[index])
الحل الأفضل في أغلب الحالات: مرّ على العناصر مباشرة
إذا كنت لا تحتاج إلى رقم الفهرس، لا تستخدمه من الأساس:
for item in items:
print(item)
وإذا احتجت العنصر ورقمه معًا: استخدم enumerate
for index, item in enumerate(items):
print(index, item)
0 A
1 B
2 C
السبب الثالث: القائمة فارغة
حتى لو استخدمت فهرسًا صحيحًا مثل 0 أو -1، سيظهر الخطأ إذا لم تكن القائمة تحتوي على أي عنصر.
tasks = []
print(tasks[0])
الحل هو التحقق من وجود عناصر أولًا:
if tasks:
print(tasks[0])
else:
print("لا توجد مهام داخل القائمة.")
في Python، القائمة الفارغة تعتبر قيمة False داخل شرط if، والقائمة التي تحتوي على عنصر واحد على الأقل تعتبر True.
السبب الرابع: استخدام pop على قائمة فارغة
الدالة pop() تزيل عنصرًا من القائمة وتعيده. إذا استدعيتها على قائمة فارغة، ستظهر IndexError.
cart = []
last_item = cart.pop()
اكتب التحقق أولًا:
if cart:
last_item = cart.pop()
print(f"تم حذف: {last_item}")
else:
print("السلة فارغة، لا يوجد عنصر لحذفه.")
كذلك، pop(index) سيظهر الخطأ إذا كان index خارج نطاق القائمة.
السبب الخامس: القائمة تغيرت داخل الحلقة
قد تحسب طول القائمة، ثم تحذف عناصر منها داخل الحلقة، ثم تحاول استخدام الفهارس القديمة. هذا قد يسبب تجاوزًا للنطاق.
مثال يحتاج حذرًا
numbers = [10, 20, 30, 40]
for index in range(len(numbers)):
if numbers[index] > 20:
numbers.pop(index)
عند حذف عنصر، تقصر القائمة وتتحرك العناصر. لذلك قد يصبح index الذي ستصل إليه في دورة لاحقة غير صالح.
حل واضح: أنشئ قائمة جديدة
numbers = [10, 20, 30, 40]
filtered_numbers = []
for number in numbers:
if number <= 20:
filtered_numbers.append(number)
print(filtered_numbers)
أو استخدم list comprehension عندما تصبح مرتاحًا معها:
filtered_numbers = [number for number in numbers if number <= 20]
الفرق بين indexing وslicing مهم جدًا
الوصول إلى عنصر واحد باستخدام indexing مثل:
letters = ["A", "B", "C"]
print(letters[10])
سيظهر خطأ لأن العنصر غير موجود.
لكن slicing مثل:
print(letters[10:])
لا يظهر خطأ عادة، بل يعيد قائمة فارغة:
[]
السبب أن slicing تتعامل بلطف مع الحدود خارج نطاق التسلسل، بينما indexing يتطلب عنصرًا موجودًا فعلًا في الموضع المطلوب.
هل أستخدم try وexcept لحل IndexError؟
يمكن استخدام try وexcept عندما يكون غياب العنصر احتمالًا طبيعيًا في برنامجك، لكن لا تستخدمها لإخفاء خطأ في منطق الكود.
مثال مناسب:
messages = []
try:
latest_message = messages[-1]
print(latest_message)
except IndexError:
print("لا توجد رسائل حتى الآن.")
لكن في كثير من الحالات، يكون شرط واضح أسهل في القراءة:
if messages:
print(messages[-1])
else:
print("لا توجد رسائل حتى الآن.")
{alertWarning}
نصيحة مهمة: لا تكتب except IndexError: pass فقط لإخفاء المشكلة. حاول أولًا معرفة لماذا وصل الكود إلى فهرس غير صالح، ثم ضع معالجة مفهومة للمستخدم أو صحح منطق الحلقة.
مثال عملي: اختيار عنصر من قائمة بطريقة آمنة
البرنامج التالي يعرض قائمة دورات، ثم يسمح للمستخدم باختيار دورة برقم يبدأ من 1. نطرح 1 لأن فهارس Python تبدأ من الصفر، ونتحقق من أن الرقم ضمن النطاق قبل الوصول إلى القائمة.
courses = [
"أساسيات بايثون",
"القوائم في Python",
"الدوال في Python",
"البرمجة كائنية التوجه"
]
for number, course in enumerate(courses, start=1):
print(f"{number}. {course}")
try:
user_choice = int(input("اختر رقم الدورة: "))
index = user_choice - 1
if 0 <= index < len(courses):
print(f"اخترت: {courses[index]}")
else:
print("اختر رقمًا من القائمة الظاهرة فقط.")
except ValueError:
print("الرجاء إدخال رقم صحيح.")
هذا المثال يعالج مشكلتين مختلفتين:
ValueErrorإذا أدخل المستخدم نصًا بدل رقم.- التحقق من index قبل الوصول إلى القائمة لتجنب
IndexError.
خطوات تشخيص الخطأ بسرعة
- اقرأ السطر الذي يشير إليه traceback؛ غالبًا ستجد فيه
list[index]أوlist.pop(index). - اطبع القائمة وطولها مؤقتًا باستخدام
print(items)وprint(len(items)). - اطبع قيمة index قبل استخدامه.
- تأكد أن القيمة تحقق الشرط
0 <= index < len(items). - إذا كانت داخل حلقة، راجع
range()وتأكد أنك لم تكتب+ 1دون حاجة. - إذا كنت تحذف عناصر، لا تعتمد على فهارس قديمة بعد أن يتغير طول القائمة.
أخطاء قريبة من IndexError
| الخطأ | المعنى المختصر | مثال شائع |
|---|---|---|
IndexError |
طلب موضع غير موجود داخل list أو string أو tuple. | items[10] مع قائمة قصيرة. |
KeyError |
طلب مفتاح غير موجود داخل dictionary. | user["email"] عندما لا يوجد المفتاح. |
ValueError |
القيمة غير مناسبة للعملية المطلوبة. | int("12a"). |
TypeError |
استخدمت نوعًا غير مناسب في عملية ما. | محاولة استخدام فهرس نصي مع list. |
يمكنك مراجعة مشكلة وحل 18: حل خطأ ValueError عند تحويل النص إلى رقم لفهم أحد الأخطاء القريبة التي تظهر كثيرًا مع إدخال المستخدم.
روابط داخلية مفيدة من بايثون العرب
- سلسلة مشكلة وحل في بايثون
- بايثون بالمثال 14: عدّ تكرار العناصر في List باستخدام Python
- مشكلة وحل 18: حل خطأ ValueError عند تحويل النص إلى رقم
- كورس أساسيات بايثون للمبتدئين
الخلاصة
- خطأ
IndexError: list index out of rangeيعني أنك طلبت عنصرًا غير موجود داخل القائمة. - الفهارس تبدأ من
0، لذلك آخر index في قائمة طولهاnهوn - 1. - لا تستخدم
items[len(items)]للوصول إلى العنصر الأخير؛ استخدمitems[-1]بعد التأكد أن القائمة ليست فارغة. - استخدم
range(len(items))بدون+ 1، أو مرّ على العناصر مباشرة باستخدامfor item in items. - تحقق من القوائم الفارغة قبل استخدام
[0]أو[-1]أوpop(). - استخدم
try/exceptلمعالجة حالة متوقعة، وليس لإخفاء خطأ في منطق البرنامج.
{alertSuccess} قاعدة ذهبية: قبل الوصول إلىitems[index]، تأكد أنindexموجود فعلًا داخل المدى:0 <= index < len(items). وعندما لا تحتاج إلى الفهرس، مرّ على العناصر مباشرة.
مصادر خارجية رسمية للتوسع
- IndexError — Python Built-in Exceptions
- An Informal Introduction to Python — Indexing and Slicing
- Data Structures — Python Documentation
أسئلة شائعة
ما معنى list index out of range في Python؟
تعني أن كود Python حاول الوصول إلى عنصر غير موجود داخل القائمة. يحدث ذلك عندما يكون رقم الفهرس أكبر من آخر index صالح، أو عندما تكون القائمة فارغة.
ما هو آخر index في قائمة طولها 5؟
آخر index هو 4، لأن الفهرسة تبدأ من الصفر: 0 و1 و2 و3 و4.
لماذا يظهر الخطأ عند استخدام len(list)؟
لأن len(list) يعيد عدد العناصر وليس آخر index. للوصول إلى آخر عنصر استخدم list[len(list) - 1] أو list[-1] بعد التحقق أن القائمة ليست فارغة.
هل يمكن أن يظهر IndexError مع String؟
نعم. أي تسلسل يمكن الوصول إلى عناصره بالفهرس قد يظهر معه الخطأ، مثل string وtuple. لكن هذا المقال يركز على القوائم لأن رسالة الخطأ هنا تقول list index out of range.
هل try/except هو أفضل حل دائمًا؟
لا. إذا كان لديك شرط واضح مثل فحص طول القائمة أو التحقق من index، فهو غالبًا أوضح. استخدم try/except عندما يكون عدم وجود العنصر حالة متوقعة أثناء تشغيل البرنامج.



