Python وظائف لامدا مع الأمثلة

⚡ ملخص ذكي

وظائف لامدا في Python هي دوال مجهولة صغيرة يتم تعريفها باستخدام الكلمة المفتاحية lambda بدلاً من def. وهي تحتوي على تعبير واحد، وتأخذ أي عدد من الوسائط، وغالبًا ما يتم تمريرها مباشرة إلى الدوال المضمنة مثل map() و filter() و sorted().

  • 🔑 الكلمة المفتاحية لامدا: تُكتب دالة لامدا على النحو التالي: lambda arguments: expression، بدون تعريف، بدون اسم، وبدون عبارة إرجاع صريحة.
  • 🧮 تعبير واحد: يحتوي النص على تعبير واحد فقط يتم إرجاع قيمته تلقائيًا، لذا فإن العبارات والأسطر المتعددة غير مسموح بها.
  • 🔗 خاصية الاقتران المدمجة: يتم تمرير الدوال اللامدا عادةً إلى map() و filter() و reduce() و sorted() لتحويل أو تحديد العناصر في تسلسل.
  • IIFE: يمكن تعريف دالة لامدا واستدعاؤها على الفور باستخدام النمط (lambda x: x + x)(2)، مما يؤدي إلى إرجاع نتيجة في وقت واحد.
  • 🇧🇷 ضد: تحتاج الدوال العادية إلى اسم ويمكنها استيعاب العديد من التعليمات، بينما تستبدل الدوال اللامدا هذه القوة بصيغة مختصرة من سطر واحد.
  • 🤖 مساعدة الذكاء الاصطناعي: تقوم المساعدات المدعومة بالذكاء الاصطناعي مثل GitHub Copilot بإنشاء تعبيرات لامدا لمفاتيح الخريطة والتصفية والفرز من خلال مطالبة قصيرة.

Python وظائف لامدا

ما هي وظيفة لامدا في Python?

A وظيفة لامدا في Python البرمجة هي وظيفة مجهولة أو وظيفة ليس لها اسم. إنها وظيفة صغيرة ومقيدة لا تحتوي على أكثر من سطر واحد. تمامًا مثل الدالة العادية، يمكن أن تحتوي دالة Lambda على وسائط متعددة بتعبير واحد.

In Python، يتم استخدام تعبيرات لامدا (أو نماذج لامدا) لإنشاء وظائف مجهولة. للقيام بذلك، سوف تستخدم لامدا الكلمة الرئيسية (تمامًا كما تستخدم صفر لتحديد الوظائف العادية). كل وظيفة مجهولة تحددها فيها Python سيكون لها 3 أجزاء أساسية:

  • الكلمة الأساسية لامدا.
  • المعلمات (أو المتغيرات المرتبطة)، و
  • الجسم الوظيفي.

يمكن أن تحتوي دالة لامدا على أي عدد من المعلمات، ولكن يمكن أن يحتوي نص الدالة فقط على صورة واحدة؟ تعبير. علاوة على ذلك، تتم كتابة لامدا في سطر واحد من التعليمات البرمجية ويمكن أيضًا استدعاؤها على الفور. سترى كل هذا عمليًا في الأمثلة القادمة.

بناء الجملة والأمثلة

بناء الجملة الرسمي لكتابة دالة لامدا هو كما يلي:

lambda p1, p2: expression

هنا، p1 وp2 هما المعلمتان اللتان تم تمريرهما إلى دالة lambda. يمكنك إضافة العديد أو القليل من المعلمات حسب حاجتك.

لكن لاحظ أننا لا نستخدم الأقواس حول المعاملات كما نفعل مع الدوال العادية. الجزء الأخير (التعبير) هو أي تعبير صالح Python تعبير يعمل على المعاملات التي تقدمها للدالة.

مثال 1

الآن بعد أن تعرفت على لامدا، دعنا نجربها بمثال. لذلك، افتح الخاص بك IDLE واكتب ما يلي:

adder = lambda x, y: x + y
print (adder (1, 2))

Code تفسير

هنا، نحدد متغيرًا سيحتفظ بالنتيجة التي يتم إرجاعها بواسطة دالة لامدا.

1. الكلمة الأساسية lambda المستخدمة لتحديد وظيفة مجهولة.

2. x وy هما المعلمتان اللتان نمررهما إلى دالة lambda.

