في الدروس السابقة، تعاملنا مع المتغيرات التي تخزن قيمة واحدة فقط، مثل رقم فردي أو نص قصير يمثل معلومة واحدة محددة. لكن عندما تبدأ في بناء تطبيقات حقيقية، ستجد نفسك بحاجة ماسة لتخزين مجموعة من البيانات المرتبطة معاً تحت اسم واحد ومعالجتها ككتلة واحدة. هنا يأتي دور القوائم أو ما يُعرف بالـ Lists في لغة بايثون.
القائمة هي بنية بيانات مرنة وعملية للغاية، تتيح لك ترتيب العناصر، إضافتها، تعديلها، أو حتى حذفها بسهولة تامة. في هذا الدرس الشامل، سنتعرف بعمق على كيفية إنشاء القوائم، وفهم طريقة عمل الفهارس بدقة، واستخدام أهم الدوال والأدوات المتاحة لإدارة القوائم بكفاءة تامة ودون تعقيد برمجي.
ما هي القائمة (List) في بايثون؟
القائمة في بايثون هي حاوية متسلسلة تخزن مجموعة مرتبة من العناصر. يمكن أن تحتوي القائمة على نصوص، أرقام صحيحة، أرقام عشرية، قيم منطقية، أو حتى أنواع بيانات مختلطة ومركبة في نفس الوقت. تُمثّل القوائم برمجياً باستخدام الأقواس المربعة الشكل، وتُفصل العناصر داخلها باستخدام الفاصلة العادية.
تخيل أنك تريد تخزين درجات خمسة طلاب في اختبار البرمجة لجامعتك. بدلاً من إنشاء خمسة متغيرات منفصلة يصعب تتبعها، يمكنك جمعها كلها داخل قائمة واحدة يسهل الوصول إليها وتعديلها وحساب متوسطها الحسابي بأسطر قليلة.
# مثال لتعريف قائمة تحتوي على أرقام ونصوص
student_names = ["أحمد", "سارة", "محمد", "ليلى"]
student_grades = [85, 92, 78, 90]
# قائمة مختلطة البيانات تجمع أنواع مختلفة
mixed_list = ["بايثون", 2024, True, 3.14]
print(student_names)
print(student_grades)
print(mixed_list)في الكود أعلاه، قمنا بإنشاء ثلاث قوائم مختلفة. الأولى لتخزين النصوص، والثانية للأرقام، والثالثة تجمع أنواع بيانات مختلفة تماماً. بايثون لا تضع قيوداً صارمة على نوع البيانات داخل القائمة الواحدة، مما يمنحك مرونة هائلة أثناء كتابة الشفرة المصدرية.
فهم الفهارس (Indexing) والوصول للعناصر
لكي تستفيد من البيانات المخزنة داخل القائمة، يجب أن تعرف تماماً كيف تصل إلى عنصر معين بمفرده. تعتمد بايثون على نظام الفهارس (Indices) للوصول إلى العناصر، وأهم قاعدة ذهبية يجب أن تتذكرها للمبتدئين هي أن العد البرمجي يبدأ من الصفر (0) وليس من الواحد.
هذا يعني أن العنصر الأول في أي قائمة يكون موجوداً في الفهرس 0، والعنصر الثاني في الفهرس 1، وهكذا حتى نهاية القائمة. كما تتيح بايثون ميزة متقدمة تتمثل في استخدام الفهارس السالبة للوصول إلى العناصر من نهاية القائمة إلى بدايتها، حيث يشير الفهرس -1 إلى العنصر الأخير مباشرة، و-2 إلى العنصر قبل الأخير.
languages = ["Python", "JavaScript", "C++", "Java"]
# الوصول إلى العناصر باستخدام الفهارس الموجبة والسالبة
first_lang = languages[0] # النتيجة: Python
second_lang = languages[1] # النتيجة: JavaScript
last_lang = languages[-1] # النتيجة: Java
penultimate = languages[-2] # النتيجة: C++
print("العنصر الأول:", first_lang)
print("العنصر الأخير:", last_lang)
print("قبل الأخير:", penultimate)في هذا المثال، قمنا باستخراج العنصر الأول عبر languages[0] والعنصر الأخير عبر languages[-1]. استخدام الفهارس السالبة مفيد جداً عندما تكون القائمة طويلة ومتغيرة، ولا تعرف بدقة عدد عناصرها الكلي في لحظة الاستدعاء.
تعديل محتويات القائمة وإضافة عناصر جديدة
واحدة من أهم المزايا الجوهرية للقوائم في بايثون أنها قابلة للتغيير (Mutable). هذا يعني أنه يمكنك تعديل قيم العناصر الموجودة بالفعل، أو إضافة عناصر جديدة تماماً، أو إدراجها في مواضع معينة بعد إنشاء القائمة الأساسية دون الحاجة لإنشاء قائمة جديدة من الصفر.
لإضافة عنصر جديد تماماً في نهاية القائمة، نستخدم الدالة append(). أما إذا أردت إدراج عنصر في مكان محدد بدقة، فنستخدم الدالة insert() مع تحديد رقم الفهرس المطلوب والعنصر المراد إضافته.
# إنشاء قائمة مهام أولية
tasks = ["قراءة كتاب", "كتابة الكود"]
# إضافة مهمة جديدة في نهاية القائمة
tasks.append("مراجعة المشروع")
# إدراج مهمة في المنتصف (تحديداً في الفهرس 1)
tasks.insert(1, "شرب القهوة")
print(tasks)عند تنفيذ الكود السابق، ستكون النتيجة قائمة مرتبة بالشكل التالي: المهمة الأولى تبقى في مكانها، وتدخل مهمة "شرب القهوة" في الفهرس رقم 1 دافعة العناصر السابقة للأمام، بينما تُضاف "مراجعة المشروع" في النهاية تماماً. يمكنك أيضاً تعديل عنصر مباشر عبر تعيين قيمة جديدة لفهرسه:
# تعديل عنصر موجود
tasks[0] = "قراءة كتاب متقدم"
print(tasks)حذف العناصر وإدارتها بكفاءة
مثلما نضيف العناصر ونعدلها، نحتاج أحياناً كثيرة إلى إزالتها من القائمة عندما تفقد صلاحيتها أو حاجتها. توفر لغة بايثون طرقاً ودوال مختلفة لحذف العناصر بناءً على قيمتها النصية أو الرقمية أو بناءً على موقعها المباشر (الفهرس).
الدالة remove() تبحث عن القيمة المحددة وتزيلها من القائمة (أول مطابقة تقابلها فقط)، بينما الدالة pop() تحذف العنصر الموجود في فهرس معين (وإذا لم تحدد فهرساً، فإنها تحذف العنصر الأخير افتراضياً وتُعيده لك).
colors = ["أحمر", "أخضر", "أزرق", "أصفر", "أخضر"]
# حذف عنصر بناءً على قيمته (يحذف أول "أخضر" تقابله)
colors.remove("أخضر")
# حذف العنصر الأخير باستخدام pop وحفظه في متغير
removed_color = colors.pop()
print("القائمة بعد الحذف:", colors)
print("العنصر المحذوف بواسطة pop:", removed_color)هنا قمنا بحذف اللون "أخضر" بالاسم، ثم أزلنا العنصر الأخير وحفظناه في متغير لتوضيح أن دالة pop() لا تقم بعملية الحذف فحسب، بل تُعيد لك القيمة المحذوفة لكي تستخدمها في منطق برنامجك إذا احتجت لذلك.
التحقق من وجود عنصر وترتيب القوائم
كثيراً ما تحتاج أثناء كتابة الخوارزميات إلى التأكد مما إذا كان عنصر معين موجوداً داخل القائمة أم لا، وذلك قبل إجراء أي عملية عليه لتفادي الأخطاء. للقيام بذلك بشكل آمن، نستخدم الكلمة المفتاحية in البسيطة والمعبرة.
بالإضافة إلى ذلك، يمكنك ترتيب القوائم الرقمية أو النصية تصاعدياً أو تنازلياً باستخدام الدالة sort()، أو عكس ترتيب العناصر تماماً باستخدام دالة reverse().
fruits = ["تفاح", "موز", "برتقال", "مانجو"]
# التحقق من وجود عنصر داخل القائمة
if "موز" in fruits:
print("الموز موجود في قائمة الفواكه!")
# ترتيب العناصر أبجدياً تصاعدياً
fruits.sort()
print("بعد الترتيب:", fruits)
# عكس ترتيب العناصر تماماً
fruits.reverse()
print("بعد العكس:", fruits)ساعدتنا الكلمة المفتاحية in في التحقق الآمن قبل تنفيذ منطق برمجي معين، بينما قامت sort() بترتيب الفواكه أبجدياً، وجاءت reverse() لتعكس هذا الترتيب فوراً حسب الحاجة.
أخطاء شائعة يقع فيها المبتدئون وكيفية تجنبها
حتى تكون متمكناً تماماً من التعامل مع القوائم واحتراف إدارتها، هناك خطأ شهير يقع فيه أغلب المبتدئين ويسمى بخطأ تجاوز الحدود (IndexError). يحدث هذا الخطأ عندما تحاول الوصول إلى فهرس غير موجود في القائمة أصلاً (مثلاً طلب العنصر رقم 10 في قائمة تحتوي على 3 عناصر فقط).
numbers = [10, 20, 30]
# هذا السطر سيتسبب في خطأ IndexError لأن الفهرس 5 غير موجود
# print(numbers[5])
# الطريقة الصحيحة لمعرفة طول القائمة وتفادي الخطأ
print("طول القائمة:", len(numbers))
# الوصول الآمن بآخر عنصر بناءً على الطول
print("العنصر الأخير بأمان:", numbers[len(numbers) - 1])استخدام الدالة len() يخبرك دائماً بالعدد الكلي للعناصر، وبما أن العد البرمجي يبدأ من الصفر، فإن أقصى فهرس متاح في قائمة طولها 3 هو 2. تذكر هذه القاعدة جيداً لتجنب توقف برنامجك بشكل مفاجئ أثناء التشغيل.
حالات استخدام عملية للقوائم في الواقع
لا تقتصر القوائم على الأمثلة التعليمية البسيطة، بل تُستخدم في كل مكان في تطوير البرمجيات. إليك بعض حالات الاستخدام الشائعة التي ستتعامل معها يومياً كمبرمج:
تخزين سجلات المستخدمين: حفظ قائمة بأسماء المستخدمين النشطين في نظام الدردشة أو لوحة التحكم.
قوائم المهام (To-Do Lists): إضافة، تعديل، وحذف المهام اليومية في تطبيق الإنتاجية الخاص بك.
جمع نتائج البيانات: تخزين درجات الطلاب أو قراءات المستشعرات (Sensors) في مشاريع إنترنت الأشياء (IoT) لتحليلها لاحقاً.
# مثال عملي لحساب متوسط درجات الطلاب باستخدام القوائم
grades = [88, 92, 79, 95, 84]
total_sum = sum(grades)
count = len(grades)
average = total_sum / count
print("المجموع الكلي:", total_sum)
print("عدد الطلاب:", count)
print("المتوسط الحسابي للدرجات:", average)خلاصة
تُعد القوائم بمثابة العمود الفقري لتنظيم وتخزين البيانات في لغة بايثون. من خلال فهمك العميق لآلية الفهارس الموجبة والسالبة، ومعرفة كيفية الإضافة باستخدام append وinsert، والحذف عبر remove وpop، والبحث والترتيب، بات بإمكانك الآن بناء تطبيقات وبرامج حقيقية تدير مجموعات بيانات متعددة بكفاءة عالية وبدون أخطاء.
تدرب على هذه الدوال والمفاهيم جيداً، وجرب كتابة قوائم خاصة بك وتطبيق أمثلة برمجية متعددة لتثبيت المعلومة في ذهند، والانتقال بثقة وثبات إلى المواضيع والدروس القادمة في عالم بايثون.
