الدالة functools.lru_cache()‎ في بايثون

من موسوعة حسوب
< Python‏ | functools
مراجعة 16:11، 20 يونيو 2018 بواسطة عبد-الهادي-الديوري (نقاش | مساهمات) (←‏ملاحظات)
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

الدّالة functools.lru_cache()‎ مُزخرفٌ يُحيط دالّة بكائن قابل للاستدعاء مُتذكّر (memoizing callable).

الكائن المُتذكِّر يحتفظ بعددٍ من آخر الاستدعاءات حسب قيمة المُعامل maxsize. ويُمكن أن تختصر الوقت إن كانت دالّة تأخذ الكثير من الوقت تُستدعَى بنفس المُعاملات عدّة مرّات.

ولأنّ النّتائج تُخبّأ (cache) في قاموس، فيجب على المُعاملات المُمرّرة للدّالة المُزخرَفة أن تكون قابلة للتّجزئة (hashable).

البنية العامة

@functools.lru_cache(maxsize=128, typed=False)

المعاملات

maxsize

عدد الاستدعاءات التي ستُخبّأ، إن مُرّرت له القيمة None، تُعطّل ميّزة LRU (الأقلّ استخدامًا مؤخّرًا، Least recently used) ويُمكن للتّخبئة أن تنمو دون قيود. تعمل ميّزة LRU بشكل أفضل إن كانت قيمة maxsize قوّة 2 (power-of-two).

typed

مُعامل يُحدّد ما إذا كانت مُعاملات الدّالة التي تكون أنواعها مُختلفةً ستُخبأ بشكل مُنفصل أو لا.

إن كانت قيمته القيمةَ True، فستُخبّأ مُعاملات كلّ نوع على حدة. فمثلًا، سيُعامل f(3)‎ وf(3.0)‎ على أنّهما استدعاءان مُختلفان مع نتيجتين مُختلفتين.

القيمة الافتراضيّة هي القيمة False.

أمثلة

المثال التّالي يوضّح كيفيّة عمل هذه الدّالة للحصول على محتوى ويب ثابت:

@lru_cache(maxsize=32)
def get_pep(num):
    'الحصول على نصّ من اقتراح من اقتراحات تحسين بايثون'
    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num
    try:
        with urllib.request.urlopen(resource) as s:
            return s.read()
    except urllib.error.HTTPError:
        return 'Not Found'

>>> for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:
...     pep = get_pep(n)
...     print(n, len(pep))

>>> get_pep.cache_info()
CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)

مثال على طريقة فعّالة لحساب أعداد فيبوناتشي باستخدام تخبئة لتطبيق تقنيّة برمجة ديناميكيّة:

@lru_cache(maxsize=None)
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

>>> [fib(n) for n in range(16)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

>>> fib.cache_info()
CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)

ملاحظات

للمُساعدة على قياس مدى كفاءة التّخبئة وتغيير قيمة المُعامل maxsize، تحصل الدّالة المُزخرَفة على الدّالة cache_info()‎ التي تُعيد صفًّا مُسمًّى يُظهر الضّربات (hits)، حالات الفشل (misses)، عدد الاستدعاءات الأقصى (maxsize)، وعدد الاستدعاءات الحاليّ (maxsize). تكون الضّربات وحالات الفشل تقريبيّة في بيئة مُتعدّدة السّلاسل (multi-threaded environment).

يُوفّر المُزخرِف كذلك دالّة cache_clear()‎‎ لمسح أو تعطيل صلاحيّة التّخبئة.

يُمكن الوصول إلى الدّالة الأصليّة عبر الخاصيّة ‎__wrapped__‎. هذا مُفيد لفحص الدّالة، أو تجاهل التّخبئة، أو لإعادة زخرفة الدّالة بتخبئة مُختلفة.

تعمل تخبئة LRU بشكل أفضل عندما تتوقّع آخر الاستدعاءاتِ حدوثًا الاستدعاءات القادمة (فمثلًا، تتغيّر أكثر المقالات شهرةً في خادوم أخبارٍ كلّ يوم). الحدّ الأقصى لحجم الخبيئة يتحقّق من أنّ التّخبئة لا تنمو دون ارتباط على عمليّات تأخذ وقتًا طويلًا لتتم، كخوادم الويب مثلًا.

انظر أيضًا

مصادر