يظهر خطأ AttributeError: 'list' object has no attribute 'lower' عندما تحاول استخدام lower() على قائمة List بدل تطبيقها على نص String داخل القائمة. هذا من الأخطاء الشائعة للمبتدئين لأنه يبدو للوهلة الأولى وكأن المشكلة في lower() نفسها، بينما السبب الحقيقي هو نوع المتغير الذي استُدعيت عليه.
في مشكلة وحل 8 من سلسلة بايثون العرب سنفكك رسالة الخطأ، ونحدد متى نستخدم الفهرسة، ومتى نمر على العناصر باستخدام for أو List Comprehension، وكيف نتعامل مع القوائم التي تحتوي على أنواع مختلفة.
باختصار: إذا كان المتغير قائمة فلا تكتب names.lower(). استخدم names[0].lower() عندما تريد عنصرًا واحدًا، أو طبّق lower() على كل عنصر نصي عندما تريد تحويل القائمة كاملة. المهم أن تصل أولًا إلى النص الصحيح ثم تستدعي الـmethod عليه.
{getToc} $title={محتوى المقال}
{alertInfo} الحل السريع:lower()تعمل على النصstr، لا على القائمة نفسها. إذا كانت لديك قائمة نصوص، طبّقlower()على كل عنصر نصي داخلها.
إذا كنت تحتاج إلى مراجعة القوائم أولًا، اقرأ أساسيات بايثون 16: شرح Lists في بايثون للمبتدئين.
سبب خطأ list object has no attribute lower
لنبدأ بالكود الذي يسبب المشكلة:
names = ["Ahmed", "Sara", "Omar"]
names = names.lower()
print(names)
عند التشغيل تظهر الرسالة:
AttributeError: 'list' object has no attribute 'lower'
المتغير names من نوع list. وعندما تكتب names.lower() فأنت تطلب من القائمة نفسها method اسمها lower، لكن list لا تملك هذه الـmethod. لهذا ترفع بايثون AttributeError.
ما معنى AttributeError في هذه الحالة؟
خطأ AttributeError يعني أن بايثون حاولت الوصول إلى attribute أو method غير موجودة على الكائن الحالي. لذلك أهم جزء في الرسالة هو:
'list' object has no attribute 'lower'
الرسالة تخبرك بشيئين مباشرة: الكائن من نوع list، والاسم الذي حاولت الوصول إليه هو lower. قبل تغيير الكود، افحص نوع المتغير الذي تستدعي عليه الـmethod.
ما وظيفة lower() في بايثون؟
lower() هي method للنصوص من نوع str. وهي تعيد نسخة من النص بعد تحويل المحارف التي لها حالة أحرف إلى lowercase. لذلك هذا الاستخدام صحيح:
name = "AHMED"
small_name = name.lower()
print(small_name)
الناتج:
ahmed
{alertSuccess} لاحظ أنlower()لا تعدّل النص الأصلي نفسه؛ بل تعيد نصًا جديدًا. أما استدعاؤها علىListمباشرة فهو الذي يسبب الخطأ.
الفرق بين String وList عند استخدام lower()
| القيمة | النوع | هل lower() تعمل؟ |
|---|---|---|
"PYTHON" |
str |
نعم |
["PYTHON", "CODE"] |
list |
لا، تظهر AttributeError |
["PYTHON"][0] |
str |
نعم، لأننا وصلنا إلى العنصر النصي |
يمكنك التأكد من النوع باستخدام type():
words = ["PYTHON", "CODE"]
word = "PYTHON"
print(type(words))
print(type(word))
سيظهر أن الأولى list والثانية str. وهذه عادةً أسرع خطوة لتشخيص أخطاء الـmethods عندما لا تكون متأكدًا من نوع المتغير.
الحل الأول: تطبيق lower() على عنصر واحد
إذا كنت تحتاج إلى عنصر واحد فقط، استخدم الفهرس للوصول إليه ثم طبّق lower():
names = ["Ahmed", "Sara", "Omar"]
first_name = names[0].lower()
print(first_name)
الناتج:
ahmed
هنا names[0] تعيد النص "Ahmed"، لذلك أصبح استدعاء lower() صحيحًا.
الحل الثاني: تحويل كل عناصر القائمة باستخدام for
إذا كانت القائمة تحتوي على نصوص وتريد تحويلها كلها، مرّ على العناصر وطبّق lower() على كل نص:
names = ["Ahmed", "Sara", "Omar"]
lower_names = []
for name in names:
lower_names.append(name.lower())
print(lower_names)
الناتج:
['ahmed', 'sara', 'omar']
بهذه الطريقة بقيت القائمة الأصلية كما هي، وأنشأنا قائمة جديدة بالقيم المحولة.
الحل الثالث: List Comprehension
بعد فهم حلقة for يمكنك كتابة الفكرة نفسها بشكل مختصر:
names = ["Ahmed", "Sara", "Omar"]
lower_names = [name.lower() for name in names]
print(lower_names)
الناتج:
['ahmed', 'sara', 'omar']
إذا أردت شرحًا أوسع لهذه الصيغة، راجع شرح List Comprehension في بايثون بالأمثلة.
ماذا لو كانت القائمة تحتوي على نصوص وأرقام؟
الخطأ قد ينتقل من القائمة نفسها إلى أحد عناصرها إذا طبقت lower() على كل عنصر بدون التأكد من نوعه:
items = ["Python", 10, "Code"]
result = [item.lower() for item in items]
print(result)
عندما تصل الحلقة إلى الرقم 10 سيظهر خطأ؛ لأن int لا يملك lower() أيضًا. إذا كنت تريد تحويل النصوص فقط والإبقاء على بقية القيم كما هي، استخدم isinstance():
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}
استخدم isinstance(item, str) عندما تكون عناصر القائمة مختلطة ولا يمكنك ضمان أن كل عنصر نص.
مثال عملي: البحث عن اسم بدون الاهتمام بحالة الأحرف
من الاستخدامات الشائعة تحويل النصوص قبل المقارنة. وللبحث بدون إنشاء قائمة ثانية، يمكنك المرور على العناصر والتوقف عند العثور على الاسم:
names = ["Ahmed", "Sara", "Omar"]
search_name = "ahmed"
for name in names:
if name.lower() == search_name.lower():
print("الاسم موجود")
break
else:
print("الاسم غير موجود")
هذا المثال يحل المشكلة التعليمية مباشرة، لكن إذا كنت تبني مقارنة نصية عامة بين لغات وحالات أحرف أكثر تعقيدًا، توجد أيضًا casefold() في بايثون للمقارنات غير الحساسة لحالة الأحرف بشكل أوسع. لا تحتاجها لحل خطأ List نفسه.
أخطاء مشابهة: strip وreplace على List
نفس الفكرة قد تظهر مع methods نصية أخرى:
AttributeError: 'list' object has no attribute 'strip'
AttributeError: 'list' object has no attribute 'replace'
الحل ليس إضافة try/except لإخفاء الخطأ، بل تحديد العنصر النصي الصحيح ثم تطبيق method النص عليه. مثال تنظيف قائمة أسماء:
names = [" Ahmed ", " SARA ", " Omar "]
clean_names = [name.strip().lower() for name in names]
print(clean_names)
الناتج:
['ahmed', 'sara', 'omar']
جدول سريع: أي حل تختار؟
| الحالة | الحل | مثال |
|---|---|---|
| القيمة نص واحد | استخدم lower() مباشرة |
name.lower() |
| تريد عنصرًا واحدًا من List | استخدم الفهرس ثم lower() |
names[0].lower() |
| كل عناصر القائمة نصوص | استخدم for أو List Comprehension |
[x.lower() for x in names] |
| القائمة تحتوي أنواعًا مختلفة | افحص النوع بـ isinstance() |
isinstance(x, str) |
خطوات تشخيص الخطأ بسرعة
- اقرأ نوع الكائن في رسالة الخطأ؛ هنا هو
list. - افحص المتغير باستخدام
type()إذا لم يكن نوعه واضحًا. - اسأل: هل الـmethod التي أستخدمها تخص هذا النوع؟
- إذا كنت تتعامل مع قائمة، حدّد هل تريد عنصرًا واحدًا أم جميع العناصر.
- إذا كانت العناصر مختلطة، افحص نوع كل عنصر قبل استدعاء methods النصوص.
أسئلة شائعة
ما سبب AttributeError: 'list' object has no attribute 'lower'؟
لأنك استدعيت lower() على كائن من نوع list، بينما lower() method للنصوص من نوع str.
كيف أحول جميع النصوص داخل List إلى lowercase؟
إذا كانت كل العناصر نصوصًا، استخدم حلقة for أو List Comprehension مثل [name.lower() for name in names].
هل lower() تعمل مع النص العربي؟
lower() تطبق قواعد تحويل حالة الأحرف على المحارف التي لها uppercase وlowercase وفق Unicode. الحروف العربية لا تملك هذا التقابل، لذلك يبقى النص العربي عادةً دون تغيير.
كيف أتجنب الخطأ مع قائمة مختلطة؟
تحقق أولًا من أن العنصر نص باستخدام isinstance(item, str) قبل استدعاء lower().
روابط مفيدة
- سلسلة مشكلة وحل في بايثون
- شرح Lists في بايثون للمبتدئين
- شرح List Comprehension في بايثون
- مشكلة وحل 7: TypeError can only concatenate str not int to str
- مشكلة وحل 9: NameError name is not defined
- توثيق Python الرسمي لـ str.lower()
- توثيق Python الرسمي لـ AttributeError
الخلاصة
خطأ AttributeError: 'list' object has no attribute 'lower' لا يعني أن lower() معطلة. الرسالة تخبرك أن الكائن الذي استخدمتها عليه هو List، بينما هذه الـmethod تخص النصوص.
- للنص الواحد: استخدم
text.lower(). - لعنصر داخل القائمة: استخدم الفهرس ثم
lower(). - لكل العناصر النصية: استخدم
forأو List Comprehension. - للقائمة المختلطة: افحص النوع باستخدام
isinstance().
{alertSuccess}
الخلاصة السريعة: لا تطبق lower() على الـList نفسها؛ طبّقها على النص الموجود داخل القائمة.
في الدرس التالي
ننتقل في مشكلة وحل 9 إلى حل خطأ NameError: name is not defined في بايثون.