2014-07-15 3 views
4

일부 중요한 데이터를 저장하기 위해 OrderedDict를 사용하고 있습니다. 실수로이 사전에 새 키를 삽입하면 예외가 발생하지만, 이되어야합니다. 키를 수정하려면 (__init__에서 생성 된 후) 키를 원한다. 일부 도서관 수업에서 그렇게 할 수 있습니까? 아니면 어떻게 든 새 클래스를 구현해야합니까?고정 키와 정렬 키가있는 변경 가능한 사전

예 :

d = FixedOrderedDict((("A", 1), ("B", 2))) 

print d["A"] 
# 1 
d["A"] = 11 
print d["A"] 
# 11 
d["C"] = 33 
# throws exception 

나는 FrozenDict라는 솔루션을 찾아 볼 것을 권장했지만 그것은 DICT 읽기 전용으로 만드는 - 값 수정 (새로운 값을 할당 할 때 예외를 throw) 할 수 없습니다. 이것은 내가 성취하고자하는 것이 아닙니다.

+1

나는 꽤 비슷한 문제에 잠깐 들렀다. 나는'__additem __()'IIRC를 하위 클래스화하고 오버라이드해야했습니다. – rdodev

답변

4

저는 표준 라이브러리에서 이러한 솔루션을 인식하지 못합니다 (다소 전문화 된 사용 사례입니다). 그러나 대부분의 기능을 무료로 사용하려면 collections.MutableMapping (3.3 및 이후 버전에서는 collections.abc.MutableMapping)을 사용할 수 있습니다. 부여 또는 지금 내가 내려다 보이는 할 수있는 몇 가지 사소한 문제를 가지고, 그것은 단지 :

from collections import MutableMapping, OrderedDict 

class FixedOrderedDict(MutableMapping): 
    def __init__(self, *args): 
     self._d = OrderedDict(*args) 

    def __getitem__(self, key): 
     return self._d[key] 

    def __setitem__(self, key, value): 
     if key not in self._d: 
      raise KeyError("Must not add new keys") 
     self._d[key] = value 

    def __delitem__(self, key): 
     raise NotImplementedError("Must not remove keys") 

    def __iter__(self): 
     return iter(self._d) 

    def __len__(self): 
     return len(self._d) 
+1

왜 캡슐화를 사용하지 않고 'OrderedDict'의 하위 클래스를 만들지 않습니까? – dano

+0

@ dano 그 권리를 어떻게 수행 할 지 모르겠고 여전히 MutableMapping에서 믹스 인을 얻습니다. 다중 상속은 어렵습니다 (그리고 찾고자하는 단어는 * composition *입니다). 그리고 그것은 네 개의 한 줄짜리 메소드 만 저장할 것입니다 (그리고 어리석은 타입 테스트를 통과 할 것입니다). – delnan

+0

@delnan에 동의합니다. 여기로 이동하는 방법이 있습니다. – mgilson

1

당신은 당신이 어떤 지점에서 키를 동결했지만 값이 돌연변이를 할 수 있도록 할 수 있습니다 dict의 서브 클래스를 필요하십니까? 이 기능을 사용하면 더 많은 유연성을 제공하기 위해 채우기 후에 키를 고정 할 수 있습니다. 코드는 모든 상속 방법이 제대로 작동한다고 가정 -

from collections import OrderedDict 

class FreezableDict(OrderedDict): 
    def __init__(self, *args, **kw): 
     super(OrderedDict, self).__init__(*args, **kw) 
     self._frozen = False 
    def __setitem__(self, key, value): 
     if key not in self and self._frozen: 
      raise TypeError("No key additions once a FreezableDict is frozen!") 
     return super(OrderedDict, self).__setitem__(key, value) 
    def freeze(self): 
     self._frozen = True 

d = FreezableDict((("A", 1), ("B", 2))) 

print d["A"] 
d["C"] = "New Value" 
d.freeze() 
d["C"] = "Replacement" 
print d["C"] 
d["D"] = "This raises a TypeError exception" 

모든 방법이 여기에 싸여하지하고 OrderedDict의 완전한 에뮬레이션로하지 않는다는 것을 기억하지만,주의하십시오. 예를 들어, 항목 삭제는 현재 동결 후에도 여전히 허용됩니다.

+0

d.update, d.setdefault ...도 있습니다. –

관련 문제