مستوى المقال: مبتدئ. لو لسه بادئ في البرمجة وسمعت كلمة Memoization وحسّيتها معقّدة، المقال ده ليك. هتخرج منه فاهم الفكرة وقادر تطبّقها في سطر واحد.
الـ Memoization: خلّي دالتك تفتكر الإجابة بدل ما تحسبها من الأول
نفس الدالة ممكن تشتغل في جزء من الثانية، أو تتعلّق ثواني طويلة، والفرق سطر واحد بس. الحيلة اسمها Memoization: بدل ما الدالة تعيد حساب نفس النتيجة كل مرة، بتحفظها وترجّعها جاهزة.
مثال بسيط الأول
تخيّل طالب بيحل مسألة رياضة، ولقى إنه محتاج ناتج 7×8 خمس مرات في نفس الورقة. المرة الأولى حسبها وكتب "56" على الهامش. باقي المرات بصّ على الهامش وخلّص في ثانية بدل ما يعيد الضرب.
ده بالظبط اللي بيعمله الـ Memoization: أول مرة الدالة تحسب، تكتب الناتج في جنب (الذاكرة)، وأي مرة تانية تقرأه بدل ما تحسبه من الأول.
يعني إيه علميًا
الـ Memoization أسلوب تحسين (optimization) بتخزّن فيه نتيجة استدعاء الدالة مربوطة بمدخلاتها. لو الدالة اتنادت بنفس المدخل تاني، بترجّع النتيجة المخزّنة من غير إعادة حساب. الشرط الأساسي: الدالة لازم تكون "نقية" (pure) — نفس المدخل يدّي نفس المخرج دايمًا، من غير آثار جانبية.
المشكلة في مثال حقيقي: متتالية فيبوناتشي
خد دالة فيبوناتشي اللي بتنادي نفسها. من غير Memoization، حساب fib(40) بيكرّر نفس القيم ملايين المرات. عدد الاستدعاءات بينمو أُسّيًا وبيوصل 331,160,281 استدعاء — أكتر من 331 مليون. مع Memoization بينزل لـ 41 عملية بس، لأن كل قيمة بتتحسب مرة واحدة وتتخزّن.
الكود: قبل وبعد
import time
# من غير Memoization — بطيء
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
# مع Memoization — سريع
cache = {}
def fib_memo(n):
if n < 2:
return n
if n in cache:
return cache[n]
cache[n] = fib_memo(n - 1) + fib_memo(n - 2)
return cache[n]
t = time.perf_counter()
fib(35)
print("fib بدون:", round(time.perf_counter() - t, 3), "ثانية")
t = time.perf_counter()
fib_memo(35)
print("fib memo:", round((time.perf_counter() - t) * 1000, 4), "مللي ثانية")
على جهاز عادي، fib(35) من غير Memoization بياخد حوالي 1.6 ثانية. النسخة اللي فيها Memoization بتخلّص في حوالي 0.02 مللي ثانية — يعني تحسّن أكتر من 10 آلاف مرة على نفس الجهاز. في بايثون تقدر تكسب نفس النتيجة بسطر واحد فوق الدالة باستخدام functools.lru_cache: