تخطَّ إلى المحتوى

دوال lambda و map و filter و sorted في Python

الدرس 22 من 25 · Python

في Python الدوال قيم مثل الأرقام والنصوص: تستطيع أن تحفظها في متغير، وأن ترسلها إلى دالة أخرى. هذه الفكرة تفتح باباً واسعاً: دوال جاهزة مثل sorted و map و filter تطلب منك «دالة صغيرة» تخبرها كيف تعمل. وفي هذا الدرس ستتعلم كتابة هذه الدوال الصغيرة في سطر واحد بالكلمة lambda.

lambda طريقة لكتابة دالة قصيرة بدون اسم وفي سطر واحد. قارن بين الطريقتين:

def double(x):
return x * 2
double_short = lambda x: x * 2
print(double(5))
print(double_short(5))
الناتج
10
10

الدالتان تعملان الشيء نفسه. صيغة lambda هي: المعاملات، ثم نقطتان، ثم تعبير واحد تُعاد قيمته تلقائياً دون كلمة return:

add = lambda a, b: a + b
print(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 مثل المصفاة في المطبخ: يمر منها ما يحقق الشرط، ويبقى الباقي خارجاً.

ربما لاحظت أن 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 في مكانها الطبيعي.

عندك قائمة المنتجات التالية:

products = [
{"name": "قلم", "price": 5},
{"name": "حقيبة", "price": 150},
{"name": "دفتر", "price": 12},
{"name": "آلة حاسبة", "price": 90},
]

اكتب كوداً يطبع: اسم أرخص منتج، ثم أسماء المنتجات مرتبة من الأغلى إلى الأرخص، ثم أسماء المنتجات التي سعرها أقل من 50:

الناتج
قلم
['حقيبة', 'آلة حاسبة', 'دفتر', 'قلم']
['قلم', 'دفتر']
  • كتابة return داخل lambda: lambda x: return x * 2 خطأ في الصياغة. القيمة تُعاد تلقائياً.
  • استدعاء الدالة بدلاً من إرسالها: sorted(words, key=len()) خطأ. المطلوب إرسال الدالة نفسها key=len دون أقواس.
  • نسيان list(): طباعة ناتج map أو filter مباشرة لا تعرض العناصر.
  • lambda طويلة ومعقدة: إذا لم تفهمها من أول نظرة، فحوّلها إلى دالة عادية باسم واضح.

سؤال

ما ناتج (lambda a, b: a * b)(3, 4)؟

سؤال

ما ناتج list(filter(lambda n: n > 2, [1, 2, 3, 4]))؟

  • lambda معاملات: تعبير دالة قصيرة بلا اسم تعيد قيمة التعبير تلقائياً.
  • sorted و max و min تقبل key: دالة تحدد أساس الترتيب أو المقارنة.
  • map(دالة, قائمة) تطبّق الدالة على كل عنصر.
  • filter(دالة, قائمة) تُبقي العناصر التي تحقق الشرط.
  • حوّل ناتج map و filter إلى قائمة بـ list().