List Comprehension في Python: بناء القوائم في سطر واحد
كثيراً ما تحتاج أن تبني قائمة جديدة من قائمة موجودة: مربعات الأرقام، أو الأسماء بحروف كبيرة، أو الدرجات الناجحة فقط. تعلمت أن تفعل ذلك بحلقة for و append. في هذا الدرس ستتعلم طريقة أقصر وأجمل يحبها مبرمجو Python: List Comprehension، أي بناء القائمة بصيغة مختصرة.
من الحلقة إلى سطر واحد
Section titled “من الحلقة إلى سطر واحد”لنفترض أننا نريد قائمة بمربعات الأرقام. هذه الطريقة التي تعرفها:
numbers = [1, 2, 3, 4, 5]
squares = []for n in numbers: squares.append(n * n)
print(squares)[1, 4, 9, 16, 25]ثلاثة أسطر لفكرة بسيطة. والآن الفكرة نفسها بالصيغة المختصرة:
squares = [n * n for n in numbers]print(squares)[1, 4, 9, 16, 25]اقرأها كأنها جملة عادية: «ضع n * n لكل n في numbers». الصيغة العامة هي:
[التعبير for العنصر in المصدر]- التعبير: ما تريد وضعه في القائمة الجديدة.
- العنصر: اسم مؤقت لكل قيمة، مثل متغير الحلقة تماماً.
- المصدر: قائمة، أو
range، أو نص، أو أي شيء يمكن المرور عليه.
تخيّلها مثل خط إنتاج في مصنع: تدخل العناصر من جهة واحداً واحداً، تُجرى على كل عنصر العملية نفسها، وتخرج من الجهة الأخرى قائمة جديدة.
أمثلة على التحويل
Section titled “أمثلة على التحويل”التعبير يمكن أن يكون أي شيء: عملية حسابية، أو استدعاء دالة، أو تابعاً من توابع النصوص:
names = ["sara", "omar", "laila"]
print([name.capitalize() for name in names])print([len(name) for name in names])print([n * 10 for n in range(1, 6)])['Sara', 'Omar', 'Laila'][4, 4, 5][10, 20, 30, 40, 50]لاحظ أن القائمة الأصلية names لم تتغير. الصيغة المختصرة تنشئ دائماً قائمة جديدة.
التصفية بالشرط if
Section titled “التصفية بالشرط if”يمكنك إضافة شرط في آخر الصيغة، فلا يدخل القائمة الجديدة إلا العنصر الذي يحقق الشرط:
evens = [n for n in range(1, 11) if n % 2 == 0]print(evens)
long_names = [name for name in names if len(name) > 4]print(long_names)[2, 4, 6, 8, 10]['laila']اقرأها: «ضع n لكل n من 1 إلى 10 إذا كان n زوجياً». وتستطيع الجمع بين التحويل والتصفية معاً:
grades = [45, 80, 62, 30, 91]bonus = [g + 5 for g in grades if g >= 50]print(bonus)[85, 67, 96]هنا اخترنا الدرجات الناجحة فقط، وأضفنا لكل واحدة خمس درجات.
الاختيار بين قيمتين: if و else
Section titled “الاختيار بين قيمتين: if و else”ماذا لو أردت كل العناصر، لكن بقيمة مختلفة حسب الشرط؟ هنا نكتب if و else في أول الصيغة، داخل التعبير نفسه:
results = ["ناجح" if g >= 50 else "راسب" for g in grades]print(results)['راسب', 'ناجح', 'ناجح', 'راسب', 'ناجح']القواميس والمجموعات أيضاً
Section titled “القواميس والمجموعات أيضاً”الفكرة نفسها تعمل مع القواميس والمجموعات، لكن بأقواس معقوفة:
prices = {"قلم": 5, "دفتر": 12, "حقيبة": 150}
doubled = {item: price * 2 for item, price in prices.items()}print(doubled)
lengths = {len(word) for word in ["أحمد", "منى", "علي", "سارة"]}print(lengths){'قلم': 10, 'دفتر': 24, 'حقيبة': 300}{3, 4}في القاموس نكتب المفتاح: القيمة قبل for. وفي المجموعة حُذف التكرار تلقائياً كما تعلمت في درس المجموعات: أربعة أسماء، لكن طولين مختلفين فقط.
مع الدوال الجاهزة
Section titled “مع الدوال الجاهزة”إذا كنت سترسل النتيجة مباشرة إلى دالة مثل sum أو max، فيمكنك حذف الأقواس المربعة:
print(sum(n * n for n in numbers))print(max(len(name) for name in names))555جرّب بنفسك
Section titled “جرّب بنفسك”عندك قائمة درجات الحرارة بالمئوية: [0, 18, 25, 37, 100]. اكتب بالصيغة المختصرة:
- قائمة بالدرجات نفسها بالفهرنهايت (المعادلة:
c * 9 / 5 + 32). - قائمة بالدرجات الأعلى من 20 فقط.
- قائمة فيها «حار» إذا كانت الدرجة 30 أو أكثر، و«معتدل» لغير ذلك.
[32.0, 64.4, 77.0, 98.6, 212.0][25, 37, 100]['معتدل', 'معتدل', 'معتدل', 'حار', 'حار']أخطاء شائعة
Section titled “أخطاء شائعة”- نسيان الأقواس المربعة:
squares = (n * n for n in numbers)بأقواس عادية لا تنشئ قائمة، بل شيئاً اسمه «مولّد»، وعند طباعته ترى<generator object ...>بدلاً من الأرقام. - وضع
elseفي الآخر:[n for n in numbers if n > 2 else 0]خطأ في الصياغة.if ... elseتُكتب قبلfor. - استخدامها لتنفيذ أوامر فقط: لا تكتب
[print(n) for n in numbers]. إذا كنت لا تحتاج القائمة الناتجة، فالحلقة العادية هي الصحيحة. - الإفراط في التعقيد: سطر واحد لا يفهمه أحد ليس أفضل من أربعة أسطر واضحة.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ما ناتج [n + 1 for n in [1, 2, 3]]؟
التعبير n + 1 يُطبَّق على كل عنصر، فيزيد كل رقم واحداً.
سؤال
ما ناتج [n for n in range(6) if n > 3]؟
range(6) تعطي الأرقام من 0 إلى 5، والشرط يُبقي الأكبر من 3 فقط: 4 و 5.
الخلاصة
Section titled “الخلاصة”- الصيغة
[تعبير for عنصر in مصدر]تبني قائمة جديدة في سطر واحد. ifفي آخر الصيغة تصفّي العناصر، وif ... elseفي أولها تختار بين قيمتين.- الفكرة نفسها تعمل مع القواميس والمجموعات بأقواس معقوفة.
- القائمة الأصلية لا تتغير، والنتيجة قائمة جديدة.
- استخدمها عندما تجعل الكود أوضح، لا أعقد.