فهم القوائم (List Comprehensions)
أنشئ القوائم بإيجاز باستخدام فهم القوائم ، الطريقة الأكثر تعبيرًا في بايثون.
- كتابة فهم القوائم للتحويل والتصفية
- استخدام فهم الشرط لضمان خلط المنطق
- بناء القواميس والمجموعات عبر الفهم
- فهم متى يكون الفهم أكثر وضوحًا من الحلقات
تدوينُ بناءِ المجموعاتِ شيفرةً
لِلرياضياتِ طريقٌ مقتضَبٌ لوصفِ مجموعةٍ مبنيةٍ من أخرى: باني المجموعات. والفهمُ هو ذلك التدوينُ مكتوبًا مباشرةً:
اقرأ «مجموعةَ ، لكلِّ في هذا المصدر» ، وبايثونُ هي الجملةُ نفسها مقلوبةً شيفرةً:
# حلقة عادية
squares = []
for x in range(6):
squares.append(x ** 2)
# فهم
squares = [x ** 2 for x in range(6)]
# [0, 1, 4, 9, 16, 25]تهجّي الحلقةُ ثلاثَ حركاتٍ ، البدءَ فارغًا، والإضافةَ، والإعادةَ؛ بينما يعلن الفهمُ المجموعةَ كلَّها في سطرٍ واحدٍ يحاكي تشريحَ الباني: التعبيرُ في المقدمة، والمتغيرُ المَجالتُ خلفه.
التصفيةُ بالشروط
يحمل تدوينُ البناءِ أيضًا اختباراتِ إدماجٍ. فـ يصيرُ if في الذيل:
evens = [x for x in range(10) if x % 2 == 0]
# [0, 2, 4, 6, 8]
long_words = [w.upper() for w in ["hi", "hello", "hey"] if len(w) > 2]
# ['HELLO', 'HEY']if في النهاية مصفاةٌ: لا يبلغُ التعبيرَ إلا ما اجتازها. يقطع العنصرُ الطريقَ تعبيرٌ ← مصفاةٌ ← قائمةٌ، بالترتيبِ الذي تُقرأ به الجملة.
If/else بصفته تعبيرًا
إنّ if...else الذي تعرفه تعبيرٌ ، ينتج قيمةً. ولصقُ واحدٍ قبل for يزرعه في خطّ البناء، مختارًا بحسب العنصرِ لا مصفِّيًا بحسبِه:
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
# ['even', 'odd', 'even', 'odd', 'even']الموضعانِ شوكةٌ بمهمتينِ مختلفتين: بعدَ for تصوّت الجملةُ على العناصر؛ وقبلَ for تسمّيها. أولاهما تطرح، وأخراهما تحوّل.
فهمُ القواميس
يبني الشكلُ نفسه أزواجَ الاقتران ، التعبيرُ يسارَ النقطتين يصيرُ المفتاحَ، والذي عن يمينهما القيمةَ:
squares_dict = {x: x**2 for x in range(6)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# عكس قاموس
original = {"a": 1, "b": 2}
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b'}العكسُ هو الشاهدُ الأنيق: تجوّل على items() وبادل أيُّ نصفٍ من كل زوجٍ يصيرُ المفتاحَ.
فهمُ المجموعات
الأقواسُ المعقوفةُ مع فهمٍ تنتج مجموعةً ، فُرضتِ الفرديةُ تلقائيًّا:
lengths = {len(word) for word in ["hello", "hi", "hey"]}
# {2, 3, 5} (أطوال فريدة)تنطوي ثلاثةُ أطوالٍ إلى مجموعةِ قيمٍ، مسقطةً ما تكرر كما يجبُ على مجموعةٍ.
الفهمُ المتداخلُ: المُسطِّح
المصفوفةُ قائمةُ صفوفٍ، وتسطيحُها حلقتانِ في تعبيرٍ واحدٍ ، اقرأ جُملتَي for من اليسار يمينًا، الخارجيةَ أولًا:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]تفتح كلُّ for مستوىً: تجوب row القائمةَ الخارجيةَ، وتجوب num كلَّ صفٍّ، ويتبع ترتيبُ المجموعةِ الحلقتينِ حذوًا.
مثالٌ محلول: ثلاثُ سطورٍ من مُنشئِ المجموعات
حركاتُ الدرسِ الثلاثُ ، بناءٌ وتصفيةٌ وتسميةٌ ، سطرٌ لكلٍّ منها:
squares = [x ** 2 for x in range(2, 9)]
# [4, 9, 16, 25, 36, 49, 64]
numbers = [x for x in range(1, 11) if x % 3 == 0]
# [3, 6, 9]
labels = ["even" if x % 2 == 0 else "odd" for x in numbers]
# ['odd', 'even', 'odd']أولُها هو مكتوبٌ كما هو؛ وثانيها يصفّي قواسمَ ؛ وثالثها يسمّي كلَّ ناجٍ. ما يقوله مُنشئُ المجموعاتِ بنَفَسٍ واحدٍ، يتهجّاه الفهمُ في سطرٍ.
متى لا نستخدمُ الفهمَ
- حين تعقُد المنطقُ ، الحلقةُ العاديةُ تجني لها وضوحَها.
- حين يحتاج الجسمُ
try/except، لا متسعَ للفهمِ له. - حين تُهمّ الآثارُ الجانبيةُ ، الطباعةُ والكتابةُ في ملفاتٍ ينبغي أن تكون جملًا متعمَّدةً لا تعبيراتٍ صامتةً.
- وضعُ
ifقبلَforيسمّي ولا يصفّي.[x if x % 2 == 0 else 'odd' for x in ...]يُبقي كلَّ عنصرٍ، مسمًّى فحسب؛ ولا يُسقِطُ إلاifبعدَfor. في الموضعِ الخاطئِ يبقى المرفوضونَ صامتينَ.
🧩 تحديات
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
سطّح [[1, 2], [3, 4], [5, 6]] إلى [1, 2, 3, 4, 5, 6] بفهمٍ.
💡 الجواب: [num for row in matrix for num in row] ، الحلقةُ الخارجيةُ تفتح كلَّ صفٍّ، والداخليةُ تفرشه.
🧩 تحدٍّ ، فكّر أولًا ثم أظهر
اربط الكلماتَ بأطوالها بفهمِ قاموسٍ: ["hi", "hello", "hey"] ← {"hi": 2, "hello": 5, "hey": 3}.
💡 الجواب: {w: len(w) for w in words} ، الكلمةُ هي المفتاحُ وطولُها هي القيمةُ، زوجٌ لكل مدخلٍ.
🤔 أسئلة سقراطية
- لماذا يقف
if...elseقبلَforفي فهمٍ بينما يتأخرifالمصفاةُ بعده؟ - أين يعبر فهمٌّ الخطَّ نحو قراءةٍ أصعبَ من حلقةٍ؟ وأين ترسمه أنت؟
- هل يستطيع
awaitالظهورَ داخلَ فهمٍّ ، وأيُّ صيغةٍ تُتيح نسخةً لامتزامنةً كاملةً؟
✅ فحص سريع
١. ماذا ينتج [x * 2 for x in range(4) if x > 1]؟
٢. أيُّ فهمِ قاموسٍ صحيح؟