الـ tuple في بايثون: قائمة لا يمكن تعديلها
لأول وهلة، يبدو أن الـ tuples والـ lists في بايثون متشابهان — كلاهما تسلسل مرتّب، وكلاهما يدعم الفهرسة والتكرار — لكن هناك فرقًا جوهريًا واحدًا يُغيّر كل شيء: الـ tuples غير قابلة للتعديل (immutable). بمجرد إنشاء tuple، لن تستطيع إضافة عنصر إليه أو حذف عنصر منه أو استبدال أي قيمة داخله.
تُكتب الـ tuples باستخدام الأقواس الهلالية (وأحيانًا بدونها):
الـ tuple اللي يحتوي على عنصر واحد لازم تحط بعده فاصلة، وإلا بايثون راح يعتبر الأقواس مجرد أقواس تجميع عادية:
أمّا لإنشاء tuple فارغ، فاستخدم ():
الثبات (Immutability) عمليًا
جرّب تعديل أي tuple في بايثون، وسترى كيف يرفض المترجم ذلك فورًا:
يمكنك القراءة من الـ tuple بحرية تام — الفهرسة والتقطيع والتكرار واستخدام in — لكن لا يمكنك تعديله. وإذا احتجت إلى tuple مختلف، فما عليك سوى إنشاء واحد جديد.
لماذا نستخدم شيئًا لا يمكن تغييره؟
قد تبدو خاصية immutable في بايثون قيدًا للوهلة الأولى، لكنها في الغالب هي المزية التي تبحث عنها فعلًا.
- الأمان. عند تمرير tuple إلى دالة، فلن يستطيع أحد تعديله من وراء ظهرك.
- قابلية التجزئة (Hashability). يمكن استخدام الـ tuples التي تحتوي على قيم غير قابلة للتغيير كمفاتيح لـ dictionary أو كعناصر داخل set، بينما لا يمكن فعل ذلك مع الـ lists.
- وضوح النية. الـ tuple يقول ضمنيًا: "هذا سجل ذو شكل ثابت". فكتابة
point = (3, 4)تُعبّر عن "إحداثيَّين" بشكل أوضح بكثير منpoint = [3, 4].
تتألق الـ tuples في حالات مثل:
- الإحداثيات:
(x, y)،(lat, lon) - ألوان RGB:
(255, 128, 0) - السجلات:
(name, email, signup_date) - إرجاع قيم متعددة من دالة بايثون
تفكيك الـ Tuple (Unpacking)
الـ tuples وصيغة الـ unpacking في بايثون مصنوعتان لبعضهما البعض:
الفاصلة هنا هي اللي بتقوم بعملية الـ unpacking. بايثون بيشوف اسمين وفي المقابل tuple بداخله قيمتين، فيقوم بربط كل اسم بالقيمة المقابلة له.
وهذا الأسلوب ستجده في كل مكان في كود بايثون الاصطلاحي (Pythonic):
يمكنك استخدام * لتجميع "الباقي":
مفيدة لما تهمّك أول القيم وآخرها فقط.
استخدام tuple كمفتاح dictionary
بما أن الـ tuples قابلة للتجزئة (hashable) طالما أن محتوياتها كذلك، فيمكنك استخدامها كمفاتيح في الـ dictionary. الـ lists لا تدعم هذا الأمر:
هذا النمط — استخدام مجموعة من القيم كمفتاح — مفيد بشكل يفوق التوقعات. تخيّل معي: "نتيجة المستخدم X في اليوم Y"، أو "أفضل مسار من A إلى B".
إرجاع قيم متعددة من دالة بايثون باستخدام tuples
عندما تحتاج الدالة إلى إرجاع أكثر من قيمة، فإنها عادةً ما تُرجعها على هيئة tuple:
دالة divmod() المدمجة في بايثون تقوم بهذا العمل بالضبط، وأسلوب فك الإسناد (destructuring) في الكود المستدعي يجعل القراءة سلسة وطبيعية.
namedtuple في بايثون: لمّا الترتيب ما يكفي
لما يكبر الـ tuple عندك ويتجاوز عنصرين أو ثلاثة، يصير من المتعب أن تتذكر معنى كل موضع. هنا يجي دور collections.namedtuple ليحل المشكلة:
الآن أصبح لعناصر الـ tuple أسماء. هو لا يزال immutable ولا يزال tuple (يعني الـ unpacking والفهرسة تشتغلان بشكل طبيعي)، لكن طريقة الوصول إلى العناصر صارت أوضح بكثير. وإذا احتجت شيئًا أكثر تعقيدًا، فهناك dataclasses — وسنتعرف عليها لاحقًا في فصل الكلاسات.
Tuple أم List؟ دليل سريع لاتخاذ القرار
- شكل ثابت وكل موضع له معنى محدد ← استخدم tuple.
- مجموعة قد تكبر أو تصغر ← استخدم list.
- إرجاع قيم متعددة من دالة ← tuple.
- تحتاج مفتاحًا لـ dictionary أو عنصرًا في set ← tuple (الـ list لن ينفع هنا).
- ستقوم بتعديل العناصر ← list (الـ tuple لن يسمح لك بذلك).
لننتقل للأمام
الـ tuples تغطي طرفًا واحدًا من الطيف: بنية ثابتة وصغيرة ومنظمة. في الدرس القادم سنتناول الـ sets، وهي تؤدي مهمة مختلفة تمامًا: التحقق السريع من وجود عنصر، وضمان عدم تكرار القيم.
الأسئلة الشائعة
ما هو الـ tuple في بايثون؟
الـ tuple عبارة عن تسلسل مرتّب وغير قابل للتعديل (immutable) — يشبه الـ list، لكن بمجرد إنشائه لا يمكنك إضافة عناصر أو حذفها أو تغييرها. يُكتب باستخدام الأقواس العادية، مثل: point = (3, 4).
ما الفرق بين الـ tuple والـ list؟
كلاهما تسلسل مرتّب، لكن الـ list قابل للتعديل (mutable) بينما الـ tuple غير قابل للتعديل (immutable). نستخدم الـ tuple عادةً لتجميع قيم صغيرة مرتبطة ببعضها كسجل واحد، مثل الإحداثيات أو القيم المتعددة التي تُعيدها دالة واحدة.
متى يُفضَّل استخدام الـ tuple؟
استخدمه عندما يكون لديك سجل بحجم ثابت، وكل موضع فيه له معنى محدد — مثل الإحداثيات، أو ألوان RGB، أو صف من قاعدة بيانات. كذلك يُستخدم الـ tuple كمفتاح في الـ dictionary أو كعنصر في الـ set، لأن الـ list لا يصلح في هذه الحالات. أما إذا كانت المجموعة قابلة للنمو أو التقلّص، فالـ list هو الخيار الافتراضي.