القوائم في Python (list): الطرق والشرائح والترتيب وappend والصفوف والمجموعات
القائمة (list) في Python مجموعة مرتبة قابلة للتعديل من القيم بين أقواس مربعة، مثل [250, 1200, 99]، ويمكن إضافة العناصر إليها بالدالة append أو إدراجها وحذفها وأخذ أجزاء منها بالشرائح وترتيبها. الطريقة sort ترتب القائمة في مكانها وتعيد None، أما الدالة sorted فتعيد قائمة جديدة مرتبة.
القائمة في Python (list) مجموعة مرتبة من القيم أياً كانت بين أقواس مربعة، ويمكن تعديلها: إضافة عناصر في النهاية، أو إدراجها في الوسط، أو حذفها، أو ترتيبها. وهي أكثر المجموعات استخداماً في اللغة: أسطر الملف، والمصروفات الشهرية، وردود الـ API، وكلها تبدأ غالباً بقائمة. فيما يلي شرح list في Python بالكامل: الإنشاء، والطرق، والشرائح، والترتيب، وتوليد القوائم، والنسخ، وفي الختام الصفوف والمجموعات.
ما هي القائمة في Python
تحفظ القائمة عناصرها بالترتيب الذي أدخلتها به، وتصل إليها بالفهرس ابتداءً من الصفر. يمكن أن تحتوي القائمة الواحدة على قيم من أنواع مختلفة، لكن عملياً تُحفظ فيها بيانات من نوع واحد غالباً.
amounts = [250, 1200, 99]
print(amounts[0]) # 250 — العنصر الأول
print(amounts[-1]) # 99 — الأخير
amounts[1] = 1300 # القائمة قابلة للتعديل
print(len(amounts)) # 3 — طول القائمة
يعيد طول القائمة الدالة len(). أما الوصول إلى فهرس غير موجود فيعطي الخطأ IndexError: list index out of range.
إنشاء قائمة
empty = [] # قائمة فارغة
also_empty = list() # الشيء نفسه بالدالة list
nums = [1, 2, 3]
chars = list("abc") # ['a', 'b', 'c']
digits = list(range(5)) # [0, 1, 2, 3, 4]
zeros = [0] * 4 # [0, 0, 0, 0]
تحوّل الدالة list() أي كائن قابل للتكرار إلى قائمة: نص، أو range، أو مجموعة، أو مفاتيح قاموس.
append وبقية طرق القوائم
تضيف الطريقة append عنصراً واحداً إلى نهاية القائمة، وهي أكثر طرق بايثون استخداماً. وهي تعدّل القائمة في مكانها وتعيد None.
amounts = [250, 1200]
amounts.append(450) # [250, 1200, 450]
amounts.extend([10, 20]) # [250, 1200, 450, 10, 20]
amounts.insert(0, 5) # [5, 250, 1200, 450, 10, 20]
amounts.remove(1200) # حذف أول قيمة تساوي 1200
last = amounts.pop() # 20 — حذف الأخير وإعادته
خطأ شائع: a.append([10, 20]) يضيف عنصراً واحداً هو قائمة متداخلة، لا رقمين. لإضافة عدة عناصر استخدم extend.
| الطريقة | ماذا تفعل |
|---|---|
append(x) | إضافة x إلى النهاية |
extend(iter) | إضافة كل عناصر متتالية |
insert(i, x) | إدراج x قبل الفهرس i |
remove(x) | حذف أول ظهور للقيمة x (ValueError إن لم توجد) |
pop(i=-1) | حذف العنصر عند الفهرس وإعادته |
index(x) | فهرس أول ظهور للقيمة |
count(x) | عدد مرات ظهور x |
sort() | الترتيب في المكان نفسه |
reverse() | عكس الترتيب في المكان نفسه |
copy() | نسخة سطحية |
clear() | تفريغ القائمة |
يمكن حذف عنصر بفهرسه أو مدى كامل بالعامل del: del a[0] أو del a[1:3]. ومن الدوال المضمنة المفيدة مع القوائم: len وsum وmin وmax وsorted وreversed وenumerate وzip.
الشرائح في Python
تأخذ الشريحة جزءاً من القائمة بالصيغة a[start:stop:step]: من start (شاملاً) حتى stop (غير شامل) بخطوة step. ويمكن حذف أي جزء منها. والشريحة تعيد دائماً قائمة جديدة.
a = [0, 1, 2, 3, 4, 5]
print(a[1:4]) # [1, 2, 3]
print(a[:2]) # [0, 1] — أول اثنين
print(a[-2:]) # [4, 5] — آخر اثنين
print(a[::2]) # [0, 2, 4] — كل عنصر ثانٍ
print(a[::-1]) # [5, 4, 3, 2, 1, 0] — معكوسة
print(a[:]) # نسخة من القائمة كلها
على خلاف الفهرس، لا تسبب الشريحة خارج حدود القائمة أي خطأ: a[10:20] تعيد [] ببساطة. ويمكن إسناد قيمة إلى شريحة لاستبدال جزء من القائمة: a[1:3] = ["x", "y", "z"].
شريحة النص
تعمل الشرائح بالطريقة نفسها على أي متتالية، ومنها النصوص والصفوف:
s = "Python 3.15"
print(s[:6]) # Python
print(s[-4:]) # 3.15
print(s[::-1]) # 51.3 nohtyP
لا يمكن تعديل نص بالشريحة، فالنصوص غير قابلة للتعديل، والشريحة تنشئ نصاً جديداً.
ترتيب القائمة: sort وsorted
هنا يقع المبتدئون في الخلط أكثر من غيره. الطريقة sort تعيد ترتيب العناصر داخل القائمة نفسها وتعيد None. أما الدالة sorted فلا تمس القائمة الأصلية، وتعيد قائمة جديدة مرتبة.
amounts = [250, 1200, 99]
amounts.append(450)
print(sorted(amounts)) # [99, 250, 450, 1200] — نسخة جديدة
print(amounts) # [250, 1200, 99, 450] — الأصلية لم تتغير
result = amounts.sort() # ترتيب في المكان نفسه
print(result, amounts) # None [99, 250, 450, 1200]
ومن هنا الخطأ الكلاسيكي «لماذا تظهر لي None»: الكتابة a = a.sort() تمسح القائمة وتضع فيها القيمة None. اكتب إما a.sort() وإما a = sorted(a).
المفتاح والترتيب العكسي
يقبل الاثنان المعاملين key وreverse. والمعامل key دالة تُقارَن العناصر بحسب نتيجتها.
words = ["قهوة", "تاكسي", "اشتراك"]
print(sorted(words, key=len)) # ['قهوة', 'تاكسي', 'اشتراك'] حسب الطول
print(sorted(words, key=str.lower)) # دون مراعاة حالة الأحرف اللاتينية
print(sorted([3, 1, 2], reverse=True)) # [3, 2, 1]
expenses = [("طعام", 650), ("سينما", 120), ("تاكسي", 300)]
expenses.sort(key=lambda e: e[1]) # حسب المبلغ
الترتيب في Python ثابت: العناصر التي لها المفتاح نفسه تحافظ على ترتيبها الأصلي. والفرق أيضاً في نطاق الاستخدام: تقبل sorted أي متتالية (نصاً أو قاموساً أو مجموعة)، أما sort فهي موجودة في القوائم فقط.
عكس القائمة
ثلاث طرق لها سلوكيات مختلفة:
a.reverse()— تعكس القائمة في مكانها، وتعيدNone؛a[::-1]— قائمة جديدة معكوسة؛reversed(a)— مُكرِّر كسول، مناسب داخل الحلقة:for x in reversed(a):.
المرور على القائمة
items = ["قهوة", "مترو", "سينما"]
for item in items:
print(item)
for i, item in enumerate(items, start=1):
print(i, item) # 1 قهوة، 2 مترو، 3 سينما
print("سينما" in items) # True — التحقق من وجود العنصر
لا تحذف عناصر من القائمة التي تمر عليها الحلقة، فسيُتخطّى بعض العناصر. اجمع العناصر المطلوبة في قائمة جديدة بمولّد، أو مرّ على نسخة a[:].
توليد القوائم (list comprehension)
يبني مولّد القوائم قائمة جديدة في سطر واحد: تعبير، وحلقة، وشرط اختياري.
squares = [n * n for n in range(6)] # [0, 1, 4, 9, 16, 25]
big = [a for a in [250, 1200, 99] if a > 200] # [250, 1200]
names = [s.strip() for s in [" أمينة ", "عمر"]] # ['أمينة', 'عمر']
مولّدات القوائم عادةً أسرع وأسهل قراءة من الحلقة التي تستخدم append. لكن إذا لم يتسع المنطق لسطر واحد مفهوم، فالحلقة العادية أفضل.
دمج القوائم وجمعها وطرحها
a = [1, 2, 3]
b = [3, 4]
print(a + b) # [1, 2, 3, 3, 4] — قائمة جديدة
a += b # مثل a.extend(b)
print([*a, *b]) # فك التعبئة في قائمة جديدة
لا يوجد طرح قوائم بالعامل -. لإزالة عناصر قائمة من أخرى استخدم مولّداً: [x for x in a if x not in set(b)]. ويسهل إيجاد التقاطع بين القوائم عبر المجموعات: set(a) & set(b) (لكن الترتيب والتكرار يضيعان في هذه الحالة).
القوائم المتداخلة والثنائية الأبعاد
قائمة القوائم طريقة بسيطة لحفظ جدول أو مصفوفة:
matrix = [[1, 2, 3], [4, 5, 6]]
print(matrix[1][2]) # 6
grid = [[0] * 3 for _ in range(2)] # الطريقة الصحيحة
bad = [[0] * 3] * 2 # فخ: مرجعان لقائمة واحدة
bad[0][0] = 9
print(bad) # [[9, 0, 0], [9, 0, 0]]
فك تعبئة القائمة
first, second, third = [10, 20, 30]
head, *rest = [1, 2, 3, 4] # head=1, rest=[2, 3, 4]
print(*["a", "b"], sep=", ") # a, b — طباعة عناصر القائمة بلا أقواس
إذا لم يتطابق عدد المتغيرات مع طول القائمة يظهر ValueError، وتنقذك النجمة في هذه الحالة.
نسخ القائمة
التعبير b = a لا ينسخ القائمة، بل يضع اسماً ثانياً على الكائن نفسه، فتظهر التغييرات التي تجريها عبر b في a. النسخة المستقلة تُنشأ صراحةً: a.copy() أو list(a) أو a[:]. ولكن مع البيانات المتداخلة لا تكفي هذه الطرق، فالقوائم الداخلية تبقى مشتركة، ويلزم copy.deepcopy(a).
import copy
a = [[1, 2], [3]]
b = a.copy()
b[0].append(99)
print(a) # [[1, 2, 99], [3]] — القائمة الداخلية مشتركة
c = copy.deepcopy(a) # نسخة مستقلة تماماً
الصفوف: قائمة غير قابلة للتعديل
الصف (tuple) يشبه القائمة، لكن لا يمكن تعديله بعد إنشائه. وهذه إشارة واضحة للقارئ: أمامه سجل بحقول ثابتة، لا مجموعة تنمو. والصفوف تُفكّ بسهولة، ولهذا تُرجع الدوال بها عدة قيم.
expense = (250, "قهوة")
amount, item = expense
expense[0] = 300
# TypeError: 'tuple' object does not support item assignment
الصف المكوّن من قيم غير قابلة للتعديل قابل للتجزئة (hash)، لذلك يصلح مفتاحاً في القاموس. أما الصف المكوّن من عنصر واحد فيُكتب مع فاصلة: (5,).
المجموعات: القيم الفريدة فقط
المجموعة (set) تحفظ القيم الفريدة فقط ولا تحفظ الترتيب. وهي أسرع طريقة لإزالة التكرار والتحقق من «هل يوجد هذا العنصر»، وتدعم كذلك التقاطع والاتحاد والفرق.
jan = {"طعام", "تاكسي", "سينما"}
feb = {"طعام", "اشتراكات"}
print(jan & feb) # {'طعام'}
print(feb - jan) # {'اشتراكات'}
unique = list(dict.fromkeys([3, 1, 3, 2])) # [3, 1, 2] — دون تكرار مع الحفاظ على الترتيب
empty = set() # {} — هذا قاموس فارغ!
أي مجموعة تختار
| المهمة | المجموعة |
|---|---|
| ترتيب مع إمكانية التعديل | list |
| سجل بحقول ثابتة | tuple |
| البحث بالمفتاح | dict |
| التفرد والتحقق من الوجود | set |
| إعدادات غير قابلة للتعديل | frozendict (Python 3.15) |
الفحص x in list يمر على العناصر واحداً تلو الآخر، أما x in set فيعمل تقريباً في لحظة. وإذا كنت تتحقق كثيراً داخل حلقة من وجود عنصر في قائمة كبيرة، فحوّلها إلى مجموعة.
الخلاصة
قائمة Python مجموعة مرتبة قابلة للتعديل: تضيف append وextend، وتحذف pop وremove، وتأخذ الشرائح a[start:stop:step] أجزاءها، وترتب sort في المكان وتعيد None، بينما تعيد sorted قائمة جديدة. انسخ صراحةً عند الحاجة، واختر الصف للسجلات الثابتة، والمجموعة للقيم الفريدة. وقد شُرحت القوائم والصفوف والقواميس والمجموعات عملياً في دورة «بايثون 3.15: من المبتدئ إلى المحترف».
الأسئلة الشائعة
ما الفرق بين القائمة والمصفوفة في Python؟
ليس في Python مصفوفة مضمنة بالمعنى المعروف في لغات أخرى، ويؤدي القائمة دورها، وهي تحفظ قيماً من أنواع مختلفة. للمصفوفات الرقمية المضغوطة توجد الوحدة array ومكتبة NumPy.
كيف أجد فهرس عنصر في القائمة؟
تعيد الطريقة a.index(x) فهرس أول ظهور، وترفع ValueError إن لم يوجد العنصر، لذلك تحقق من x in a قبل استدعائها.
كيف أزيل التكرار من قائمة مع الحفاظ على الترتيب؟
استخدم list(dict.fromkeys(a)): القاموس يحفظ المفاتيح فريدة وبترتيب الإدخال. أما list(set(a)) فتزيل التكرار أيضاً لكنها لا تحافظ على الترتيب.
كيف أدمج قائمة نصوص في نص واحد؟
بالطريقة join للنص: ", ".join(["a", "b", "c"]) تعطي "a, b, c". ويجب أن تكون العناصر نصوصاً، وتُحوَّل الأرقام أولاً بالدالة map(str, a).
هل يمكن أن تحتوي القائمة على عناصر من أنواع مختلفة؟
نعم، فالقائمة تحفظ أرقاماً ونصوصاً وقوائم أخرى وكائنات مختلفة في الوقت نفسه. لكن ترتيب مثل هذه القائمة دون معامل key غالباً غير ممكن، لأن مقارنة الرقم بالنص تعطي TypeError.
يُشرح هذا الموضوع بالتفصيل مع التطبيق العملي في دورة «Python 3.15: от новичка до профи».
الانتقال إلى الدورة