خطأ TypeError: 'NoneType' object is not subscriptable يظهر عندما تستخدم الأقواس المربعة [] على قيمة أصبحت None بدل كائن يدعم الوصول بهذه الصيغة، مثل قائمة أو قاموس أو نص. لذلك المشكلة الحقيقية ليست في الأقواس نفسها، بل في مصدر القيمة التي تحاول فهرستها.
لإصلاح الخطأ، حدّد أولًا المتغير الموجود مباشرة قبل []، ثم افحص قيمته ونوعه. إذا كان None، ارجع إلى الدالة أو العملية التي أعطته هذه القيمة: قد تكون دالة نسيت return، أو عملية بحث لم تجد نتيجة، أو Method مثل list.sort() تعدّل الكائن وتعيد None.
{alertSuccess} الحل المختصر: لا تحذف[]عشوائيًا. اكتشف لماذا أصبحت القيمةNone، وأصلح المصدر. استخدمif value is Noneفقط عندما تكونNoneنتيجة متوقعة في تصميم البرنامج.
{getToc} $title={محتوى المقال}
ما معنى NoneType object is not subscriptable؟
الجزء NoneType يعني أن القيمة هي None. أما object is not subscriptable فتعني أن هذا الكائن لا يدعم الصيغة obj[...]. في بايثون تستخدم هذه الصيغة مثلًا للوصول إلى عنصر في قائمة باستخدام Index أو إلى قيمة في Dictionary باستخدام Key.
| جزء الرسالة | المعنى |
|---|---|
TypeError |
تم استخدام عملية لا يدعمها نوع الكائن الحالي. |
NoneType |
القيمة التي وصلت إليها تساوي None. |
not subscriptable |
لا يمكنك استخدام [] على هذه القيمة. |
هذا المثال ينتج الخطأ مباشرة:
data = None
print(data["name"])
لأن التعبير الموجود قبل الأقواس، وهو data، لا يحتوي قاموسًا بل None.
أسرع طريقة لتشخيص الخطأ
ابدأ من السطر الذي يظهر في آخر جزء من Traceback. انظر إلى التعبير الموجود مباشرة قبل []، ثم افحص قيمته قبل السطر المسبب للمشكلة:
print(repr(data))
print(type(data))
print(data["name"])
إذا ظهر:
None
<class 'NoneType'>
فقد عرفت مكان المشكلة: المطلوب الآن هو معرفة لماذا أصبحت data تساوي None. إذا كان الـTraceback نفسه غير واضح لك، راجع شرح أخطاء بايثون وطريقة قراءة Traceback.
السبب الأول: الدالة لم ترجع القيمة التي تتوقعها
إذا انتهت دالة في بايثون دون تنفيذ return بقيمة، تكون نتيجتها None. لذلك هذا الخطأ شائع عندما نتوقع من الدالة Dictionary أو List بينما لا تعيد شيئًا فعليًا.
مثال خاطئ: نسيان return
def get_user():
user = {"name": "Ali"}
# لا يوجد return
result = get_user()
print(result["name"])
هنا قيمة result هي None. إذا كان هدف الدالة فعلًا إعادة بيانات المستخدم، أصلح الدالة نفسها:
def get_user():
return {"name": "Ali"}
result = get_user()
print(result["name"])
الناتج:
Ali
إذا أردت فهم هذه النقطة بتفصيل أكبر، راجع شرح معنى return في دوال بايثون. ولشرح قيمة None نفسها والفرق بينها وبين القيم الفارغة، يوجد درس مستقل عن None في بايثون.
السبب الثاني: None نتيجة متوقعة من الدالة
أحيانًا لا توجد مشكلة في الدالة نفسها؛ فقد يكون من الطبيعي أن تعيد None عندما لا تجد نتيجة. في هذه الحالة يجب أن يتعامل الكود الذي يستدعيها مع الاحتمالين.
def find_student(student_id):
if student_id == 123:
return {
"name": "Ahmed",
"grade": "Very Good"
}
return None
student = find_student(999)
if student is None:
print("لم يتم العثور على الطالب.")
else:
print(student["name"])
هنا فحص None جزء من منطق البرنامج، لأن عدم العثور على الطالب حالة متوقعة. لا نستخدم الشرط فقط لإخفاء خطأ ناتج عن دالة ناقصة.
السبب الثالث: تخزين نتيجة list.sort() في متغير
من الحالات الشائعة أن تستخدم Method تعدّل الكائن في مكانه ثم تتوقع منها كائنًا جديدًا. مثلًا، list.sort() ترتب القائمة الأصلية وتعيد None.
الكود الذي يسبب الخطأ
numbers = [3, 1, 2]
sorted_numbers = numbers.sort()
print(sorted_numbers[0])
القيمة sorted_numbers أصبحت None. لديك حلان حسب المطلوب.
إذا كنت تريد تعديل القائمة الأصلية
numbers = [3, 1, 2]
numbers.sort()
print(numbers[0])
إذا كنت تريد قائمة مرتبة جديدة
numbers = [3, 1, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers[0])
الناتج في الحالتين:
1
للتفصيل في الفرق بين الطريقتين، راجع ترتيب عناصر List باستخدام sort وsorted.
هل dict.get() يحل خطأ NoneType؟
ليس إذا كان القاموس نفسه None. الدالة get() تساعد عندما يكون لديك Dictionary فعلًا لكن المفتاح قد لا يكون موجودًا:
student = {"name": "Ali"}
print(student.get("grade", "غير معروف"))
أما إذا كانت قيمة student نفسها None، فاستدعاء student.get(...) سيؤدي إلى خطأ مختلف من نوع AttributeError. لذلك لا تخلط بين «القاموس موجود لكن المفتاح غير موجود» و«لا يوجد قاموس أصلًا».
هل try-except هو الحل؟
ليس كحل افتراضي لهذا الخطأ. كتابة except TypeError حول الكود قد تخفي TypeError آخر لا علاقة له بـNone. إذا كانت None حالة متوقعة، يكون فحص is None أكثر وضوحًا. وإذا لم تكن متوقعة، فالأفضل إصلاح مصدرها.
{alertWarning}
لا تجعل الهدف هو «منع ظهور الرسالة» فقط. الهدف أن تعيد الدالة أو العملية نوع البيانات الصحيح، أو أن تتعامل بوضوح مع احتمال None إذا كان جزءًا طبيعيًا من النتيجة.
لا تخلط بين أخطاء متشابهة
| الموقف | الخطأ المعتاد |
|---|---|
data = None ثم data["name"] |
TypeError: 'NoneType' object is not subscriptable |
| Dictionary موجود لكن المفتاح غير موجود | KeyError |
| List موجودة لكن الـIndex خارج حدودها | IndexError |
data = None ثم data.get("name") |
AttributeError: 'NoneType' object has no attribute 'get' |
إذا كانت رسالتك من النوع الأخير، فالمقال الأنسب هو حل خطأ AttributeError: 'NoneType' object has no attribute.
خطوات حل الخطأ بسرعة
- اقرأ آخر سطر في الـTraceback وحدد السطر الذي استخدم
[]. - حدد التعبير الموجود مباشرة قبل الأقواس.
- افحصه باستخدام
repr()وtype()أو الـDebugger. - إذا كان
None، ارجع إلى المكان الذي أُسندت فيه القيمة. - تحقق من
returnومن نتائج Methods التي تعدّل الكائن في مكانه مثلsort(). - إذا كانت
Noneنتيجة متوقعة، تعامل معها صراحة باستخدامis None. - أعد تشغيل الحالة التي سببت المشكلة للتأكد أن السبب نفسه تم إصلاحه.
وإذا أردت مساعدة سريعة في تفكيك رسالة خطأ كاملة، يمكنك لصق الـTraceback في محلل أخطاء بايثون.
أسئلة شائعة
ما سبب TypeError: 'NoneType' object is not subscriptable؟
السبب المباشر هو استخدام [] على قيمة None. السبب الأهم الذي يجب البحث عنه هو: لماذا أصبحت القيمة None بدل النوع الذي كنت تتوقعه؟
هل الحل هو if value is not None دائمًا؟
لا. استخدم الشرط عندما تكون None نتيجة متوقعة. إذا كانت الدالة يفترض أن ترجع Dictionary أو List دائمًا، فقد يكون الأصح إصلاح الدالة بدل تجاوز المشكلة بشرط.
لماذا ترجع الدالة None رغم أنني لم أكتب return None؟
إذا وصلت الدالة إلى نهايتها دون تنفيذ return بقيمة، فإنها ترجع None ضمنيًا.
لماذا numbers.sort() ترجع None؟
لأن list.sort() تعدّل القائمة نفسها في مكانها ولا تنشئ قائمة مرتبة جديدة. إذا كنت تريد قيمة جديدة، استخدم sorted(numbers).
مصادر رسمية
الخلاصة
خطأ TypeError: 'NoneType' object is not subscriptable يعني أن القيمة الموجودة قبل [] هي None ولا تدعم عملية Subscription. أسرع طريق للحل هو تحديد هذه القيمة ثم تتبع مصدرها بدل تعديل سطر الفهرسة وحده.
راجع أولًا return في الدوال، ثم انتبه إلى Methods التي تعدّل الكائن وتعيد None مثل list.sort(). وإذا كانت None نتيجة متوقعة، تعامل معها صراحة قبل استخدام [].
{alertSuccess} القاعدة الذهبية: عندما ترىNoneTypeفي رسالة الخطأ، ابحث عن مصدرNoneأولًا. هذا عادةً يقودك إلى السبب الحقيقي أسرع من تعديل السطر الذي انفجر فقط.
للمزيد من أخطاء بايثون الشائعة، يمكنك الرجوع إلى سلسلة مشكلة وحل في بايثون.