قد تكتب كودًا بسيطًا للتعامل مع قائمة، ثم تظهر أمامك الرسالة:
TypeError: list indices must be integers or slices, not str
هذه الرسالة تعني أن لديك قائمة List وحاولت الوصول إلى عنصر منها باستخدام نص من نوع str، بينما القوائم في بايثون تعتمد على فهارس رقمية مثل 0 و1 و2 أو على slice.
يظهر الخطأ كثيرًا في ثلاث حالات: استخدام مفتاح نصي مع List كما لو كانت Dictionary، استخدام القيمة القادمة من input() مباشرة كفهرس، والتعامل مع بيانات JSON التي تكون في الحقيقة قائمة من القواميس وليست قاموسًا واحدًا.
في مشكلة وحل 28 سنفهم رسالة الخطأ، ونحدد نوع المتغير قبل إصلاحه، ونوضح الفرق بين list[index] وdict[key]، ثم نطبق الحل على أمثلة من الإدخال وJSON وList of Dictionaries.
{alertInfo} الحل المختصر: إذا كان المتغير List فاستخدم فهرسًا رقميًا مثلitems[0]وليس مفتاحًا نصيًا مثلitems["name"]. وإذا جاء الفهرس منinput()فحوّله إلىintبعد التحقق منه. وإذا كانت لديك قائمة من القواميس، فاختر عنصر القائمة أولًا ثم المفتاح:users[0]["name"].
{getToc} $title={محتوى المقال}
ما معنى list indices must be integers or slices, not str؟
| الجزء | المعنى |
|---|---|
TypeError | استخدمت نوع بيانات غير مناسب للعملية. |
list indices | المشكلة مرتبطة بفهرسة قائمة. |
must be integers or slices | القائمة تحتاج فهرسًا رقميًا أو Slice. |
not str | الفهرس الذي مررته كان نصًا. |
بمعنى أبسط: أنت تعاملت مع List بطريقة تناسب Dictionary أو استخدمت نصًا بدل رقم.
أبسط مثال يسبب الخطأ
names = ["Ali", "Sara", "Omar"]
print(names["0"])
القيمة "0" نص وليست عددًا. الصحيح:
print(names[0])
الناتج:
Ali
الفرق بين "0" و0
print(type("0"))
print(type(0))
الناتج:
<class 'str'>
<class 'int'>
القيمة تبدو رقمًا للإنسان، لكن علامات الاقتباس تجعلها نصًا في بايثون.
كيف تعمل فهارس List؟
names = ["Ali", "Sara", "Omar"]
print(names[0])
print(names[1])
print(names[2])
الفهرسة تبدأ من صفر. لذلك العنصر الأول رقمه 0 والثاني 1.
ما المقصود بـslices؟
الـSlice تسمح باختيار جزء من القائمة:
numbers = [10, 20, 30, 40]
print(numbers[1:3])
الناتج:
[20, 30]
الفرق بين List وDictionary
القائمة تستخدم موقع العنصر، بينما القاموس يستخدم مفتاحًا.
names = ["Ali", "Sara"]
print(names[0])
أما القاموس:
user = {
"name": "Ali",
"city": "Aden"
}
print(user["name"])
لذلك names["name"] خطأ؛ لأن names قائمة وليست قاموسًا.
كيف أعرف نوع المتغير؟
استخدم type() بدل التخمين:
data = ["Ali", "Sara"]
print(type(data))
إذا ظهر <class 'list'> فاستخدم قواعد القوائم. وإذا ظهر <class 'dict'> فيمكن استخدام مفاتيح القاموس.
السبب الأول: استخدام مفتاح نصي مع قائمة
products = ["Keyboard", "Mouse"]
print(products["product"])
هذا غير صحيح لأن products List. إذا كنت تريد أول عنصر:
print(products[0])
أما إذا كنت تحتاج الوصول إلى قيمة باسم "product"، فربما بنية Dictionary هي الأنسب:
product = {
"name": "Keyboard",
"price": 80
}
print(product["name"])
السبب الثاني: input ترجع نصًا
هذه من أشهر حالات الخطأ:
colors = ["red", "green", "blue"]
index = input("اختر رقم العنصر: ")
print(colors[index])
حتى لو كتب المستخدم 1، فإن input() تعيد "1" من نوع str.
الحل
index = int(input("اختر رقم العنصر: "))
print(colors[index])
التحويل وحده لا يكفي في البرامج الحقيقية
إذا كتب المستخدم كلمة بدل رقم، سيظهر ValueError. لذلك الأفضل التحقق:
raw_index = input("اختر رقم العنصر: ").strip()
try:
index = int(raw_index)
except ValueError:
print("يجب إدخال رقم صحيح.")
raise SystemExit
ثم تحقق من حدود القائمة:
if 0 <= index < len(colors):
print(colors[index])
else:
print("رقم العنصر خارج حدود القائمة.")
الفرق بين TypeError وIndexError
| الخطأ | المشكلة |
|---|---|
list indices must be integers... | نوع الفهرس نفسه غير صحيح. |
list index out of range | الفهرس رقمي لكنه يشير إلى موقع غير موجود. |
colors["1"] # TypeError
colors[99] # IndexError
السبب الثالث: List of Dictionaries
هذه الحالة مهمة جدًا في JSON وواجهات API:
users = [
{
"name": "Ali",
"city": "Aden"
},
{
"name": "Sara",
"city": "Sanaa"
}
]
المتغير users قائمة، لذلك هذا خطأ:
print(users["name"])
الحل الصحيح
print(users[0]["name"])
النتيجة:
Ali
اقرأ التعبير على مرحلتين: users[0] يعيد أول قاموس، ثم ["name"] يأخذ قيمة المفتاح من ذلك القاموس.
الوصول إلى جميع الأسماء
for user in users:
print(user["name"])
داخل الحلقة، user هو Dictionary واحدة، لذلك المفتاح النصي صحيح.
خطأ شائع داخل for loop
for i in users:
print(users[i]["name"])
المتغير i ليس رقم فهرس، بل هو القاموس نفسه. الصحيح:
for user in users:
print(user["name"])
وإذا كنت تحتاج رقم الفهرس:
for index, user in enumerate(users):
print(index, user["name"])
السبب الرابع: بيانات JSON ليست بالشكل الذي توقعته
لنفترض أن ملف JSON يحتوي:
[
{"name": "Ali"},
{"name": "Sara"}
]
بعد القراءة:
import json
with open("users.json", "r", encoding="utf-8") as file:
data = json.load(file)
print(type(data))
ستكون data قائمة. لذلك:
print(data[0]["name"])
وليس:
print(data["name"])
أما إذا كان JSON قاموسًا
{
"name": "Ali",
"city": "Aden"
}
عندها يكون هذا صحيحًا:
print(data["name"])
السبب الخامس: استجابة API تعيد List بدل Dictionary
قد تتوقع أن الاستجابة قاموس، لكن API تعيد قائمة من النتائج. الحل ليس تغيير السطر عشوائيًا، بل فحص البنية:
print(type(data))
print(data)
إذا كانت List، افحص أول عنصر:
if data:
print(type(data[0]))
print(data[0])
بيانات متداخلة: List داخل Dictionary والعكس
data = {
"users": [
{
"name": "Ali",
"phones": ["111", "222"]
}
]
}
للوصول إلى أول رقم:
print(data["users"][0]["phones"][0])
حلل كل مستوى وفق نوعه: Dictionary ← List ← Dictionary ← List.
طريقة تشخيص الخطأ خطوة بخطوة
عندما ترى رسالة الخطأ، لا تبدأ بتحويل القيم عشوائيًا. نفذ الخطوات التالية:
- حدد التعبير الذي يحتوي الأقواس
[]. - اطبع نوع المتغير الموجود قبل الأقواس.
- إذا كان List، افحص نوع الفهرس.
- إذا كانت List of Dictionaries، اختر عنصر القائمة أولًا.
- إذا كانت البيانات من JSON أو API، افحص بنيتها الفعلية.
- إذا جاء الفهرس من input، حوّله إلى int بعد التحقق.
- بعد إصلاح النوع، تحقق من حدود القائمة حتى لا يظهر IndexError.
print(type(data))
if isinstance(data, list) and data:
print(type(data[0]))
print(data[0])
لماذا لا يصلح استخدام get() على List؟
قد يحاول المبتدئ استبدال:
data["name"]
بـ:
data.get("name")
لكن إذا كانت data List فهذه ليست طريقة صحيحة أيضًا؛ لأن get() من methods القواميس.
كيف أبحث عن عنصر بالاسم داخل List؟
إذا كانت القائمة تحتوي قواميس:
for user in users:
if user["name"] == "Sara":
print(user)
ويمكن الحصول على أول نتيجة باستخدام:
result = next(
(
user
for user in users
if user["name"] == "Sara"
),
None
)
print(result)
هل يمكن استخدام فهرس سالب؟
نعم، لأنه integer:
names = ["Ali", "Sara", "Omar"]
print(names[-1])
الناتج Omar.
هل يمكن استخدام float كفهرس؟
لا:
names[1.0]
قد تظهر رسالة تنتهي بـnot float. القاعدة نفسها: القائمة تحتاج فهرسًا مناسبًا.
أخطاء شائعة عند محاولة الحل
1. تحويل أي نص إلى int
إذا كتبت users["name"] فالمشكلة ليست أن كلمة name تحتاج تحويلًا إلى رقم؛ المشكلة أنك تتعامل مع القائمة ببنية خاطئة.
2. استخدام get() على List
.get() مناسبة للقواميس، لا للقوائم.
3. افتراض أن JSON دائمًا Dictionary
افحص النوع والبنية قبل الوصول إلى القيم.
4. استخدام input مباشرة
input() تعيد نصًا حتى لو كتب المستخدم رقمًا.
5. الخلط بين القائمة والعنصر داخلها
في List of Dictionaries، المفتاح النصي ينتمي إلى القاموس الداخلي وليس إلى List الخارجية.
6. إصلاح TypeError ثم تجاهل IndexError
بعد تحويل الإدخال إلى رقم، تحقق أن الرقم داخل حدود القائمة.
مثال عملي كامل: اختيار مستخدم من قائمة
users = [
{"name": "Ali", "city": "Aden"},
{"name": "Sara", "city": "Sanaa"},
{"name": "Omar", "city": "Taiz"}
]
for index, user in enumerate(users):
print(index, user["name"])
raw_choice = input("اختر رقم المستخدم: ").strip()
try:
choice = int(raw_choice)
except ValueError:
print("الرجاء إدخال رقم صحيح.")
raise SystemExit
if 0 <= choice < len(users):
selected_user = users[choice]
print("الاسم:", selected_user["name"])
print("المدينة:", selected_user["city"])
else:
print("الرقم خارج حدود القائمة.")
هذا المثال يعالج نوع الإدخال وحدود القائمة، ثم يستخدم مفتاح القاموس بعد اختيار عنصر List الصحيح.
مثال عملي مع JSON
import json
with open("users.json", "r", encoding="utf-8") as file:
users = json.load(file)
print(type(users))
if isinstance(users, list) and users:
print(users[0]["name"])
جدول تشخيص سريع
| الكود | المشكلة | التصحيح |
|---|---|---|
items["0"] | الفهرس نص. | items[0] |
items[input(...)] | input تعيد str. | تحويل الإدخال إلى int بعد التحقق. |
users["name"] | users قائمة من القواميس. | users[0]["name"] أو البحث داخل القائمة. |
data["id"] بعد JSON | data قد تكون List. | افحص type(data) والبنية. |
items[1.5] | float ليست فهرسًا صالحًا للقائمة. | استخدم integer صحيحًا إذا كان ذلك منطقيًا. |
الفرق بين هذه المشكلة وtoo many values to unpack
| الخطأ | السبب |
|---|---|
list indices must be integers or slices, not str | استخدام نوع غير مناسب كفهرس للقائمة. |
too many values to unpack | عدد القيم أكبر من عدد المتغيرات المستقبلة. |
روابط داخلية مفيدة من بايثون العرب
- سلسلة مشكلة وحل في بايثون
- حل خطأ IndexError: list index out of range في بايثون
- حل خطأ too many values to unpack وفهم Unpacking في بايثون
- حل خطأ str object has no attribute append في بايثون
- بايثون العرب
مصادر رسمية للتوسع
الخلاصة
رسالة TypeError: list indices must be integers or slices, not str تعني أن الكود استخدم نصًا كفهرس لقائمة. القوائم تعتمد على مواقع رقمية أو slices، بينما القواميس تستخدم مفاتيح مثل "name".
إذا جاء الفهرس من input() فتذكر أن الإدخال نص. وإذا جاءت البيانات من JSON أو API فلا تفترض أنها Dictionary؛ افحص النوع والبنية. وفي List of Dictionaries، اختر عنصر القائمة أولًا ثم استخدم مفتاح القاموس.
{alertSuccess} القاعدة المهمة: عندما ترى هذا الخطأ، لا تغيّر الأقواس أو تحوّل القيم عشوائيًا. اطبع نوع البيانات أولًا واسأل: هل لدي List أم Dictionary؟ ثم استخدم طريقة الوصول المناسبة.
أسئلة شائعة
ما معنى list indices must be integers or slices, not str في بايثون؟
تعني أنك استخدمت قيمة نصية كفهرس لقائمة، بينما القائمة تحتاج فهرسًا من نوع integer أو slice.
كيف أحل TypeError list indices must be integers or slices not str؟
افحص نوع المتغير باستخدام type(). إذا كان List فاستخدم فهرسًا رقميًا. وإذا كانت قائمة من القواميس فاختر عنصرًا أولًا ثم استخدم المفتاح، مثل users[0]["name"].
لماذا items["0"] لا تعمل بينما items[0] تعمل؟
لأن "0" نص من نوع str، أما 0 فهو integer صالح لفهرسة القائمة.
لماذا يظهر الخطأ عند استخدام input مع قائمة؟
لأن input() تعيد نصًا دائمًا. إذا كنت تريد استخدام الإدخال كفهرس، حوّله إلى int بعد التحقق من صحة القيمة.
ما الفرق بين فهرس List ومفتاح Dictionary؟
List تستخدم مواقع رقمية مثل 0 و1، بينما Dictionary تستخدم مفاتيح مثل "name".
كيف أصل إلى name داخل List of Dictionaries؟
استخدم users[0]["name"] لأول عنصر، أو مر على القائمة بحلقة واستخدم user["name"].
لماذا يظهر الخطأ عند قراءة JSON؟
غالبًا لأن JSON أعاد List لكن الكود تعامل معها كأنها Dictionary. استخدم type(data) وافحص أول عنصر.
كيف أعرف إذا كانت بيانات JSON قائمة أم قاموسًا؟
بعد القراءة استخدم type(data). إذا ظهر list تعامل معها كقائمة، وإذا ظهر dict استخدم مفاتيح القاموس.
ما الفرق بين هذا الخطأ وIndexError list index out of range؟
TypeError يعني أن نوع الفهرس غير صحيح، بينما IndexError يعني أن الفهرس رقمي لكنه خارج حدود القائمة.
كيف أبحث عن عنصر بالاسم داخل List؟
إذا كانت القائمة تحتوي قواميس، مر على العناصر باستخدام for أو استخدم next() للعثور على القاموس المطلوب.
هل يمكن استخدام مفتاح نصي مع List؟
لا بالطريقة العادية. إذا كنت تحتاج الوصول بالقيم الاسمية فقد تكون Dictionary أو List of Dictionaries هي بنية البيانات المناسبة.
كيف أتجنب الخطأ عند التعامل مع API؟
افحص شكل الاستجابة الفعلي قبل كتابة منطق الوصول، ولا تفترض أن البيانات قاموس دون التحقق من النوع والبنية.



