2016-08-04 5 views
3

私はキーとオブジェクトのペアでいっぱいの辞書を持っています。私は辞書を不変にしたいと思うし、ベスト/最も簡単な方法はfrozensetにキャストすることだと思ったが、frozenset(dict)tuple(dict)にはキーしか格納されていない。不変式のキーとオブジェクトのペアPython

を使用するfrozenset(dict.items())私はキーとオブジェクトのペアでフロゼンセットを取得するようですが、値/キーの取得方法はわかりません。

私は、作品次のコードを持っている限り、「__obfuscatorsは」辞書

def obfuscate_value(self, key, value): 
    obfuscator = self.__obfuscators.get(key) 
    if obfuscator is not None: 
     return obfuscator.obfuscate_value(value) 
    else: 
     return value 

であるように私はそれが凍結されたセットでの作業を取得しようとする試みでこれを試してみました:

def obfuscate_value(self, key, value): 
    try: 
     obfuscator = self.__obfuscators[key] 
    except: 
     return value 
    return obfuscator.obfuscate_value(value) 

しかし、これはfrozenset does not have \__getitem__self.__obfuscators.__getattribute__(key)は、(私はこれがキーという名前の関数を検索すると仮定しているので)属性を持たないと常に言います 辞書を作る良い方法はありますか?どのようにキーに応じてオブジェクトを取得できますか?

編集: 私はtuple(obfuscator.items()) を使用してタプルに辞書をキャストしてしまった後、自分の検索値関数で書きました:私は彼らの努力と入力のためのみんなに感謝したいと思います

def find_obfuscator(self, key): 
    for item in self.__obfuscators: 
     x, y = item 
     if self.case_insensitive: 
      if x.lower() == key.lower(): 
       return y 
     else: 
      if x == key: 
       return y 

を。

+0

'' collections.Mapping'をサブクラス化するか、 'Mappingproxy'を使うのはどうですか?私が知る限り、どちらも不変です(与えられた不変の値に対して)。 – MSeifert

答えて

0

辞書を取り、項目取得機能を持ちますが、設定項目を持たないラッパークラスを作ることができます。スレッドの安全性とハッシングのためにいくつかのものを追加する必要がありますが、基本クラスはそれほど難しくありません。これは、あなたが辞書を作成することができます

class MyDict(dict): 
    def __setitem__(self, key, value): 
     raise NotImplementedError("This is a frozen dictionary") 

その後項目の割り当てによって変更することはできない。私はあなたが望むものを達成するために考えることができ

+0

私はこれについて考えましたが、独自のカスタム辞書クラスを作成するよりも簡単で高速な解決策が得られることを願っていました。私はキーオブジェクトのペアを持つfrozensetを持っているので私はとても近いようでしたが、私はちょうどそれらにアクセスすることはできませんまたは少なくとも私はこのオプションを使用して – ThunderM

0

最も簡単な方法は、標準dictタイプをサブクラス化し、その__setitem__メソッドを上書きしました:

d = MyDict({1: 2, 3: 4}) 

または、等価的に:

d = MyDict([(1, 2), (3, 4)]) 

辞書はその後、ちょうど標準のdictのように出力します:あなたが値を変更(または新しいものを追加)しようとすると、

{1: 2, 3: 4} 

しかし:

d[1] = 15 
--------------------------------------------------------------------------- 
NotImplementedError      Traceback (most recent call last) 
<ipython-input-21-a22420992053> in <module>() 
----> 1 d[1] = 34 

<ipython-input-18-03f266502231> in __setitem__(self, key, value) 
     1 class MyDict(dict): 
     2  def __setitem__(self, key, value): 
----> 3   raise NotImplementedError("This is a frozen dictionary") 

NotImplementedError: This is a frozen dictionary 

注これは完全ではないこと不変の、しかし:

d.update({1:17}) 

例えば、それを更新しますが、この解決策は十分であるかもしれない - それはより広範な要件に依存します。

1

あなたがtypes.MappingProxyTypeを使用して、辞書の不変のビューを作成することができますので、あなたはまだvauleオブジェクトを変更することができます

from types import MappingProxyType 
d = { 'a': 1 } 
fd = MappingProxyType(d) 
fd['a'] 
#output: 
1 

fd['a'] = 2 
#output: 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'mappingproxy' object does not support item assignment 

の通知、:

d = { 'a': [1] } 
fd = MappingProxyType(d) 
fd['a'].append(2) 
fd['a'] 
#output: 
[1,2] 

は動作しますが。

0

、あなたのオリジナルのポストでtuple(dict)に言及しているので、おそらくあなたが望むものを達成するための最も簡単な解決策は、単純に次のようになります。

tuple(dict.items()) 
+0

私はまだ ' frozenset(dict.items()) '。キーに基づいてどのように値にアクセスできますか? – ThunderM

+0

このオプションについてもう一度考えると、他のすべてのオプションが単純ではないので – ThunderM

0

あなたが凍結することのできるdictが必要ですか?あなたは、単にものを作ることができます。

class FrozenDict(dict): 
    def __init__(self, *args, **kwargs): 
     self._frozen = False 
     dict.__init__(self, *args, **kwargs) 
    def freeze(self): 
     self._frozen = True 
    def __setitem__(self, key, value): 
     if (self._frozen): 
      raise TypeError("Attempted assignment to a frozen dict") 
     else: 
      return dict.__setitem__(self, key, value) 

a = FrozenDict({7:8}) 
a[5] = 6 
print(a) 
a.freeze() 
a[3] = 2 # raises TypeError 

あなたは.freeze()を呼び出すまでそれはまさにdictいつものように動作します。それは凍っている。