مشكلة وحل 20: حل خطأ IndexError: list index out of range في Python

حل خطأ IndexError list index out of range في Python للمبتدئين

قد تكتب قائمة في 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 خارج نطاق القائمة.

شرح فهرسة List في Python من الصفر إلى آخر عنصر

الفرق بين 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.

الفرق بين len list وآخر index في Python

السبب الأول: طلب عنصر برقم أكبر من آخر 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
حل خطأ IndexError داخل for loop وrange في Python

السبب الثالث: القائمة فارغة

حتى لو استخدمت فهرسًا صحيحًا مثل 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.
أخطاء شائعة تسبب IndexError list index out of range في Python

خطوات تشخيص الخطأ بسرعة

  1. اقرأ السطر الذي يشير إليه traceback؛ غالبًا ستجد فيه list[index] أو list.pop(index).
  2. اطبع القائمة وطولها مؤقتًا باستخدام print(items) وprint(len(items)).
  3. اطبع قيمة index قبل استخدامه.
  4. تأكد أن القيمة تحقق الشرط 0 <= index < len(items).
  5. إذا كانت داخل حلقة، راجع range() وتأكد أنك لم تكتب + 1 دون حاجة.
  6. إذا كنت تحذف عناصر، لا تعتمد على فهارس قديمة بعد أن يتغير طول القائمة.

أخطاء قريبة من IndexError

الخطأ المعنى المختصر مثال شائع
IndexError طلب موضع غير موجود داخل list أو string أو tuple. items[10] مع قائمة قصيرة.
KeyError طلب مفتاح غير موجود داخل dictionary. user["email"] عندما لا يوجد المفتاح.
ValueError القيمة غير مناسبة للعملية المطلوبة. int("12a").
TypeError استخدمت نوعًا غير مناسب في عملية ما. محاولة استخدام فهرس نصي مع list.

يمكنك مراجعة مشكلة وحل 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). وعندما لا تحتاج إلى الفهرس، مرّ على العناصر مباشرة.

مصادر خارجية رسمية للتوسع

أسئلة شائعة

ما معنى 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 عندما يكون عدم وجود العنصر حالة متوقعة أثناء تشغيل البرنامج.

إرسال تعليق

أحدث أقدم