في هذا الدرس من سلسلة مشكلة وحل في بايثون العرب سنتعامل مع خطأ شائع جدًا يظهر للمبتدئين عند استخدام القوائم والنصوص في Python، وهو:
AttributeError: 'list' object has no attribute 'lower'
هذا الخطأ يظهر غالبًا عندما تحاول استخدام الدالة lower() على قائمة List بدل استخدامها على نص واحد من نوع String.
في هذا المقال سنفهم معنى الخطأ، ولماذا يحدث، وكيف نصلحه بأكثر من طريقة عملية وبسيطة، مع أمثلة تساعدك على قراءة أخطاء Python بطريقة أوضح أثناء تعلم بايثون.
{getToc} $title={محتوى المقال}
{alertInfo} هذا الخطأ لا يعني أن Python معقدة، بل يعني فقط أنك استخدمت دالة خاصة بالنصوص على نوع بيانات مختلف.
قصة المشكلة
تخيل أن لديك قائمة أسماء، وتريد تحويل كل الأسماء إلى حروف صغيرة حتى يسهل البحث أو المقارنة بينها.
فقد تكتب الكود التالي:
names = ["Ahmed", "Sara", "Omar"]
names = names.lower()
print(names)
لكن بدل أن يعمل الكود، تظهر رسالة الخطأ التالية:
AttributeError: 'list' object has no attribute 'lower'
المشكلة هنا أن المتغير names ليس نصًا واحدًا، بل قائمة تحتوي على أكثر من نص.
ماذا يعني هذا الخطأ؟
رسالة الخطأ تقول:
'list' object has no attribute 'lower'
ومعناها بالعربي:
الكائن من نوع list لا يمتلك دالة اسمها lower.
بمعنى آخر: Python تقول لك إن lower() ليست دالة متاحة للقوائم، بل هي دالة خاصة بالنصوص.
ما وظيفة lower في Python؟
الدالة lower() تُستخدم مع النصوص لتحويل الحروف الإنجليزية الكبيرة إلى حروف صغيرة.
مثال صحيح:
name = "AHMED"
small_name = name.lower()
print(small_name)
الناتج:
ahmed
هنا الكود صحيح لأن name عبارة عن نص واحد من نوع str.
{alertSuccess} الدالة lower تعمل مع String، لكنها لا تعمل مباشرة مع List.
لماذا لا تعمل lower مع List؟
القائمة في Python قد تحتوي على نصوص، أرقام، قواميس، أو أنواع بيانات مختلفة. لذلك Python لا تفترض أن كل عناصر القائمة نصوص.
مثال:
items = ["Python", 10, True]
في هذه القائمة يوجد:
- نص:
"Python" - رقم:
10 - قيمة منطقية:
True
لذلك لا يمكن استخدام lower() على القائمة كاملة، لأن القائمة نفسها ليست نصًا.
الحل الأول: استخدم lower على عنصر واحد من القائمة
إذا كنت تريد تحويل عنصر محدد داخل القائمة إلى حروف صغيرة، استخدم الفهرس للوصول إلى هذا العنصر.
names = ["Ahmed", "Sara", "Omar"]
first_name = names[0].lower()
print(first_name)
الناتج:
ahmed
هنا استخدمنا names[0] للوصول إلى أول عنصر داخل القائمة، وهو نص، ثم استخدمنا عليه lower().
الحل الثاني: تحويل كل عناصر القائمة إلى حروف صغيرة باستخدام for loop
إذا كنت تريد تحويل كل الأسماء داخل القائمة، يمكنك استخدام حلقة for.
names = ["Ahmed", "Sara", "Omar"]
lower_names = []
for name in names:
lower_names.append(name.lower())
print(lower_names)
الناتج:
['ahmed', 'sara', 'omar']
في هذا المثال مررنا على كل اسم داخل القائمة، ثم طبقنا عليه lower() وأضفناه إلى قائمة جديدة.
الحل الثالث: استخدام List Comprehension
يمكن كتابة نفس الحل بطريقة أقصر باستخدام List Comprehension.
names = ["Ahmed", "Sara", "Omar"]
lower_names = [name.lower() for name in names]
print(lower_names)
الناتج:
['ahmed', 'sara', 'omar']
{alertInfo} List Comprehension تجعل الكود أقصر، لكن تأكد أولًا أنك فهمت فكرة for loop العادية.
ماذا لو كانت القائمة تحتوي على عناصر ليست نصوصًا؟
إذا كانت القائمة تحتوي على نصوص وأرقام معًا، فقد يظهر خطأ جديد عند استخدام lower() على رقم.
مثال:
items = ["Python", 10, "Code"]
result = [item.lower() for item in items]
print(result)
هذا الكود سيظهر خطأ لأن الرقم 10 لا يمتلك دالة lower().
الحل: التأكد من نوع العنصر باستخدام isinstance
يمكننا استخدام isinstance() للتأكد أن العنصر نص قبل استخدام lower().
items = ["Python", 10, "Code"]
result = []
for item in items:
if isinstance(item, str):
result.append(item.lower())
else:
result.append(item)
print(result)
الناتج:
['python', 10, 'code']
هنا تم تحويل النصوص فقط إلى حروف صغيرة، وبقي الرقم كما هو.
{alertWarning} إذا كانت القائمة تحتوي على أنواع بيانات مختلفة، لا تستخدم lower مباشرة على كل العناصر قبل التأكد من نوعها.
مثال عملي: البحث داخل قائمة أسماء
من أشهر استخدامات lower() أنها تساعدنا في البحث بدون الاهتمام بحالة الحروف.
مثال:
names = ["Ahmed", "Sara", "Omar"]
search_name = "ahmed"
lower_names = [name.lower() for name in names]
if search_name in lower_names:
print("الاسم موجود")
else:
print("الاسم غير موجود")
الناتج:
الاسم موجود
هذا مفيد لأن المستخدم قد يكتب الاسم بحروف صغيرة، بينما القائمة تحتوي عليه بحروف مختلفة.
حل أفضل بدون إنشاء قائمة جديدة
يمكنك أيضًا المقارنة داخل الحلقة مباشرة.
names = ["Ahmed", "Sara", "Omar"]
search_name = "ahmed"
for name in names:
if name.lower() == search_name:
print("الاسم موجود")
break
هذا الحل مناسب إذا كنت تريد التوقف مباشرة عند العثور على الاسم.
جدول يوضح سبب الخطأ والحل
| الحالة | هل الكود صحيح؟ | السبب |
|---|---|---|
"Python".lower() |
صحيح | لأن القيمة نص String |
["Python"].lower() |
خطأ | لأن القيمة List وليست String |
["Python"][0].lower() |
صحيح | لأننا وصلنا إلى العنصر النصي داخل القائمة |
[name.lower() for name in names] |
صحيح إذا كانت العناصر نصوصًا | لأننا نطبق lower على كل عنصر نصي |
أخطاء شائعة مرتبطة بنفس الفكرة
هذا الخطأ قد يظهر بصيغ أخرى حسب الدالة التي تحاول استخدامها.
مثال:
AttributeError: 'list' object has no attribute 'strip'
أو:
AttributeError: 'list' object has no attribute 'replace'
والسبب غالبًا هو نفسه: استخدام دوال خاصة بالنصوص على قائمة.
{alertError} لا تستخدم دوال النصوص مثل lower و strip و replace على List مباشرة. استخدمها على عناصر نصية داخل القائمة.
كيف تعرف نوع المتغير؟
إذا لم تكن متأكدًا هل المتغير نص أم قائمة، استخدم الدالة type().
names = ["Ahmed", "Sara"]
print(type(names))
الناتج:
<class 'list'>
ولو كان المتغير نصًا:
name = "Ahmed"
print(type(name))
الناتج:
<class 'str'>
معرفة نوع المتغير تساعدك كثيرًا في قراءة أخطاء Python وفهم سبب المشكلة.
تمرين بسيط
ما الخطأ في الكود التالي؟
words = ["HELLO", "PYTHON", "CODE"]
print(words.lower())
الخطأ أن words قائمة، ولا يمكن استخدام lower() عليها مباشرة.
الحل:
words = ["HELLO", "PYTHON", "CODE"]
lower_words = [word.lower() for word in words]
print(lower_words)
الناتج:
['hello', 'python', 'code']
أسئلة شائعة
ما سبب خطأ list object has no attribute lower في Python؟
السبب أنك استخدمت الدالة lower() على قائمة List، بينما هذه الدالة تعمل على النصوص String فقط.
كيف أحول كل عناصر List إلى حروف صغيرة؟
استخدم حلقة for أو List Comprehension لتطبيق lower() على كل عنصر نصي داخل القائمة.
هل lower تعمل مع الأرقام؟
لا، لأن lower() خاصة بالنصوص فقط، ولا تعمل مع الأرقام أو القوائم مباشرة.
كيف أتأكد أن العنصر نص قبل استخدام lower؟
استخدم isinstance(item, str) للتأكد أن العنصر من نوع String.
روابط مهمة من بايثون العرب
- مشكلة وحل 7: حل خطأ TypeError can only concatenate str not int to str
- حل خطأ ValueError invalid literal for int في Python
- الفرق بين append و extend في Python
- أساسيات بايثون 14: شرح return في الدوال
- أساسيات بايثون 15: المتغيرات المحلية والعامة Scope في Python
- بايثون بالمثال: حساب مجموع عناصر List في Python
- تشغيل بايثون أون لاين بدون تثبيت
- أفضل طريقة لتعلم بايثون بالعربي من الصفر للمبتدئين
مصدر خارجي مفيد
يمكنك الرجوع إلى توثيق Python الرسمي حول دوال النصوص من هنا: Python Documentation - String Methods.
الخلاصة
خطأ AttributeError: 'list' object has no attribute 'lower' يظهر عندما تحاول استخدام lower() على قائمة بدل نص.
الحل هو أن تستخدم lower() على عنصر نصي داخل القائمة، أو تمر على عناصر القائمة باستخدام for loop أو List Comprehension.
وتذكر دائمًا: عندما ترى رسالة object has no attribute، اسأل نفسك: هل أستخدم الدالة على نوع البيانات الصحيح؟
{alertSuccess} القاعدة الذهبية: lower للنصوص، وليس للقوائم. إذا كانت لديك قائمة نصوص، طبّق lower على كل عنصر داخل القائمة.