3. هذا هو نص الدالة، الذي يجمع المعلمتين اللتين مررناهما. لاحظ أنه تعبير واحد. لا يمكنك كتابة عبارات متعددة في نص دالة لامدا.

4. نحن نسمي الدالة ونطبع القيمة التي تم إرجاعها.

مثال 2

كان هذا مثالًا أساسيًا لفهم مبادئ وبنية تعبير لامدا. لنحاول الآن طباعة تعبير لامدا ونرى النتيجة. افتح ملفك مرة أخرى. IDLE واكتب ما يلي:

#What a lambda returns
string='some kind of a useless lambda'
print(lambda string : print(string))

الآن احفظ ملفك واضغط على F5 لتشغيل البرنامج. هذا هو الناتج الذي يجب أن تحصل عليه.

الإخراج:

<function <lambda> at 0x00000185C3BF81E0>

ما الذي يحدث هنا؟ دعونا نلقي نظرة على الكود لفهم الأمر بشكل أعمق.

Code التفسير:

1. هنا، نُعرّف أ سلسلة التي ستمررها كمعامل إلى دالة لامدا.

2. نقوم بتعريف دالة لامدا تستدعي عبارة طباعة وتطبع النتيجة.

لكن لماذا لا يطبع البرنامج السلسلة التي نمررها؟ السبب هو أن دالة لامدا نفسها تُرجع كائن دالة. في هذا المثال، لا يتم تعريف دالة لامدا. تسمى بواسطة وظيفة الطباعة، ولكن ببساطة عودة كائن الدالة وموقع الذاكرة الذي يُخزَّن فيه. هذا ما يُطبع على وحدة التحكم.

مثال 3

ومع ذلك، إذا قمت بكتابة برنامج مثل هذا:

#What a lambda returns #2
x="some kind of a useless lambda"
(lambda x : print(x))(x)

قم بتشغيله بالضغط على F5، وسترى مخرجات كهذه.

الإخراج:

some kind of a useless lambda

الآن، يتم استدعاء دالة لامدا، ويتم طباعة السلسلة التي نمررها على الشاشة. ولكن ما هذا التركيب الغريب، ولماذا تعريف دالة لامدا محاط بأقواس؟ دعونا نفهم ذلك الآن.

Code التفسير:

1. إليك نفس السلسلة التي حددناها في المثال السابق.

٢. في هذا الجزء، نُعرّف دالة لامدا ونستدعيها فورًا بتمرير السلسلة النصية كوسيط. يُطلق على هذا اسم دالة مُنفذة فورًا (IIFE)، وستتعرف على المزيد عنها في الأقسام القادمة من هذا الدرس.

مثال 4

دعونا نلقي نظرة على مثال أخير لفهم كيفية تنفيذ الدوال اللامدا والدوال العادية. لذا، افتح... IDLE وفي ملف جديد، اكتب ما يلي:

#A REGULAR FUNCTION
def guru( funct, *args ):
funct( *args )
def printer_one( arg ):
return print (arg)
def printer_two( arg ):
print(arg)
#CALL A REGULAR FUNCTION 
guru( printer_one, 'printer 1 REGULAR CALL' )
guru( printer_two, 'printer 2 REGULAR CALL \n' )
#CALL A REGULAR FUNCTION THRU A LAMBDA
guru(lambda: printer_one('printer 1 LAMBDA CALL'))
guru(lambda: printer_two('printer 2 LAMBDA CALL'))

الآن، احفظ الملف واضغط على F5 لتشغيل البرنامج. إذا لم ترتكب أي أخطاء، فستكون النتيجة مشابهة لما يلي.

الإخراج:

printer 1 REGULAR CALL

printer 2 REGULAR CALL

printer 1 LAMBDA CALL

printer 2 LAMBDA CALL

Code التفسير:

1. دالة تسمى guru تأخذ دالة أخرى كمعامل أول وأي وسائط أخرى تليها.

2. الدالة printer_one هي دالة بسيطة تقوم بطباعة المعلمة التي تم تمريرها إليها وإعادتها.

3. الطابعة الثانية تشبه الطابعة الأولى ولكن بدون عبارة الإرجاع.

4. في هذا الجزء، نقوم باستدعاء دالة المعلم وتمرير دوال الطباعة وسلسلة نصية كمعاملات.

5. هذه هي الصيغة لتحقيق الخطوة الرابعة (أي استدعاء دالة المعلم) ولكن باستخدام تعبيرات لامدا.

