خطأ TypeError: '...' object is not subscriptable يعني أنك استخدمت الأقواس المربعة [] مع كائن لا يدعم الوصول بهذه الطريقة. أول خطوة للحل هي أن تقرأ نوع الكائن المذكور داخل رسالة الخطأ، ثم تنظر إلى التعبير الموجود مباشرة قبل [].
فإذا ظهر 'int' أو 'float' فأنت تحاول فهرسة رقم، وإذا ظهر 'function' أو 'method' فغالبًا نسيت استدعاء الدالة بالأقواس ()، وإذا ظهر 'NoneType' فالقيمة أصبحت None قبل الفهرسة.
TypeError: 'int' object is not subscriptable
TypeError: 'function' object is not subscriptable
TypeError: 'NoneType' object is not subscriptable
TypeError: 'type' object is not subscriptable
{alertInfo}
القاعدة الذهبية: لا تبحث عن حل عام للرسالة فقط. حدّد النوع المكتوب بين علامتي الاقتباس في الخطأ، ثم افحص لماذا أصبح المتغير من هذا النوع قبل استخدام [].
{getToc} $title={محتوى المقال}
حل سريع حسب نوع الخطأ
| رسالة الخطأ | السبب الشائع | الحل المبدئي |
|---|---|---|
'int' / 'float' object is not subscriptable |
استخدام [] مع رقم |
استخدم الرقم مباشرة، أو حوّله إلى str() فقط إذا كنت تريد التعامل مع خاناته كنص. |
'function' / 'method' / 'builtin_function_or_method' object is not subscriptable |
استخدام [] مع دالة أو method بدل استدعائها |
استخدم () لاستدعاء الدالة أو الـmethod، ثم فهرس الناتج إذا كان يدعم ذلك. |
'NoneType' object is not subscriptable |
القيمة أصبحت None |
تتبّع مصدر None: قد تكون دالة بلا return أو نتيجة بحث لم تجد شيئًا. |
'type' object is not subscriptable |
استخدام [] مع نوع غير قابل للاشتراك مثل int، أو Type Hint حديث في إصدار قديم |
استخدم () للتحويل أو الاستدعاء، وتحقق من إصدار Python عند Type Hints. |
'set' object is not subscriptable |
محاولة استخدام فهرس رقمي مع set |
استخدم in أو حلقة for، أو حوّلها إلى قائمة إذا كان ترتيب العناصر غير مهم. |
'map' / 'generator' object is not subscriptable |
محاولة فهرسة iterator | استخدمه داخل حلقة، أو next() للعنصر التالي، أو حوّله إلى list() إذا كنت تحتاج الفهرسة فعلًا. |
هذا المقال جزء من سلسلة مشكلة وحل في بايثون التي تشرح رسائل الأخطاء الشائعة من السبب إلى الإصلاح.
ما معنى object is not subscriptable في بايثون؟
كلمة subscriptable تعني أن الكائن يدعم استخدام الأقواس المربعة [] للوصول إلى عنصر أو قيمة، مثل items[0] أو user["name"]. تقنيًا، الكائنات التي تسمح بهذا السلوك تنفذ عادةً آلية مثل __getitem__، لكنك لا تحتاج إلى كتابة هذه الدالة بنفسك عند استخدام الأنواع المدمجة مثل List وString وTuple وDictionary.
مثال: القائمة List تدعم الفهرسة. إذا كانت الفهارس جديدة عليك، راجع شرح القوائم Lists في بايثون:
names = ["Ali", "Sara", "Omar"]
print(names[0])
الناتج:
Ali
والنص String يدعم الفهرسة أيضًا:
word = "Python"
print(word[0])
الناتج:
P
أما الرقم العادي فلا يدعم الفهرسة:
number = 123
print(number[0])
هنا يظهر الخطأ لأن number هو رقم من نوع int، وليس قائمة أو نصًا يمكن الوصول إلى جزء منه باستخدام [].
لماذا يظهر خطأ TypeError object is not subscriptable؟
يظهر هذا الخطأ عندما تضع [] بعد كائن لا يدعم الوصول بالفهرس. لذلك الحل يبدأ دائمًا من معرفة نوع المتغير الذي استخدمت معه الأقواس المربعة.
أمثلة على كائنات تدعم الفهرسة:
listمثل[10, 20, 30]stringمثل"Python"tupleمثل(10, 20, 30)dictionaryباستخدام المفاتيح مثلuser["name"]
وأمثلة على كائنات غالبًا لا تدعم الفهرسة:
intرقم صحيح مثل123floatرقم عشري مثل3.14None- الدالة نفسها إذا كتبت اسمها بدون أقواس الاستدعاء
()
{alertWarning} وجود الأقواس [] لا يعني أنها تصلح مع كل شيء. استخدمها فقط مع كائنات تدعم الفهرسة أو المفاتيح.
مثال 1: استخدام الفهرسة مع رقم int
هذا المثال من أشهر أسباب الخطأ:
age = 25
print(age[0])
سيظهر خطأ مثل:
TypeError: 'int' object is not subscriptable
سبب الخطأ
المتغير age يحتوي على رقم صحيح، والرقم لا يحتوي على عناصر داخلية يمكن الوصول إليها باستخدام [0].
الحل
إذا كنت تريد طباعة الرقم، اطبعه مباشرة:
age = 25
print(age)
أما إذا كنت تريد الوصول إلى أول خانة داخل العدد، حوّل الرقم إلى نص أولًا:
number = 123
text_number = str(number)
print(text_number[0])
الناتج:
1
{alertInfo} إذا أردت التعامل مع خانات الرقم كأحرف، حول الرقم إلى نص باستخدام str().
مثال 2: استخدام الفهرسة مع float
الرقم العشري أيضًا لا يدعم الفهرسة مباشرة.
price = 19.99
print(price[0])
سيظهر خطأ:
TypeError: 'float' object is not subscriptable
الحل
إذا أردت طباعة السعر، اطبعه مباشرة:
price = 19.99
print(price)
وإذا أردت التعامل معه كنص:
price = 19.99
price_text = str(price)
print(price_text[0])
الناتج:
1
مثال 3: المتغير كان قائمة ثم تغير إلى رقم
أحيانًا يكون سبب الخطأ أنك تبدأ بمتغير يحتوي على قائمة، ثم تغيّر قيمته لاحقًا إلى رقم بدون أن تنتبه.
scores = [90, 80, 70]
scores = 100
print(scores[0])
سيظهر الخطأ لأن scores لم تعد قائمة، بل أصبحت رقمًا.
الحل
لا تستخدم نفس اسم المتغير لمعنيين مختلفين:
scores = [90, 80, 70]
new_score = 100
print(scores[0])
الناتج:
90
{alertSuccess} اختر أسماء متغيرات واضحة، ولا تجعل نفس المتغير مرة قائمة ومرة رقمًا إلا إذا كنت تقصد ذلك فعلًا.
حالة NoneType object is not subscriptable
إذا كانت الرسالة هي TypeError: 'NoneType' object is not subscriptable فهذا يعني أن القيمة الموجودة قبل [] أصبحت None. من الأسباب الشائعة: دالة بلا return، أو عملية بحث لم تجد نتيجة، أو method تعدّل الكائن في مكانه وتعيد None.
هذه الحالة لها مقال مستقل ومفصل حتى لا نكرر الشرح هنا: حل خطأ 'NoneType' object is not subscriptable في بايثون.
حالة function أو method object is not subscriptable
قد تكتب اسم الدالة بدون أقواس، ثم تحاول استخدام الفهرسة على الدالة نفسها.
def get_numbers():
return [10, 20, 30]
result = get_numbers
print(result[0])
قد يظهر خطأ لأن result يشير إلى الدالة نفسها، وليس إلى ناتج الدالة.
الحل
استدعِ الدالة بالأقواس:
def get_numbers():
return [10, 20, 30]
result = get_numbers()
print(result[0])
الناتج:
10
وتظهر الفكرة نفسها مع الـmethods المدمجة. مثلًا، كتابة text.split[0] تحاول فهرسة الـmethod نفسها، بينما الصحيح هو استدعاؤها أولًا ثم فهرسة الناتج:
text = "Python is easy"
print(text.split()[0])
إذا ظهرت الرسالة 'builtin_function_or_method' object is not subscriptable فراجع أيضًا هل استخدمت [] بدل () مع دالة أو method مثل len() أو pop() أو get().
حالة type object is not subscriptable
إذا ظهرت رسالة من نوع TypeError: 'type' object is not subscriptable أو type 'int' is not subscriptable فافحص هل استخدمت الأقواس المربعة مع نوع بينما كنت تقصد استدعاءه أو تحويل قيمة إليه.
# خطأ
number = int["25"]
الصحيح هو استخدام الأقواس الدائرية عند التحويل:
number = int("25")
وقد تظهر رسالة 'type' object is not subscriptable في Python 3.8 أو أقدم عند استخدام Type Hints حديثة مثل list[str]. هذه الصيغة للأنواع المدمجة مدعومة مباشرة ابتداءً من Python 3.9، لذلك افحص إصدار Python إذا كان الخطأ داخل Annotation.
حالة set object is not subscriptable
الـset لا تدعم الفهرسة الرقمية مثل items[0]. إذا كان هدفك معرفة هل قيمة موجودة، استخدم in، وإذا أردت المرور على العناصر فاستخدم حلقة for.
skills = {"Python", "HTML", "CSS"}
if "Python" in skills:
print("موجود")
يمكن تحويل Set إلى List إذا كنت تحتاج الفهرسة فعلًا، لكن لا تعتمد على موضع عنصر بعينه لأن Set ليست بنية مخصصة للترتيب الموضعي.
حالة map أو generator object is not subscriptable
في Python 3 ترجع map() كائنًا قابلًا للتكرار وليس List، والـgenerator يعمل بالطريقة نفسها من ناحية أنه لا يدعم [0] مباشرة.
numbers = [1, 2, 3]
squares = map(lambda x: x ** 2, numbers)
squares = list(squares)
print(squares[0])
إذا كنت لا تحتاج إلى الفهرسة، فمن الأفضل المرور على iterator مباشرة. وإذا أردت العنصر التالي فقط، يمكن استخدام next() بدل تحويل كل العناصر إلى List.
إذا كانت الرسالة باسم Class مخصصة
قد ترى رسالة مثل TypeError: 'User' object is not subscriptable. في هذه الحالة أنت غالبًا تستخدم user["name"] مع object عادية بينما التصميم يعتمد على attributes، فيكون الاستخدام الصحيح مثل user.name.
إذا كنت تريد عمدًا أن تدعم class مخصصة الأقواس [] فيمكن تصميمها لذلك عبر __getitem__، لكن لا تضف هذا السلوك لمجرد التخلص من الخطأ؛ استخدم الواجهة التي صُممت class للعمل بها.
كيف تعرف نوع المتغير قبل استخدام الفهرسة؟
من أفضل الطرق لفهم سبب الخطأ استخدام الدالة type() لمعرفة نوع المتغير قبل استخدام [].
value = 123
print(type(value))
الناتج:
<class 'int'>
لا يكفي أن ترى نوعًا مثل int أو NoneType ثم تحوّل القيمة عشوائيًا. استخدم type() للتشخيص، ثم أصلح السبب الحقيقي: الرقم لا يُفهرس مباشرة، وNone يحتاج إلى معرفة لماذا ظهر أصلًا، والدالة أو الـmethod تحتاج غالبًا إلى الاستدعاء بالأقواس ().
مثال عملي كامل لتجنب الخطأ
لنفترض أنك تريد جلب أول اسم من قائمة أسماء. الطريقة الصحيحة أن تتأكد أن الناتج فعلًا قائمة قبل استخدام الفهرسة:
def get_students():
return ["Ali", "Sara", "Omar"]
students = get_students()
if isinstance(students, list):
print(students[0])
else:
print("القيمة ليست قائمة")
الناتج:
Ali
هنا استخدمنا isinstance() للتأكد أن المتغير قائمة قبل استخدام الفهرسة.
ما الفرق بين [] و () في هذا الخطأ؟
الأقواس المربعة [] تستخدم غالبًا للوصول إلى عنصر داخل قائمة أو نص أو Tuple أو قيمة داخل Dictionary. أما الأقواس الدائرية () فتستخدم لاستدعاء الدوال.
مثال فهرسة صحيح:
names = ["Ali", "Sara"]
print(names[0])
ومثال استدعاء دالة صحيح:
def get_name():
return "Ali"
print(get_name())
{alertWarning} لا تخلط بين [] للفهرسة و () لاستدعاء الدوال، فهذا سبب شائع لأخطاء كثيرة في Python.
خطوات حل خطأ object is not subscriptable
- اذهب إلى السطر الذي يشير إليه Traceback.
- ابحث عن التعبير الموجود مباشرة قبل
[]. - اقرأ النوع المذكور داخل رسالة الخطأ، أو اطبع
type(value)عند الحاجة. - إذا كان
intأوfloat، فلا تفهرس الرقم مباشرة؛ أصلح نوع البيانات أو حوّله إلى نص فقط إذا كنت تريد خاناته كنص. - إذا كان
functionأوmethod، تحقق من استدعائه باستخدام(). - إذا كان
NoneType، تتبّع لماذا أصبحت القيمةNoneقبل الفهرسة. - إذا كان
setأو iterator مثلmapأو generator، استخدم الواجهة المناسبة بدل افتراض وجود فهرس. - إذا كان object من class مخصصة، استخدم attributes أو methods التي صُممت لها، ولا تستخدم
[]إلا إذا كانت class تدعم ذلك عمدًا.
أخطاء مرتبطة قد تواجهك
IndexError
يظهر خطأ IndexError عندما يكون الكائن يدعم الفهرسة، لكنك طلبت فهرسًا غير موجود.
names = ["Ali", "Sara"]
print(names[5])
KeyError
يظهر خطأ KeyError غالبًا مع القواميس عندما تطلب مفتاحًا غير موجود.
user = {"name": "Ali"}
print(user["age"])
TypeError
الخطأ الذي نشرحه في هذا المقال هو نوع من TypeError، لأنه يحدث بسبب استخدام عملية غير مناسبة مع نوع بيانات معين.
تدريب سريع
جرّب الكود التالي، ثم غيّر قيمة المتغير value مرة إلى قائمة، ومرة إلى رقم، ومرة إلى نص. الهدف من التدريب أن تفهم متى يمكن استخدام [] ومتى لا يمكن استخدامها.
value = ["Python", "HTML", "CSS"]
print(type(value))
print(value[0])
أسئلة شائعة
ما معنى TypeError object is not subscriptable؟
يعني أنك استخدمت [] مع كائن لا يدعم الوصول بهذه الطريقة. اقرأ النوع المذكور في رسالة الخطأ، ثم افحص التعبير الموجود مباشرة قبل الأقواس المربعة.
كيف أحل int object is not subscriptable؟
لا تستخدم [] مع الرقم مباشرة. إذا كنت تريد خانات الرقم كنص فحوّله إلى str()، أما إذا كنت تتوقع List أو قيمة أخرى فابحث عن المكان الذي غيّر نوع المتغير إلى int.
كيف أحل function أو method object is not subscriptable؟
تحقق أولًا من أنك استدعيت الدالة أو الـmethod باستخدام (). مثلًا استخدم text.split()[0] بدل text.split[0].
ما سبب NoneType object is not subscriptable؟
يعني أن القيمة أصبحت None قبل استخدام []. قد يكون السبب دالة بلا return أو عملية لم تجد نتيجة. إذا كانت هذه هي رسالتك تحديدًا، استخدم الشرح المتخصص المشار إليه في قسم NoneType أعلاه.
كيف أحل type object is not subscriptable؟
تأكد أنك لم تستخدم اسم النوع نفسه مثل list[0] بدل المتغير. وإذا ظهر الخطأ داخل Type Hint مثل list[str]، فتحقق من إصدار Python لأن هذه الصيغة تحتاج Python 3.9 فأحدث.
لماذا set object is not subscriptable؟
لأن Set لا تدعم الفهرسة الموضعية مثل items[0]. استخدم in للتحقق من وجود عنصر أو حلقة for للمرور على العناصر.
هل map وgenerator يدعمان الفهرسة؟
لا يدعمان [0] مباشرة. يمكنك المرور عليهما، استخدام next() للعنصر التالي، أو التحويل إلى list() إذا كنت تحتاج الفهرسة فعلًا.
مصادر رسمية للتوسع
الخلاصة
خطأ TypeError: object is not subscriptable لا يملك إصلاحًا واحدًا يصلح لكل الحالات. معنى الرسالة ببساطة أن الكائن الموجود قبل [] لا يدعم هذا النوع من الوصول، ولذلك يجب أن تبدأ من نوع الكائن المذكور في الخطأ.
إذا كان النوع رقمًا فلا تفهرسه مباشرة، وإذا كان دالة أو method فراجع الأقواس ()، وإذا كان NoneType فتتبّع مصدر None، وإذا كان set أو map أو generator فاستخدم طريقة التعامل المناسبة لذلك النوع. أما مع class مخصصة، فاستخدم attributes أو methods إلا إذا كانت class مصممة لدعم [].
{alertSuccess} القاعدة الذهبية: اقرأ النوع داخل رسالة الخطأ، ثم افحص التعبير الموجود قبل []، وأصلح سبب النوع نفسه بدل تحويل القيمة عشوائيًا فقط لإخفاء الخطأ.