توفر List Comprehensions طريقةً مختصرةً لإنشاء القوائم بناءً على قوائم موجودة مسبقًا. فعند استخدام list comprehensions فيمكن بناء القوائم باستخدام أيّ نوع من البيانات المتسلسلة التي يمكن الدوران على عناصرها عبر حلقات التكرار، بما في ذلك السلاسل النصية و tuples.
من ناحية التركيب اللغوي، تحتوي list comprehensions على عنصر يمكن المرور عليه ضمن تعبيرٍ متبوعٍ بحلقة for
. ويمكن أن يُتبَع ما سبق بتعابير for
أو if
إضافية، لذا سيساعدك الفهم العميق لحلقات for
والعبارات الشرطية في التعامل مع list comprehensions.
توفِّر list comprehensions طريقةً مختلفةً لإنشاء القوائم وغيرها من أنواع البيانات المتسلسلة. وعلى الرغم من إمكانية استخدام الطرائق الأخرى للدوران، مثل حلقات for
، لإنشاء القوائم، لكن من المفضَّل استعمال list comprehensions لأنها تقلِّل عدد الأسطر الموجودة في برنامجك.
List Comprehensions
يمكن بناء list comprehensions في بايثون كالآتي:
list_variable = [x for x in iterable]
ستُسنَد القائمة، أو أي نوع من البيانات يمكن المرور على عناصره، إلى متغير. المتغيرات الإضافية –التي تُشير إلى عناصر موجودة ضمن نوع البيانات الذي يمكن المرور على عناصره– تُبنى حول عبارة for
. والكلمة المحجوزة in
تستعمل بنفس استعمالها في حلقات for
وذلك لمرور على عناصر iterable
.
لننظر إلى مثالٍ يُنشِئ قائمةً مبنيةً على سلسلةٍ نصية:
shark_letters = [letter for letter in 'shark']
print(shark_letters)
أسندنا في المثال السابق قائمةً جديدةً إلى المتغير shark_letters
، واستعملنا المتغير letter
للإشارة إلى العناصر الموجودة ضمن السلسلة النصية 'shark'
.
استعملنا بعد ذلك الدالة print()
لكي نتأكد من القائمة الناتجة والمُسنَدة إلى المتغير shark_letters
، وحصلنا على الناتج الآتي:
['s', 'h', 'a', 'r', 'k']
القائمة التي أنشأناها باستخدام list comprehensions تتألف من العناصر التي تكوِّن السلسلة النصية 'shark'
، وهي كل حرف في الكلمة shark.
يمكن إعادة كتابة تعابير list comprehensions كحلقات for
، لكن لاحظ أنَّك لا تستطيع إعادة كتابة كل حلقة for
بصيغة list comprehensions.
لنعد كتابة المثال السابق الذي أنشأنا فيه القائمة shark_letters
باستخدام حلقة for
، وهذا سيساعدنا في فهم كيف تعمل list comprehensions عملها:
shark_letters = []
for letter in 'shark':
shark_letters.append(letter)
print(shark_letters)
عند إنشائنا للقائمة عبر استخدام الحلقة for
، فيجب تهيئة المتغير الذي سنُسنِد العناصر إليه كقائمة فارغة، وهذا ما فعلناه في أوّل سطر من الشيفرة السابقة. ثم بدأت حلقة for
بالدوران على عناصر السلسلة النصية 'shark'
مستعملةً المتغير letter
للإشارة إلى قيمة العنصر الحالي. ومن ثم أضفنا كل عنصر في السلسلة النصية إلى القائمة ضمن حلقة for
وذلك باستخدام الدالة list.append(x).
الناتج من حلقة for
السابقة يماثل ناتج list comprehension في المثال أعلاه:
['s', 'h', 'a', 'r', 'k']
الخلاصة: يمكن إعادة كتابة List comprehensions كحلقات for
، لكن بعض حلقات for
يمكن إعادة كتابتها لتصبح List comprehensions لتقليل كمية الشيفرات المكتوبة.
استخدام التعابير الشرطية مع List Comprehensions
يمكن استخدام التعابير الشرطية في list comprehension لتعديل القوائم أو أنواع البيانات المتسلسلة الأخرى عند إنشاء قوائم جديدة.
لننظر إلى مثالٍ عن استخدام العبارة الشرطية if
في تعبير list comprehension:
fish_tuple = ('blowfish', 'clownfish', 'catfish', 'octopus')
fish_list = [fish for fish in fish_tuple if fish != 'octopus']
print(fish_list)
استعملنا المتغير fish_tuple
الذي من نوع البيانات tuple كأساس للقائمة الجديدة التي سنُنشِئها التي تسمى fish_list
. استعملنا for
و in
كما في القسم السابق، لكننا أضفنا هنا العبارة الشرطية if
. ستؤدي العبارة الشرطية if
إلى إضافة العناصر غير المساوية للسلسلة النصية 'octopus'
، لذا ستحتوي القائمة الجديدة على العناصر الموجودة في بنية tuple والتي لا تُطابِق الكلمة 'octopus'
.
عند تشغيل البرنامج السابق فسنلاحظ أنَّ القائمة fish_list
تحتوي على نفس العناصر التي كانت موجودة في fish_tuple
لكن مع حذف العنصر 'octopus'
:
['blowfish', 'clownfish', 'catfish']
أي أصبحت القائمة الجديدة تحتوي على بنية tuple الأصلية لكن ما عدا السلسلة النصية التي استثنيناها عبر التعبير الشرطي.
سنُنشِئ مثالًا آخر يستعمل المعاملات الرياضية والأرقام الصحيحة والدالة range()
:
number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)
القائمة التي ستُنشَأ باسم number_list
ستحتوي على مربع جميع القيم الموجودة من المجال 0 إلى 9 لكن إذا كان الرقم قابلًا للقسمة على 2. وستبدو المخرجات كالآتية:
[0, 4, 16, 36, 64]
دعنا نُفصِّل ما الذي يفعله تعبير list comprehension السابق، ودعنا نفكِّر بالذي سيظهر إذا استعملنا التعبير x for x in range(10)
فقط. يجب أن يبدو برنامجنا الصغير كالآتي:
number_list = [x for x in range(10)]
print(number_list)
الناتج:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
لنضف العبارة الشرطية الآن:
number_list = [x for x in range(10) if x % 2 == 0]
print(number_list)
الناتج:
[0, 2, 4, 6, 8]
أدّت العبارة الشرطية if
إلى قبول العناصر القابلة للقسمة على 2 فقط وإضافتها إلى القائمة، مما يؤدي إلى حذف جميع الأرقام الفردية.
يمكننا الآن استخدام معامل رياضي لتربيع قيمة المتغير x
:
number_list = [x ** 2 for x in range(10) if x % 2 == 0]
print(number_list)
أي ستُربَّع قيم القائمة السابقة [0, 2, 4, 6, 8]
وسيُخرَج الناتج الآتي:
[0, 4, 16, 36, 64]
يمكننا أيضًا استعمال ما يشبه عبارات if
المتشعبة في تعابير list comprehension:
number_list = [x for x in range(100) if x % 3 == 0 if x % 5 == 0]
print(number_list)
سيتم التحقق أولًا أنَّ المتغير x
قابل للقسمة على الرقم 3، ثم سنتحقق إن كان المتغير x
قابل للقسمة على الرقم 5، وإذا حقَّق المتغير x
الشرطين السابقين فسيُضاف إلى القائمة، وسيُظهَر في الناتج:
[0, 15, 30, 45, 60, 75, 90]
الخلاصة: يمكن استخدام عبارات if
الشرطية لتحديد ما هي العناصر التي نريد إضافتها إلى القائمة الجديدة.
حلقات التكرار المتشعبة في تعابير List Comprehension
يمكن استعمال حلقات التكرار المتشعبة لإجراء عدِّة عمليات دوران متداخلة في برامجنا.
سننظر في هذا القسم إلى حلقة for
متشعبة وسنحاول تحويلها إلى تعبير list comprehension.
هذه الشيفرة ستُنشِئ قائمةً جديدةً بالدوران على قائمتين وبإجراء عمليات رياضية عليها:
my_list = []
for x in [20, 40, 60]:
for y in [2, 4, 6]:
my_list.append(x * y)
print(my_list)
سنحصل على الناتج الآتي عند تشغيل البرنامج:
[40, 80, 120, 80, 160, 240, 120, 240, 360]
الشيفرة السابقة تضرب العناصر الموجودة في أوّل قائمة بالعناصر الموجودة في ثاني قائمة في كل دورة.
لتحويل ما سبق إلى تعبير list comprehension، وذلك باختصار السطرين الموجودين في الشيفرة السابقة وتحويلهما إلى سطرٍ وحيدٍ، الذي يبدأ بإجراء العملية x*y
، ثم ستلي هذه العملية حلقة for
الخارجية، ثم يليها حلقة for
الداخلية؛ وسنضيف تعبير print()
للتأكد أنَّ ناتج القائمة الجديدة يُطابِق ناتج البرنامج الذي فيه حلقتين متداخلتين:
my_list = [x * y for x in [20, 40, 60] for y in [2, 4, 6]]
print(my_list)
الناتج:
[40, 80, 120, 80, 160, 240, 120, 240, 360]
أدى استعمال تعبير list comprehension في المثال السابق إلى تبسيط حلقتَي for
لتصبحا سطرًا وحيدًا، لكن مع إنشاء نفس القائمة والتي ستُسنَد إلى المتغير my_list
.
توفِّر لنا تعابير list comprehension طريقةً بسيطةً لإنشاء القوائم، مما يسمح لنا باختصار عدِّة أسطر إلى سطرٍ وحيد. لكن من المهم أن تبقي في ذهنك أنَّ سهولة قراءة الشيفرة لها الأولوية دومًا، لذا إذا أصبحتَ تعابير list comprehension طويلةً جدًا ومعقدة، فمن الأفضل حينها تحويلها إلى حلقات تكرار عادية.
الخلاصة
تسمح تعابير list comprehension لنا بتحويل قائمة أو أي نوع من البيانات المتسلسلة إلى سلسلةٍ جديدة، ولها شكلٌ بسيطٌ يُقلِّل عدد الأسطر التي نكتبها.
تتبع تعابير list comprehension شكلًا رياضيًا معيّنًا، لذا قد يجدها المبرمجون أولو الخلفية الرياضية سهلة الفهم.
وصحيحٌ أنَّ تعابير list comprehension تختصر الشيفرةـ لكن من المهم جعل سهولة قراءة الشيفرة من أولوياتنا، وحاول تجنّب الأسطر الطويلة لتسهيل قراءة الشيفرة.
هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3.
ترجمة –وبتصرّف– للمقال Understanding List Comprehensions in Python 3 لصاحبته Lisa Tagliaferri
اقرأ أيضًا
- المقالة التالية: فهم نوع البيانات Tuples في بايثون 3
- المقالة السابقة: كيفية استخدام توابع القوائم في بايثون 3
- المرجع الشامل إلى تعلم لغة بايثون
- كتاب البرمجة بلغة بايثون
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.