في القسم التالي، سوف تتعلم كيفية استخدام وظائف لامدا مع خريطة(), خفض()و منقي() in Python.

باستخدام لامدا مع Python المدمج

توفر وظائف Lambda طريقة أنيقة وقوية لإجراء العمليات باستخدام الأساليب المضمنة في Python. هذا ممكن لأنه يمكن استدعاء lambdas على الفور وتمريرها كوسيطة لهذه الوظائف.

إيف في Python لامدا

إيف لتقف على استدعاء تنفيذ الوظيفة على الفور. هذا يعني أن دالة لامدا قابلة للاستدعاء بمجرد تعريفها. دعونا نفهم هذا بمثال؛ شغّل برنامجك IDLE واكتب ما يلي:

 (lambda x: x + x)(2)

فيما يلي شرح الإخراج والكود:

تتيح لك إمكانية استدعاء lambdas على الفور استخدامها داخل وظائف مثل Map() وreduce(). إنه مفيد لأنك قد لا ترغب في استخدام هذه الوظائف مرة أخرى.

لامدا في الفلتر ()

يتم استخدام وظيفة التصفية لتحديد بعض العناصر المحددة من سلسلة من العناصر. يمكن أن يكون التسلسل أي مكرر مثل القوائم، والمجموعات، والصفوف، وما إلى ذلك.

يتم اختيار العناصر بناءً على بعض القيود المحددة مسبقًا. ويتطلب ذلك معيارين:

  • دالة تحدد قيد التصفية
  • تسلسل (أي مكرر مثل القوائم، والصفوف، وما إلى ذلك)

على سبيل المثال،

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = filter (lambda x: x > 4, sequences) 
print(list(filtered_result))

هنا هو الإخراج:

[10, 8, 7, 5, 11]

Code التفسير:

1. في العبارة الأولى، نقوم بتعريف قائمة تسمى التسلسلات والتي تحتوي على بعض الأرقام.

2. هنا، نعلن عن متغير يسمى filtered_result، والذي سيخزن القيم التي تم تصفيتها والتي يتم إرجاعها بواسطة الدالة filter().

3. دالة لامدا التي تعمل على كل عنصر في القائمة وترجع صحيحًا إذا كان أكبر من 4.

4. اطبع النتيجة التي تم إرجاعها بواسطة وظيفة التصفية.

لامدا في الخريطة ()

تُستخدم دالة map لتطبيق عملية معينة على كل عنصر في سلسلة. ومثل دالة filter()، فإنها تأخذ أيضًا وسيطين:

  1. دالة تحدد العملية المراد تنفيذها على العناصر
  2. تسلسل واحد أو أكثر

على سبيل المثال، إليك برنامجًا يقوم بطباعة مربعات الأرقام الموجودة في قائمة معينة:

sequences = [10,2,8,7,5,4,3,11,0, 1]
filtered_result = map (lambda x: x*x, sequences) 
print(list(filtered_result))

الإخراج:

 [100, 4, 64, 49, 25, 16, 9, 121, 0, 1]

Code التفسير:

1. هنا، نُعرّف قائمة تسمى المتتاليات والتي تحتوي على بعض الأرقام.

2. نقوم بتعريف متغير يسمى filtered_result والذي سيخزن القيم التي تم تعيينها.

3. دالة لامدا تعمل على كل عنصر من عناصر القائمة وتعيد مربع ذلك الرقم.

4. اطبع النتيجة التي تم إرجاعها بواسطة دالة الخريطة.

لامدا في تقليل ()

تُستخدم دالة الاختزال، مثل map()، لتطبيق عملية على كل عنصر في تسلسل. ومع ذلك، فهي تختلف عن map في طريقة عملها. وهذه هي الخطوات التي تتبعها دالة الاختزال() لحساب الناتج:

الخطوة 1) قم بإجراء العملية المحددة على أول عنصرين من التسلسل.

الخطوة 2) احفظ هذه النتيجة.

الخطوة 3) قم بإجراء العملية باستخدام النتيجة المحفوظة والعنصر التالي في التسلسل.

الخطوة 4) كرر حتى لا يتبقى المزيد من العناصر.

يستغرق أيضًا معلمتين:

  1. وظيفة تحدد العملية التي يجب تنفيذها
  2. تسلسل (أي مكرر مثل القوائم، والصفوف، وما إلى ذلك)

