القوائم والجداول (Lists and Tuples)
خزّن المتتاليات واستكشف توماس الغوص في القوائم والجداول.
- إنشاء القوائم والوصول إلى عناصرها وتعديلها
- استخدام الجداول كمتتاليات غير قابلة للتعديل
- اختيار بين القوائم والجداول
- نسخ التسلسلات دون المشاركة المريبة لمراجع الكائنات
المتتالية المرتّبة القابلة للتعديل
القائمةُ تسلسلٌ تستطيع تنميته وتقليصه وإعادة ترتيبه. والوصولُ يطيع كلَّ ما علّمك إياه التقسيم:
fruits = ["apple", "banana", "cherry"]
print(fruits[0]) # apple
print(fruits[-1]) # cherry
print(fruits[0:2]) # ['apple', 'banana']الفهرسةُ من صفرٍ، والمؤشراتُ السالبةُ العدَّ عكسيًّا، والشرائحُ آخذةً نوافذَ ، المهاراتُ الثلاثُ نفسُها، موجّهةً الآن إلى مجموعةِ أيِّ كائناتٍ. وحيث كانت السلسلةُ مجمَّدةً، كانت القائمةُ طينًا.
عدةُ القائمة
الطرقُ ورشةُ تعديلاتٍ:
nums = [3, 1, 4, 1, 5]
nums.append(9) # [3, 1, 4, 1, 5, 9]
nums.insert(0, 0) # [0, 3, 1, 4, 1, 5, 9]
nums.extend([2, 6]) # [0, 3, 1, 4, 1, 5, 9, 2, 6]
nums.pop() # يزيل 9 ويرجعه
nums.remove(1) # يزيل أول 1
nums.sort() # يرتّب في موضعه
nums.reverse() # يعكس في موضعه
len(nums) # الطول الحالييضيف append عنصرًا واحدًا في النهاية؛ ويصبّ extend تسلسلًا كاملًا؛ ويُنزلق insert عنصرًا في مركزٍ مختارٍ. يزيل pop من النهاية (أو من مركزٍ معيّنٍ) ويُسلّمك القيمةَ المزالة؛ ويمحو remove أولَ عنصرٍ مطابقٍ. وإنّ القائمةَ لابنُ العمِّ القابلُ للتغييرِ لخيولِ عملٍ كامتدادِ أرقامِ ، خيطُ قيمٍ متنامٍ ظللتَ تحرّره.
قوائم داخل قوائم: جداول ومصفوفات
يمكن أن تكون عناصرُ القائمةِ قوائمَ بدورها، ما يحوّل تسلسلًا مسطحًا إلى جدول ، المصفوفةُ قائمةٌ من الصفوف، وكلُّ صفٍّ قائمةُ أعدادٍ:
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
print(matrix[1][2]) # 6 — الصف 1، العمود 2
print(matrix[1]) # [4, 5, 6]يختار matrix[1] الصفَّ الثاني؛ وإضافةُ [2] تنزل إلى ذلك الصفِّ وتختار عنصرَه الثالث. يُخاطب العنوانانِ خليةً تمامًا كما يسمّي العددُ السفليُّ مدخلًا في مصفوفةٍ على الورق. الحيلةُ نفسُها تبني شبكاتٍ ولوحاتِ ألعابٍ وصفوفَ جداولِ بياناتٍ.
الطفرة مقابل قائمةٍ جديدة: شوكةٌ تعض
هنا خللٌ يكدّم المبتدئين. بعضُ الطرق تُحدِث طفرةً في القائمة وترجع None؛ وبعضُها يرجع قائمةً جديدةً ويترك الأصلَ سليمًا. وصوتُ الطريقة لا يخبرك بأيةٍ هما:
nums = [3, 1, 2]
result = nums.sort() # result هو None! nums الآن [1, 2, 3]
result = sorted(nums) # result هو [1, 2, 3]، nums لم تتغيريرتّب nums.sort() في موضعٍ ولا يرجع شيئًا ، قيمةُ تعبيرك هي None. بينما يحسب sorted(nums) قائمةً جديدةً مرتّبةً ويترك nums كما هي. والاسمُ هو الإشارة: أفعالٌ كـ sort وreverse تلمس الكائنَ؛ وsorted وlist.copy() ترسمان نسخةً لمالكٍ جديد.
الجداول: المتتالية المجمَّدة
الجَدْوِلُ متتاليةٌ مرتّبةٌ غيرُ قابلةٍ للتعديل ، قائمةٌ فقدت أداةَ تحريرها:
point = (3, 4)
print(point[0]) # 3
# point[0] = 5 # TypeError!عدمُ القابليةِ للتعديل ليس عجزًا؛ إنه وعدٌ. النقطةُ كائنٌ رياضيٌّ واحدٌ لا ينبغي أن يتغير تحت قدميك. الإحداثياتُ، وألوانُ RGB، وصفوفُ قواعدِ البيانات ، البياناتُ الثابتةُ بالتعريف تخصّ الجداول، حيث يصبح إسنادُ العَرَضِ استثناءً لا فسادًا صامتًا.
التفكيك: سطرٌ واحدٌ بأسماءٍ كثيرة
يستطيع تسلسلٌ أن يطويَ نفسَه في متغيراتٍ متعددةٍ في إسنادٍ واحدٍ. وتجمع بايثون حتى الفائضَ باسمٍ بنجمٍ:
x, y = (3, 4) # x=3, y=4
a, b, *rest = [1, 2, 3, 4, 5] # a=1, b=2, rest=[3, 4, 5]
first, *_, last = (1, 2, 3, 4) # first=1, last=4يبتلع *rest كلَّ ما بين الشقوق المسمّاة؛ و*_ نفسُ الإيماءةِ تحمل اسمَ «تجاهل هذا» المعهودَ. إنها نسخةُ القائمةِ من تقييم دالةٍ عند نقطةٍ ، مدخلاتٌ ومخرجاتٌ تناصفٌ وفقًا للموقع.
مثالٌ محلول: دفترُ الدرجات
شاهدِ الأدواتِ تعمل في مهمةٍ واقعية ، درجاتُ الصفِّ في اختبارٍ:
scores = []
scores.append(8)
scores.append(6)
scores.extend([9, 7, 10])
total = sum(scores) # sum() تجمع كل عنصر
best = max(scores) # max() تجد الأكبر
count = len(scores) # len() تعدّها
average = total / count
print(average) # 8.0
print(best) # 10اجمع بـ append/extend ثم اقرأ بـ sum وmax وlen. لاحظِ القسمةَ: total / count هي المتوسطُ الحسابي ، وهو نفسُ الذي تعرفه من الرياضيات، الآن في سطرٍ واحد. القائمةُ مكانٌ لتجميعِ البيانات، والدورةُ بين إشباعِها وقراءتِها هي النمطُ الذي يكرّره كلُّ برنامجٍ حقيقيٍّ.
أخطاء شائعة
sort()يرجعNone. إذا أردت قائمةً جديدةً، فدَعsorted()يحمل القيمةَ.- خلطُ النسخِ السطحي. يصنع
a = bاسمينِ لقائمةٍ واحدةٍ؛ أماa = b.copy()أوa = list(b)فيبنيان قائمةً منفصلةً. - مزج الأنواع.
[1, "two", 3.0]مشروعٌ لكنه يُعسّر المقارناتِ والاستدلال؛ أبْقِ المجموعاتِ صادقةً على محتوياتها. appendمقابلextend. يجعلnums.append([1, 2])قائمةً متداخلةً عنصرًا واحدًا؛ بينما يُفرّغnums.extend([1, 2])عناصرها عناصرَ منفصلةً.- يحذف
removeأولَ تطابقٍ فقط. يترك[1, 2, 1].remove(1)القائمةَ[2, 1]؛ ويمسحُ النسخَ كلَّها حلقةٌ (درسٌ لاحق).
🧩 تحديات
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
احذف التكرارات محافظًا على الترتيب: [1, 3, 2, 3, 1, 4, 2] ← [1, 3, 2, 4].
💡 الجواب: list(dict.fromkeys(nums)) ، يحفظ القاموسُ ترتيبَ الإدراج (منذ 3.7)، وتنطوي المفاتيحُ المكررةُ إلى موضعها الأول.
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
بادل بين متغيرينِ دون متغيرٍ مؤقتٍ، مستخدمًا تفكيكَ الجداول.
💡 الجواب: a, b = b, a ، يُقيَّم الطرفُ الأيمنُ جدولًا أولًا، فالمبادلةُ آنيةٌ لا تتابعيةٌ.
🤔 أسئلة سقراطية
- متى تلجأ إلى جَدْوِلٍ دون قائمةٍ، وماذا تشتري لك عدمُ القابليةِ للتعديل؟
- لماذا يُحدِث
sort()طفرةً حيث يرجعsorted()جديدًا ، ومتى تفضّل كلًّا؟ - كيف يجمع
*restالفائضَ؟ وهل يقدر*_على نيابةِ تجاهلٍ مسموٍّ؟
✅ فحص سريع
١. ماذا يطبع هذا؟ a = [1, 2]; b = a; b.append(3); print(a)؟
٢. أيهما صحيح؟ a, b, c = [1, 2]