الدوال والإغلاقات وLambda
عرّف دوال مساعدة قابلة لإعادة الاستخدام، واستخدم الوسائط الافتراضية، وطبّق تعبيرات lambda على الفرز والأنماط الوظيفية في مسائل المقابلات
الدوال والإغلاقات وLambda درس مجاني في Coding Interview Prep على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Coding Interview Prep، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.
تعريف الدوال في Python
الدوال في Python هي عناصر من الدرجة الأولى: يمكنكم تمريرها وإرجاعها وتخزينها. وتجعل الدوال المساعدة ذات الأسماء الواضحة شيفرة المقابلات سهلة القراءة. عالجوا الحالات الحدية أولًا.
def is_palindrome(s: str) -> bool:
'''Return True if s reads the same forwards and backwards.'''
s = s.lower()
return s == s[::-1]
print(is_palindrome('Racecar')) # True
print(is_palindrome('hello')) # False
# Functions as values
checks = [is_palindrome]
print(checks[0]('level')) # Trueالمعاملات الافتراضية والمسماة
تتيح القيم الافتراضية للمتصلين تخطي بعض المعاملات. لكن لا تستخدموا قيمة افتراضية قابلة للتغيير أبدًا مثل list؛ إذ يتشاركها جميع المتصلين. الحل هو استخدام None كقيمة افتراضية وإنشاء القائمة داخل الدالة. راجعوا الكود.
# WRONG: shared mutable default
def bad_append(val, lst=[]):
lst.append(val)
return lst
print(bad_append(1)) # [1]
print(bad_append(2)) # [1, 2] surprise!
# CORRECT: use None sentinel
def good_append(val, lst=None):
if lst is None:
lst = []
lst.append(val)
return lst
print(good_append(1)) # [1]
print(good_append(2)) # [2]*args و**kwargs
تجمع *args المعاملات الموضعية الإضافية في tuple، بينما تجمع **kwargs المعاملات الإضافية المسماة في dict. كما تفك * تسلسلًا عند استدعاء دالة.
def total(*args):
return sum(args)
print(total(1, 2, 3)) # 6
print(total(1, 2, 3, 4)) # 10
# Unpack a list as positional args
point = [3, 7]
print(max(*point)) # 7
# **kwargs
def greet(**kwargs):
name = kwargs.get('name', 'World')
return f'Hello, {name}!'
print(greet(name='Alice')) # Hello, Alice!تعبيرات Lambda
إنّ lambda دالة صغيرة في سطر واحد: lambda params: expression. وهي مثالية كـ key سريع في sorted أو max. أما ما هو أكبر من ذلك، فتكون دالة def ذات اسم أوضح قراءةً.
# Lambda as sort key
pairs = [(1, 3), (2, 1), (3, 2)]
sorted_by_second = sorted(pairs, key=lambda p: p[1])
print(sorted_by_second) # [(2,1),(3,2),(1,3)]
# Lambda with map
double = list(map(lambda n: n * 2, [1, 2, 3]))
print(double) # [2, 4, 6]
# Named function is clearer for complex logic
def sort_key(p):
return (p[1], -p[0]) # secondary sort
print(sorted(pairs, key=sort_key))الدوال المتداخلة وClosures
إنّ closure دالة تتذكر المتغيرات من الدالة المحيطة بها. عرّفوا دالة مساعدة داخل دالة أخرى، وستتمكن من استخدام متغيرات الدالة الخارجية، وهو أمر مفيد في DFS.
def make_counter(start=0):
count = [start] # list to allow mutation
def increment():
count[0] += 1
return count[0]
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
# Alternative: nonlocal keyword
def make_counter2():
count = 0
def increment():
nonlocal count
count += 1
return count
return incrementClosures في DFS العودي
من الأنماط الشائعة تعريف دالة مساعدة باسم dfs داخل الدالة الرئيسية، والسماح لها بجمع النتائج في متغير خارجي. وتكون الدالة الداخلية closure على ذلك النطاق.
def max_depth(root):
'''Closure pattern for tree DFS.'''
max_d = [0] # mutable container for closure
def dfs(node, depth):
if node is None:
return
max_d[0] = max(max_d[0], depth)
dfs(node.left, depth + 1)
dfs(node.right, depth + 1)
dfs(root, 1)
return max_d[0]
# This pattern avoids a class or global state.functools.lru_cache للحفظ المؤقت
يتذكر lru_cache (أو @cache في الإصدار 3.9 فما بعده) نتائج الدالة وفقًا لمعاملاتها، فيحوّل Fibonacci الساذج من O(2^n) إلى O(n). ويجب أن تكون المعاملات قابلة للتجزئة، لذا استخدموا Tuples.
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
print(fib(40)) # 102334155 fast!
print(fib.cache_info()) # hits, misses, sizeالدوال من الرتبة العليا
تأخذ الدالة من الرتبة العليا دالةً أو تُرجعها. وتندرج sorted وmap وfilter جميعًا ضمن ذلك. وتتيح لكم كتابة دوالكم الخاصة تجريد الأنماط المتكررة. يوضّح الكود التركيب.
def apply_twice(f, x):
return f(f(x))
print(apply_twice(lambda n: n * 2, 3)) # 12 (3*2*2)
# Composing transformations
def compose(f, g):
return lambda x: f(g(x))
double = lambda n: n * 2
add_one = lambda n: n + 1
double_then_add = compose(add_one, double)
print(double_then_add(5)) # 11 ((5*2)+1)الاستدعاء الذاتي مع الدوال المساعدة
تجمع حلول كثيرة بين دالة خارجية تتولى الإعداد والحالات الحدية، ودالة مساعدة داخلية تنفّذ الاستدعاء الذاتي. واجهة عامة نظيفة ومنطق معزول. راجعوا الكود.
def flatten(nested):
'''Flatten an arbitrarily nested list.'''
result = []
def _flatten(lst):
for item in lst:
if isinstance(item, list):
_flatten(item)
else:
result.append(item)
_flatten(nested)
return result
print(flatten([1, [2, [3, 4], 5], 6]))
# [1, 2, 3, 4, 5, 6]الدوال الجزئية باستخدام functools.partial
تملأ functools.partial بعض المعاملات مسبقًا وتُرجع callable جديدة. وهي مفيدة عندما تتطلب واجهة برمجية دالة بلا معاملات، بينما تحتاجون إلى تثبيت قيمة معامل واحد.
from functools import partial
def power(base, exp):
return base ** exp
square = partial(power, exp=2)
cube = partial(power, exp=3)
print(square(5)) # 25
print(cube(3)) # 27
print(list(map(square, [1, 2, 3, 4]))) # [1, 4, 9, 16]Lambda للمقارنات المخصصة
أزالت Python 3 المقارنات ذات المعاملين، لكن cmp_to_key يعيدها للترتيبات المعقدة، مثل ترتيب الأعداد بحيث يكون ناتج وصلها أكبر ما يمكن. راجعوا الكود.
from functools import cmp_to_key
def largest_number(nums):
def compare(a, b):
if a + b > b + a: return -1
if a + b < b + a: return 1
return 0
strs = list(map(str, nums))
strs.sort(key=cmp_to_key(compare))
result = ''.join(strs)
return '0' if result[0] == '0' else result
print(largest_number([3, 30, 34, 5, 9])) # '9534330'تحقق سريع
تحقق سريع — حان الوقت لإظهار ما تعلمتموه عن الدوال وclosures وlambdas. خذوا نفسًا وابدؤوا. 🚀
مراجعة الدرس
مراجعة: لا تستخدموا القيم الافتراضية القابلة للتغيير أبدًا (استخدموا None)، وتتيح closures للدوال المساعدة الداخلية الوصول إلى المتغيرات الخارجية في DFS، بينما تدعم أدوات functools مثل lru_cache الحلول السريعة.
الأسئلة الشائعة
هل درس «الدوال والإغلاقات وLambda» مجاني؟
نعم — نص درس «الدوال والإغلاقات وLambda» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Coding Interview Prep، انتقل إلى CoddyKit PRO. تتضمن دورة Coding Interview Prep 4 دروس في المجموع.
ماذا ستتعلم في «الدوال والإغلاقات وLambda»؟
عرّف دوال مساعدة قابلة لإعادة الاستخدام، واستخدم الوسائط الافتراضية، وطبّق تعبيرات lambda على الفرز والأنماط الوظيفية في مسائل المقابلات تتمرن على Coding Interview Prep مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Coding Interview Prep؟
لا تُشترط خبرة سابقة. Coding Interview Prep على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «الدوال والإغلاقات وLambda»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Coding Interview Prep هذا؟
نعم. كل درس في Coding Interview Prep يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- القوائم والصفوف والتقطيع
- القواميس والمجموعات في Python
- الاختصارات والدوال المضمّنة
- الدوال والإغلاقات وLambda