2012-05-25 4 views
9

"소비 된"키를 추적하는 기능이 추가 된 사전처럼 작동하는 데이터 구조를 만들고 싶습니다. 값을 재사용 할 때 값을 팝 할 수는 없습니다.액세스 된 키의 메모리가있는 파이썬 사전?

class DictWithMemory(dict): 

    def __init__(self, *args, **kwargs): 
     self.memory = set() 
     return super(DictWithMemory, self).__init__(*args, **kwargs) 

    def __getitem__(self, key): 
     self.memory.add(key) 
     return super(DictWithMemory, self).__getitem__(key) 

    def __contains__(self, key): 
     self.memory.add(key) 
     return super(DictWithMemory, self).__contains__(key) 

    def get(self, key, d=None): 
     self.memory.add(key) 
     return super(DictWithMemory, self).get(key, d) 

    def unused_keys(self): 
     """ 
     Returns the list of unused keys. 
     """ 
     return set(self.keys()).difference(self.memory) 

나는 매우 익숙하지 나처럼 :

if key in d: 
    ... 
d[key] 
d.get(key) 

이 내가 쓴 것입니다 : 소비로 액세스 할 때

구조는이 세 가지 사례를 지원해야한다, 즉 같은 키를 표시 dict의 내부 구조는이 결과를 얻는 더 좋은 방법이 있습니까?

+1

가 얼마나 자주 사용합니까'unused_keys :이 정말 더 우아한 있는지 확실하지 않습니다,하지만 당신이 사용하는 키를 저장하는 방법에 대한 당신의 마음을 변경해야합니다 캡슐화의 일부 금액을 제공한다 ? setter에 키를 추가하여 getter가이 세트에서 키를 제거하려고 시도했을 때 더 나은 성능을 제공 할 수 있습니다. ** 우아함 ** 부분에 대해서는 확실하지 않습니다. – Aprillion

+2

: 'unused_keys'가 명부? 본질적인 순서는 없으므로 집합을 반환하는 것이 좋습니다. –

+0

@ 토마스 K : 대칭성을 위해서'keys'가 목록을 반환합니다. – badzil

답변

4

다음은 메타 클래스 내 모든 것을 추상화하는 솔루션입니다. `) (

class KeyRememberer(type): 

    def __new__(meta, classname, bases, classDict): 
     cls = type.__new__(meta, classname, bases, classDict) 

     # Define init that creates the set of remembered keys 
     def __init__(self, *args, **kwargs): 
      self.memory = set() 
      return super(cls, self).__init__(*args, **kwargs) 
     cls.__init__ = __init__ 

     # Decorator that stores a requested key in the cache 
     def remember(f): 
      def _(self, key, *args, **kwargs): 
       self.memory.add(key) 
       return f(self, key, *args, **kwargs) 
      return _ 

     # Apply the decorator to each of the default implementations 
     for method_name in [ '__getitem__', '__contains__', 'get' ]: 
      m = getattr(cls, method_name) 
      setattr(cls, method_name, remember(m)) 

     return cls 


class DictWithMemory(dict): 

    # A metaclass that ensures the object 
    # has a set called 'memory' as an attribute, 
    # which is updated on each call to __getitem__, 
    # __contains__, or get. 
    __metaclass__ = KeyRememberer 

    def unused_keys(self): 
     """ 
     Returns the list of unused keys. 
     """ 
     print "Used", self.memory 
     return list(set(super(DictWithMemory, 
           self).keys()).difference(self.memory)) 
+1

나는 메타 캐스를 사용하는 것을 좋아해서 어떤 방법이 "소비자"로 간주되는지 동적으로 설정할 수 있습니다. – badzil

+0

@ badzil의 의견에 동의하며 어쩌면 더 나아가 고객이 어떤 방법을 소비자로 간주할지 정의하거나 무시할 수 있다고 생각합니다. 쉽게 추가 할 수 있다고 생각합니다. – martineau