على سبيل المثال، إليك برنامج يُرجع حاصل ضرب جميع العناصر في القائمة:

from functools import reduce
sequences = [1,2,3,4,5]
product = reduce (lambda x, y: x*y, sequences)
print(product)

هنا هو الإخراج:

120

Code التفسير:

1. استورد دالة reduce من وحدة functools.

2. هنا، نُعرّف قائمة تسمى المتتاليات والتي تحتوي على بعض الأرقام.

3. نقوم بتعريف متغير يسمى المنتج والذي سيخزن القيمة المخفضة.

4. دالة لامدا تُنفذ على كل عنصر من عناصر القائمة. ستُعيد هذه الدالة ناتج ضرب ذلك العدد وفقًا للنتيجة السابقة.

5. اطبع النتيجة التي تم إرجاعها بواسطة دالة الاختزال.

لماذا (ولماذا لا) استخدام وظائف لامدا؟

كما سترون في القسم التالي، يتم التعامل مع وظائف lambda مثل الوظائف العادية على مستوى المترجم الفوري. بطريقة ما، يمكنك القول أن lambdas توفر بناء جملة مدمجًا لوظائف الكتابة التي تُرجع تعبيرًا واحدًا.

مع ذلك، ينبغي عليك معرفة متى يكون استخدام تعابير لامدا فكرة جيدة ومتى يجب تجنبها. في هذا القسم، ستتعرف على بعض مبادئ التصميم المستخدمة بواسطة Python المطورون عند كتابة الدوال اللامدا.

يُعد استخدام الدوال اللامدا في البرمجة الوظيفية أحد أكثر حالات الاستخدام شيوعًا، حيث Python يدعم نموذجًا (أو أسلوبًا) للبرمجة يُعرف بالبرمجة الوظيفية.

تتيح لك هذه الخاصية تمرير دالة كمعامل لدالة أخرى (على سبيل المثال، في دوال مثل map و filter وغيرها). في مثل هذه الحالات، يوفر استخدام الدوال المجهولة طريقة أنيقة لإنشاء دالة تُستخدم لمرة واحدة وتمريرها كمعامل.

متى يجب ألا تتناوللامدا؟

لا ينبغي لك أبدًا كتابة وظائف لامدا معقدة في بيئة إنتاجية. سيكون من الصعب جدًا على المبرمجين الذين يقومون بصيانة الكود الخاص بك فك تشفيره. إذا وجدت نفسك تقوم بإنشاء تعبيرات معقدة من سطر واحد، فسيكون من الأفضل بكثير تحديد وظيفة مناسبة. كأفضل ممارسة، عليك أن تتذكر أن الكود البسيط أفضل دائمًا من الكود المعقد.

لامداس مقابل الوظائف العادية

كما ذُكر سابقًا، فإنّ الدوال اللامدا هي دوالٌ لا تحمل مُعرّفًا. بعبارةٍ أبسط، هي دوالٌ بلا أسماء (لذا فهي مجهولة). إليك جدولٌ يُوضّح الفرق بين الدوال اللامدا والدوال العادية. Python.

لامداس وظائف منتظمة
بناء الجملة:

lambda x : x + x
بناء الجملة:

def (x) :
return x + x 
يمكن أن يكون لوظائف Lambda تعبير واحد فقط في أجسامها. يمكن أن تحتوي الوظائف العادية على تعبيرات وعبارات متعددة في أجسامها.
لا تحمل الدوال المجهولة اسماً مرتبطاً بها. ولهذا السبب تُعرف أيضاً بالدوال المجهولة. يجب أن يكون للوظائف العادية اسم وتوقيع.
لا تحتوي Lambdas على بيان إرجاع لأنه يتم إرجاع الجسم تلقائيًا. يجب أن تتضمن الدوال التي تحتاج إلى إرجاع قيمة عبارة إرجاع.

شرح الاختلافات

الفرق الأساسي بين دالة لامدا والدالة العادية هو أن دالة لامدا تقوم بتقييم تعبير واحد فقط وتنتج كائن دالة. وبالتالي يمكننا تسمية نتيجة دالة لامدا واستخدامها في برنامجنا كما فعلنا في المثال السابق.

ستبدو الدالة العادية للمثال أعلاه كما يلي:

def adder (x, y):
return x + y 
print (adder (1, 2))

