يظهر خطأ TypeError: unsupported operand type(s) في بايثون عندما تستخدم عاملًا مثل + أو - أو * أو / بين قيمتين لا تدعمان هذه العملية معًا. من أشهر الأمثلة محاولة جمع int مع str، أو طرح نص من رقم، أو إجراء عملية حسابية على قيمة None.
الحل لا يكون بحذف العامل عشوائيًا، بل بقراءة العامل ونوعي القيم من آخر سطر في رسالة الخطأ، ثم إصلاح مصدر القيمة أو تحويلها حسب الهدف. استخدم type() عند التشخيص، وint() أو float() للحساب الرقمي، وstr() أو f-string لدمج النصوص؛ أما NoneType فيحتاج معرفة لماذا أصبحت القيمة None بدل تحويلها عشوائيًا.
في هذا الدرس من مشكلة وحل 23 سنشرح رسالة الخطأ خطوة بخطوة، وأشهر الحالات التي تسببها، وكيف تصلحها بدون تخمين، مع توضيح الفرق بينها وبين ValueError.
{alertInfo} الخلاصة السريعة: اقرأ نوعي القيم الظاهرين في رسالة الخطأ، ثم اسأل: هل أريد حسابًا رقميًا أم دمج نصوص؟ بعد ذلك وحّد النوعين بالطريقة المناسبة قبل تنفيذ العملية.
{getToc} $title={محتوى المقال}
حل خطأ unsupported operand type(s) بسرعة
ابدأ من آخر سطر في رسالة الخطأ. سيخبرك عادةً بالعامل المستخدم ونوعي القيم غير المتوافقين. ثم اختر الحل حسب هدفك:
| الحالة | المشكلة | الحل المناسب |
|---|---|---|
10 + "5" |
رقم مع نص | حوّل النص إلى رقم: 10 + int("5") |
"Age: " + 25 |
دمج نص مع رقم | استخدم str(25) أو f-string. |
100 - "20" |
عملية حسابية على نص رقمي | حوّل النص إلى int أو float. |
قيمة قادمة من input() |
input() تعيد نصًا |
حوّل الإدخال قبل الحساب وتعامل مع ValueError عند الحاجة. |
10 + None |
إحدى القيم NoneType |
تتبّع مصدر None؛ غالبًا توجد دالة لم تُرجع قيمة أو بيانات مفقودة. |
[10, 20] / 2 |
عملية حسابية مباشرة بين list ورقم |
طبّق العملية على العناصر أو استخدم الحساب المناسب مثل sum(values) / len(values). |
ما معنى TypeError في بايثون؟
خطأ TypeError يعني أن هناك مشكلة في نوع البيانات المستخدم داخل العملية. فمثلًا، قد تحاول جمع رقم مع نص، أو طرح قائمة من رقم، أو ضرب نوعين لا يدعم كل منهما هذه العملية.
إذا كنت لا تزال في بداية تعلمك، أنصحك بمراجعة درس
أنواع البيانات في بايثون
لأنه يساعدك على فهم الفرق بين int و float و str و list.
حسب توثيق بايثون الرسمي، يتم رفع خطأ TypeError عندما تُطبّق عملية أو دالة على كائن من نوع غير مناسب:
توثيق TypeError الرسمي.
شكل رسالة الخطأ
قد تظهر رسالة الخطأ بهذا الشكل:
TypeError: unsupported operand type(s) for +: 'int' and 'str'
ومعناها: لا يمكن استخدام العامل + بين قيمة من نوع int وقيمة من نوع str. اقرأ الرسالة من اليمين بهذه الطريقة: + هو العامل الذي فشل، و'int' هو نوع الطرف الأول، و'str' هو نوع الطرف الثاني. إذا تغيرت الرسالة إلى 'float' و'NoneType' مثلًا، فالحل سيتغير لأن المشكلة أصبحت وجود قيمة None داخل عملية حسابية.
إذا كانت رسالة الخطأ طويلة ولا تعرف أين تبدأ، راجع أساسيات بايثون 32: قراءة رسائل الخطأ وTraceback.
مثال خاطئ: جمع رقم مع نص
هذا المثال من أشهر أسباب الخطأ:
age = 25
message = "عمري هو " + age
print(message)
الكود السابق خطأ لأن المتغير age رقم، بينما النص "عمري هو " من نوع str.
بايثون لا يستطيع دمج نص مع رقم باستخدام + مباشرة.
الحل هو تحويل الرقم إلى نص باستخدام str():
age = 25
message = "عمري هو " + str(age)
print(message)
ويمكنك أيضًا استخدام f-string وهي طريقة أوضح:
age = 25
print(f"عمري هو {age}")
إذا كانت رسالتك بدلًا من ذلك تقول can only concatenate str (not "int") to str، فهذه صيغة قريبة لكن لها صفحة مخصصة: حل خطأ can only concatenate str not int to str.
{alertWarning}
انتبه: العامل + يستخدم للجمع بين الأرقام، ويستخدم أيضًا لدمج النصوص، لكنه لا يدمج رقمًا مع نص إلا بعد تحويل أحدهما.
مثال خاطئ: جمع مدخلات المستخدم كأنها أرقام
عند استخدام input() في بايثون، فإن القيمة الناتجة تكون نصًا حتى لو كتب المستخدم رقمًا.
num1 = input("أدخل الرقم الأول: ")
num2 = input("أدخل الرقم الثاني: ")
result = num1 + num2
print(result)
إذا أدخل المستخدم 5 و 3، قد تتوقع أن النتيجة ستكون 8، لكنها ستكون:
53
لأن القيمتين نصوص، وليس أرقامًا. والحل هو تحويلهما إلى أرقام:
num1 = int(input("أدخل الرقم الأول: "))
num2 = int(input("أدخل الرقم الثاني: "))
result = num1 + num2
print(result)
للمزيد عن التحويل إلى رقم، يمكنك الرجوع إلى توثيق int و float في بايثون.
متى أستخدم int ومتى أستخدم float؟
استخدم int() عندما تريد رقمًا صحيحًا بدون فاصلة عشرية، مثل العمر أو عدد المنتجات.
واستخدم float() عندما تتوقع رقمًا عشريًا، مثل السعر أو الوزن أو النسبة.
| الدالة | الاستخدام | مثال |
|---|---|---|
int() |
تحويل القيمة إلى عدد صحيح | int("10") |
float() |
تحويل القيمة إلى عدد عشري | float("10.5") |
str() |
تحويل القيمة إلى نص | str(25) |
مثال خاطئ: طرح نص من رقم
الطرح لا يعمل إلا مع أنواع مناسبة مثل الأرقام:
price = 100
discount = "20"
final_price = price - discount
print(final_price)
هذا الكود سيؤدي إلى خطأ لأن discount نص وليس رقمًا.
الحل:
price = 100
discount = "20"
final_price = price - int(discount)
print(final_price)
إذا أردت تدريبًا عمليًا قريبًا من هذا المثال، راجع مقال حساب الخصم والسعر النهائي في بايثون.
مثال خاطئ: قسمة نص على رقم
في بعض الأحيان تكون القيمة مخزنة كنص بسبب قراءة من ملف أو إدخال من المستخدم:
total = "100"
count = 4
average = total / count
print(average)
الحل هو تحويل النص إلى رقم قبل القسمة:
total = "100"
count = 4
average = int(total) / count
print(average)
ماذا يعني unsupported operand type(s) مع NoneType؟
إذا ظهر NoneType داخل رسالة الخطأ، مثل unsupported operand type(s) for +: 'NoneType' and 'int'، فهذا يعني أن أحد طرفي العملية قيمته None. هنا لا يكون الحل المعتاد هو int() أو str()، بل معرفة لماذا لم تحصل على القيمة التي كنت تتوقعها.
من أكثر الأسباب شيوعًا أن تستدعي دالة لا تحتوي على return ثم تحاول استخدام نتيجتها في عملية حسابية:
def get_total():
total = 100
print(total)
result = get_total() + 5
الدالة السابقة تطبع 100 لكنها لا تعيدها، ولذلك تكون نتيجة get_total() هي None. الحل هو إعادة القيمة باستخدام return:
def get_total():
total = 100
return total
result = get_total() + 5
print(result)
وقد تحصل على None أيضًا من بيانات مفقودة، أو من دوال تعدّل الكائن في مكانه وتعيد None مثل بعض دوال القوائم. لذلك اطبع القيمة ونوعها قبل سطر الخطأ وتتبع المكان الذي أصبحت فيه None.
استخدام type لمعرفة نوع القيمة
قبل أن تصلح الخطأ، يجب أن تعرف نوع القيم التي تتعامل معها.
يمكنك استخدام type() لمعرفة نوع أي قيمة:
value = "25"
print(type(value))
الناتج سيكون:
<class 'str'>
أي أن القيمة نص وليست رقمًا. يمكنك قراءة المزيد عن type() من
توثيق بايثون الرسمي.
استخدام isinstance للتحقق من النوع
إذا أردت التحقق من نوع القيمة قبل تنفيذ العملية، يمكنك استخدام isinstance().
value = 50
if isinstance(value, int):
print("القيمة رقم صحيح")
else:
print("القيمة ليست رقمًا صحيحًا")
وتفيدك هذه الطريقة عندما يكون لديك بيانات غير مضمونة المصدر. يمكنك الرجوع إلى توثيق isinstance الرسمي للتفاصيل.
{alertSuccess}
قاعدة عملية: قبل تنفيذ عملية حسابية، تأكد أن القيم أرقام. وقبل دمج نصوص، تأكد أن القيم نصوص أو حوّلها باستخدام str().
الفرق بين TypeError و ValueError
قد تختلط عليك أخطاء TypeError و ValueError.
الفرق ببساطة:
TypeError: النوع نفسه غير مناسب للعملية.ValueError: النوع مناسب، لكن القيمة لا يمكن تحويلها أو استخدامها.
مثال على TypeError:
result = 10 + "5"
هنا المشكلة أن أحد الطرفين رقم والآخر نص.
مثال على ValueError:
number = int("abc")
هنا int() تقبل نصًا قابلًا للتحويل إلى رقم، لكن القيمة "abc" ليست رقمًا.
ولفهم هذا الخطأ أكثر، يمكنك مراجعة مقال
حل خطأ ValueError: invalid literal for int.
استخدام try/except بطريقة آمنة
عند التعامل مع إدخال المستخدم، لا تعتمد على أن المستخدم سيكتب رقمًا دائمًا. يمكنك استخدام try/except لمعالجة الخطأ بطريقة منظمة.
try:
price = float(input("أدخل السعر: "))
tax = 0.15
total = price + (price * tax)
print("السعر بعد الضريبة:", total)
except ValueError:
print("الرجاء إدخال رقم صحيح")
في هذا المثال استخدمنا ValueError لأن الخطأ المتوقع غالبًا سيحدث أثناء تحويل إدخال المستخدم إلى رقم.
أما TypeError فيحدث عادة عندما تنفذ عملية بين أنواع غير متوافقة.
لمراجعة التعامل مع الأخطاء بشكل أوسع، يمكنك قراءة درس أساسيات بايثون 31: شرح try و except للمبتدئين.
جدول سريع: سبب الخطأ والحل
| الكود الخاطئ | سبب الخطأ | الحل |
|---|---|---|
10 + "5" |
جمع رقم مع نص | 10 + int("5") |
"Age: " + 25 |
دمج نص مع رقم | "Age: " + str(25) |
100 - "20" |
طرح نص من رقم | 100 - int("20") |
"100" / 4 |
قسمة نص على رقم | int("100") / 4 |
مثال عملي كامل
في هذا المثال سنحسب السعر النهائي بعد الخصم، مع تحويل القيم إلى أرقام بطريقة صحيحة:
price_text = "150"
discount_text = "25"
price = float(price_text)
discount = float(discount_text)
final_price = price - discount
print(f"السعر النهائي هو: {final_price}")
هنا حوّلنا النصوص إلى أرقام قبل تنفيذ عملية الطرح، لذلك لن يظهر خطأ unsupported operand type(s).
{alertInfo}
ملاحظة مهمة: لا تحفظ الأرقام كنصوص إلا إذا كنت تحتاجها كنص فعلًا. وإذا كانت القيمة قادمة من input() أو ملف، فحوّلها إلى النوع المناسب قبل الحساب.
ملخص المقال
هذا الدرس جزء من سلسلة مشكلة وحل في بايثون، والقاعدة الأساسية هنا هي قراءة العامل ونوعي القيم من رسالة الخطأ قبل اختيار الحل.
خطأ TypeError: unsupported operand type(s) يظهر عندما تستخدم عاملًا مثل الجمع أو الطرح أو القسمة بين أنواع بيانات لا تقبل هذه العملية معًا.
المشكلة ليست في العامل نفسه، بل في نوع القيم التي تستخدمها.
لتجنب الخطأ:
- افهم نوع كل قيمة قبل استخدامها.
- استخدم
type()عند الحاجة لمعرفة النوع. - حوّل النصوص الرقمية إلى أرقام باستخدام
int()أوfloat(). - حوّل الأرقام إلى نصوص باستخدام
str()عند دمجها مع نصوص. - إذا ظهر
NoneType، تتبع مصدرNoneبدل محاولة تحويلها عشوائيًا. - استخدم
isinstance()إذا أردت التحقق من النوع قبل العملية. - استخدم
try/exceptمع إدخال المستخدم أو البيانات غير المضمونة.
{alertSuccess}
الخلاصة العملية: عندما يظهر لك خطأ unsupported operand type(s)، اسأل نفسك: ما نوع القيمة الأولى؟ وما نوع القيمة الثانية؟ وهل هذا العامل مناسب لهذين النوعين؟
أسئلة شائعة
ما معنى TypeError: unsupported operand type(s) في بايثون؟
يعني أنك استخدمت عاملًا مثل + أو - أو / بين نوعين لا يدعمان هذه العملية معًا.
لماذا يظهر الخطأ عند جمع رقم مع نص؟
لأن الرقم من نوع int أو float، بينما النص من نوع str. يجب تحويل أحدهما حسب الهدف: إما تحويل النص إلى رقم للحساب، أو تحويل الرقم إلى نص للدمج.
هل input يعيد رقمًا في بايثون؟
لا. الدالة input() تعيد نصًا دائمًا، حتى لو كتب المستخدم أرقامًا. لذلك تحتاج إلى int() أو float() قبل العمليات الحسابية.
ما الفرق بين TypeError و ValueError؟
TypeError يعني أن نوع البيانات غير مناسب للعملية، بينما ValueError يعني أن النوع مقبول لكن القيمة نفسها غير صالحة، مثل محاولة تحويل "abc" إلى رقم.
كيف أعرف نوع المتغير في بايثون؟
استخدم الدالة type():
value = "10"
print(type(value))
ماذا يعني ظهور NoneType في رسالة unsupported operand type(s)؟
يعني أن إحدى القيم المستخدمة مع العامل تساوي None. افحص مصدرها؛ فقد تكون دالة لا تحتوي على return، أو قيمة مفقودة، أو ناتج دالة تعدّل كائنًا في مكانه وتعيد None.
ما أفضل حل لخطأ unsupported operand type(s)؟
أفضل حل هو قراءة العامل ونوعي القيم أولًا، ثم إصلاح مصدر القيمة أو تحويلها إلى النوع المناسب للعملية. لا تعتمد على التخمين، واستخدم type() أو isinstance() عند الحاجة.



