دوال lambda و map و filter و sorted في Python
في Python الدوال قيم مثل الأرقام والنصوص: تستطيع أن تحفظها في متغير، وأن ترسلها إلى دالة أخرى. هذه الفكرة تفتح باباً واسعاً: دوال جاهزة مثل sorted و map و filter تطلب منك «دالة صغيرة» تخبرها كيف تعمل. وفي هذا الدرس ستتعلم كتابة هذه الدوال الصغيرة في سطر واحد بالكلمة lambda.
ما هي lambda؟
Section titled “ما هي lambda؟”lambda طريقة لكتابة دالة قصيرة بدون اسم وفي سطر واحد. قارن بين الطريقتين:
def double(x): return x * 2
double_short = lambda x: x * 2
print(double(5))print(double_short(5))1010الدالتان تعملان الشيء نفسه. صيغة lambda هي: المعاملات، ثم نقطتان، ثم تعبير واحد تُعاد قيمته تلقائياً دون كلمة return:
add = lambda a, b: a + bprint(add(3, 4))7تخيّل lambda مثل ورقة ملاحظات لاصقة: تكتب عليها تعليمة قصيرة تستخدمها مرة واحدة ثم ترميها. أما الدالة العادية بـ def فهي مثل صفحة في دفتر: لها عنوان وتعود إليها مرات كثيرة.
في الواقع، لا نحفظ lambda في متغير كما فعلنا هنا إلا للشرح. فائدتها الحقيقية أن نرسلها مباشرة إلى دالة أخرى، كما سترى الآن.
sorted مع key: الترتيب حسب ما تريد
Section titled “sorted مع key: الترتيب حسب ما تريد”الدالة sorted ترتّب أي قائمة وتعيد قائمة جديدة. والمعامل key يستقبل دالة تحدد على أي أساس يتم الترتيب:
words = ["برتقال", "تين", "فراولة", "موز"]
print(sorted(words))print(sorted(words, key=len))print(sorted(words, key=len, reverse=True))['برتقال', 'تين', 'فراولة', 'موز']['تين', 'موز', 'برتقال', 'فراولة']['برتقال', 'فراولة', 'تين', 'موز']في السطر الأول رُتّبت الكلمات أبجدياً. وفي الثاني أرسلنا الدالة الجاهزة len (بدون أقواس!)، فرتّبت sorted الكلمات حسب طولها. و reverse=True تعكس الترتيب.
وتظهر قوة lambda عندما نرتّب قائمة قواميس، وهذا شائع جداً في البرامج الحقيقية:
students = [ {"name": "سارة", "grade": 88}, {"name": "عمر", "grade": 95}, {"name": "ليلى", "grade": 72},]
top = sorted(students, key=lambda s: s["grade"], reverse=True)for s in top: print(s["name"], s["grade"])عمر 95سارة 88ليلى 72الدالة lambda s: s["grade"] تأخذ طالباً وتعيد درجته، فتعرف sorted أن الدرجة هي أساس الترتيب. والمعامل key نفسه يعمل مع max و min:
best = max(students, key=lambda s: s["grade"])print(best["name"])عمرmap: طبّق دالة على كل عنصر
Section titled “map: طبّق دالة على كل عنصر”الدالة map تأخذ دالة وقائمة، وتطبّق الدالة على كل عنصر:
prices = [10, 25, 40]
with_shipping = list(map(lambda p: p + 5, prices))print(with_shipping)
numbers = list(map(int, ["1", "2", "3"]))print(numbers)[15, 30, 45][1, 2, 3]في المثال الثاني أرسلنا الدالة الجاهزة int نفسها، فحوّلت map كل نص إلى رقم. وهذه حيلة مفيدة جداً عند قراءة أرقام من المستخدم أو من ملف.
filter: اختر العناصر التي تحقق شرطاً
Section titled “filter: اختر العناصر التي تحقق شرطاً”الدالة filter تأخذ دالة تعيد True أو False، وتُبقي فقط العناصر التي أعادت الدالة معها True:
ages = [12, 17, 21, 15, 30]
adults = list(filter(lambda age: age >= 18, ages))print(adults)[21, 30]تخيّل filter مثل المصفاة في المطبخ: يمر منها ما يحقق الشرط، ويبقى الباقي خارجاً.
lambda أم List Comprehension؟
Section titled “lambda أم List Comprehension؟”ربما لاحظت أن map و filter تفعلان ما تفعله الصيغة المختصرة من الدرس السابق. هذا صحيح:
print(list(map(lambda p: p + 5, prices)))print([p + 5 for p in prices])
print(list(filter(lambda age: age >= 18, ages)))print([age for age in ages if age >= 18])[15, 30, 45][15, 30, 45][21, 30][21, 30]أغلب مبرمجي Python يفضّلون الصيغة المختصرة لأنها أسهل في القراءة. لكن ستقابل map و filter كثيراً في كود غيرك، ويجب أن تفهمهما. أما مع sorted و max و min فلا بديل عن key، وهناك تكون lambda في مكانها الطبيعي.
جرّب بنفسك
Section titled “جرّب بنفسك”عندك قائمة المنتجات التالية:
products = [ {"name": "قلم", "price": 5}, {"name": "حقيبة", "price": 150}, {"name": "دفتر", "price": 12}, {"name": "آلة حاسبة", "price": 90},]اكتب كوداً يطبع: اسم أرخص منتج، ثم أسماء المنتجات مرتبة من الأغلى إلى الأرخص، ثم أسماء المنتجات التي سعرها أقل من 50:
قلم['حقيبة', 'آلة حاسبة', 'دفتر', 'قلم']['قلم', 'دفتر']أخطاء شائعة
Section titled “أخطاء شائعة”- كتابة
returnداخل lambda:lambda x: return x * 2خطأ في الصياغة. القيمة تُعاد تلقائياً. - استدعاء الدالة بدلاً من إرسالها:
sorted(words, key=len())خطأ. المطلوب إرسال الدالة نفسهاkey=lenدون أقواس. - نسيان
list(): طباعة ناتجmapأوfilterمباشرة لا تعرض العناصر. - lambda طويلة ومعقدة: إذا لم تفهمها من أول نظرة، فحوّلها إلى دالة عادية باسم واضح.
اختبر نفسك
Section titled “اختبر نفسك”سؤال
ما ناتج (lambda a, b: a * b)(3, 4)؟
الدالة تضرب المعاملين، و 3 × 4 = 12.
سؤال
ما ناتج list(filter(lambda n: n > 2, [1, 2, 3, 4]))؟
filter تُبقي العناصر التي تحقق الشرط فقط، وهي الأكبر من 2.
الخلاصة
Section titled “الخلاصة”lambda معاملات: تعبيردالة قصيرة بلا اسم تعيد قيمة التعبير تلقائياً.sortedوmaxوminتقبلkey: دالة تحدد أساس الترتيب أو المقارنة.map(دالة, قائمة)تطبّق الدالة على كل عنصر.filter(دالة, قائمة)تُبقي العناصر التي تحقق الشرط.- حوّل ناتج
mapوfilterإلى قائمة بـlist().