وهنا علينا أن نحدد أ الاسم للوظيفة التي عائدات النتيجة عندما نحن دعوة لا تحتوي دالة لامدا على عبارة إرجاع لأنها تحتوي على تعبير واحد فقط يتم إرجاعه افتراضيًا. ولا تحتاج حتى إلى تعيين قيمة لدالة لامدا، إذ يمكن استدعاؤها مباشرةً (انظر القسم السابق). وكما سترى، تصبح دوال لامدا قوية للغاية عند استخدامها مع Pythonوظائف المدمج في.

ومع ذلك، ربما لا تزال تتساءل عن مدى اختلاف lambdas عن دالة تُرجع تعبيرًا واحدًا (مثل التعبير أعلاه). على مستوى المترجم، لا يوجد فرق كبير. قد يبدو الأمر مفاجئًا، لكن أي دالة لامدا تحددها Python يتم التعامل معها كوظيفة عادية من قبل المترجم.

على مستوى رمز البايت، يتم التعامل مع التعريفين بنفس الطريقة بواسطة Python المترجم. الآن، لا يمكنك تسمية دالة لامدا لأنه محجوز من قبل Python، ولكن أي اسم دالة آخر سينتج نفس رمز البايت.

الأسئلة الشائعة

نعم. يمكن للدالة اللامدا استخدام تعبير شرطي مثل: `lambda x: 'even' if x % 2 == 0 else 'odd'`. لا يمكنها احتواء جملة شرطية كاملة، لأن جسم الدالة اللامدا يجب أن يكون تعبيرًا واحدًا وليس مجموعة من الجمل.

عمومًا لا. توصي PEP 8 باستخدام def عندما تحتاج الدالة إلى اسم، لأن ربط تعبير لامدا بمتغير يعطيه اسمًا ولكنه يفقد الوضوح. tracيُفضل تمرير الدوال اللامدا مباشرةً إلى دوال مثل sorted() و map() و filter().

لا. على مستوى رمز البايت Python يعامل هذا الأسلوب تعبير لامدا والتعريف المكافئ له بنفس الطريقة، لذا لا توجد ميزة في السرعة. يوفر تعبير لامدا سطرًا واحدًا من التعليمات البرمجية فقط؛ فهو لا يُنفذ أسرع من دالة مُسماة تقوم بنفس العمل.

نعم. يمكن للدالة اللامدا قراءة المتغيرات من النطاق المحيط بها، مما يُشكل إغلاقًا. داخل حلقة تكرار، انتبه: الدالة اللامدا تلتقط المتغير نفسه، وليس قيمته الحالية، لذا استخدم وسيطًا افتراضيًا مثل lambda x, n=n: x + n لتثبيته.

مرر دالة لامدا كمعامل رئيسي للدالة sorted() أو list.sort(). على سبيل المثال، sorted(users, key=lambda u: u['age']) ترتب العناصر حسب العمر. تخبر دالة لامدا المستخدم بالترتيب. Python تحديد القيمة التي يجب مقارنتها لكل عنصر، مما يوفر فرزًا مخصصًا موجزًا ​​دون الحاجة إلى دالة مسماة منفصلة.

ليس بشكل مباشر، لأن دالة لامدا المجهولة ليس لها اسم يمكن الرجوع إليه. يمكنك تجاوز هذه المشكلة بتعيين دالة لامدا إلى متغير واستدعاء ذلك الاسم، لكن استخدام دالة تعريف عادية (def) هو الخيار الأوضح والأكثر توصية للتكرار.

تُتيح دوال لامدا إجراء تحويلات سريعة ومباشرة في أكواد الذكاء الاصطناعي والتعلم الآلي. يستخدمها علماء البيانات مع دوال pandas .apply() و map() و filter() لتنظيف البيانات أو إعادة تشكيلها، كما أنها تُعدّ دوالًا أساسية لفرز الميزات، وتحافظ علىping معالجة مسبقة مضغوطة داخل مسارات تدريب أكبر.

يقترح GitHub Copilot تعابير لامدا كاملة من تعليق قصير أو من الكود المحيط، بما في ذلك المعاملات والتعبيرات الصحيحة لاستدعاءات map() و filter() و sorted(). كما يمكنه اقتراح تحويل تعبير لامدا مطوّل إلى دالة مُسمّاة أكثر وضوحًا عندما تكون سهولة القراءة مهمة.

تلخيص هذه التدوينة بـ: