تحديد حجم قاموس python




caching dictionary (5)

بيثون 2.7 و 3.1 ديك OrderedDict وهناك تطبيقات بيثون نقية OrderedDict سابق.

from collections import OrderedDict

class LimitedSizeDict(OrderedDict):
  def __init__(self, *args, **kwds):
    self.size_limit = kwds.pop("size_limit", None)
    OrderedDict.__init__(self, *args, **kwds)
    self._check_size_limit()

  def __setitem__(self, key, value):
    OrderedDict.__setitem__(self, key, value)
    self._check_size_limit()

  def _check_size_limit(self):
    if self.size_limit is not None:
      while len(self) > self.size_limit:
        self.popitem(last=False)

يجب أيضًا تجاوز الطرق الأخرى التي يمكنها إدراج عناصر ، مثل التحديث. الاستخدام الأساسي لـ OrderedDict هو حتى تتمكن من التحكم في ما يمكن أن ينفجر بسهولة ، وإلا ستعمل الطريقة المعتادة.

أود أن أعمل مع dict في python ، ولكن قلل عدد أزواج المفاتيح / القيم إلى X. وبعبارة أخرى ، إذا كان dict يقوم حاليًا بتخزين أزواج X مفتاح / قيمة وأقوم بإجراء إدخال ، أود الحصول على الأزواج الموجودة ليتم إسقاطها. سيكون من اللطيف إذا كان هذا هو أقل مفتاح تم إدخاله / دخوله مؤخرًا ولكن هذا ليس ضروريًا تمامًا.

إذا كان هذا موجودًا في المكتبة القياسية ، فالرجاء حفظ بعض الوقت والإشارة إليه!


سوف توفر لك cachetools تنفيذ لطيفة من رسم الخرائط Hashes أن يفعل هذا (ويعمل على الثعبان 2 و 3).

مقتطفات من الوثائق:

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


ليس لدى dict هذا السلوك. يمكنك إنشاء صفك الخاص الذي يفعل هذا ، على سبيل المثال شيء من هذا القبيل

class MaxSizeDict(object):
    def __init__(self, max_size):
        self.max_size = max_size
        self.dict = {}
    def __setitem__(self, key, value):
        if key in self.dict:
            self.dict[key] = value    
            return

        if len(self.dict) >= self.max_size:
      ...

بعض الملاحظات حول هذا

  • سيكون من المغري لبعض لفئة subclass هنا. يمكنك القيام بذلك من الناحية الفنية ، ولكنها عرضة للخلل لأن الطرق لا تعتمد على بعضها البعض. يمكنك استخدام UserDict.DictMixin لحفظ الحاجة إلى تحديد كافة الطرق. هناك بعض الأساليب التي يمكنك إعادة استخدامها إذا كنت dict فئة فرعية.
  • لا تعرف الوسيلة ما هو أقل مفتاح تم إضافته مؤخرًا ، نظرًا لعدم وجود دييكت غير مرتبة.
    • سوف 2.7 إدخال مجموعات.ترتيب collections.OrderedDict ، ولكن الآن للحفاظ على مفاتيح بالترتيب ينبغي أن تعمل بشكل جيد (استخدام collections.deque كقائمة انتظار).
    • إذا كان الحصول على الأقدم ليس بالأمر السهل ، يمكنك فقط استخدام طريقة popitem لحذف عنصر واحد عشوائي.
  • لقد فسرنا أقدمها ليعني الإدخال الأول ، تقريبًا. يجب عليك القيام بشيء مختلف بعض الشيء لإزالة عناصر LRU. تتضمن الإستراتيجية الفعالة الأكثر وضوحًا الاحتفاظ بقائمة مفاتيح مزدوجة مرتبطة بالمراجع إلى العقد التي تم تخزينها كقيم dict (مع القيم الحقيقية). يصبح هذا الأمر أكثر تعقيدًا ويؤدي تنفيذه في بايثون النقية إلى الكثير من النفقات العامة.

هنا ، حل Python 2.6+ بسيط ، لا LRU (في بايثون أقدم يمكنك القيام بشيء مماثل مع UserDict.DictMixin ، ولكن في 2.6 وأفضل أن لا ينصح بذلك ، وأبجديات من collections هي الأفضل على أي حال ...):

import collections

class MyDict(collections.MutableMapping):
  def __init__(self, maxlen, *a, **k):
    self.maxlen = maxlen
    self.d = dict(*a, **k)
    while len(self) > maxlen:
      self.popitem()
  def __iter__(self):
    return iter(self.d)
  def __len__(self):
    return len(self.d)
  def __getitem__(self, k):
    return self.d[k]
  def __delitem__(self, k):
    del self.d[k]
  def __setitem__(self, k, v):
    if k not in self and len(self) == self.maxlen:
      self.popitem()
    self.d[k] = v 

d = MyDict(5)
for i in range(10):
  d[i] = i
  print sorted(d)

كما ذكرت إجابات أخرى ، ربما لا ترغب في أن تكتب فئة فرعية - التفويض الصريح إلى self.d هو لسوء الحظ bilerplatey لكنه يضمن أن كل طريقة أخرى يتم توفيرها بشكل صحيح من قبل collections.MutableDict .MutableDict.


يمكنك إنشاء فئة قاموس مخصص عن طريق subclassing dict. في حالتك ، يجب عليك تجاوز __setitem__ للتحقق من __setitem__ الخاص وحذف شيء ما إذا تم تقييد الحد. سيطبع المثال التالي الطول الحالي بعد كل إدخال:

class mydict(dict):
    def __setitem__(self, k, v):
        dict.__setitem__(self, k, v)
        print len(self)

d = mydict()
d['foo'] = 'bar'
d['bar'] = 'baz'




lru