web-dev-qa-db-ja.com

サブクラスdict:UserDict、dictまたはABC?

UserDictdictABCの違いは何ですか?どちらが推奨されますか?ドキュメントはUserDictを非推奨にしているようです?

また、UserDictのupdate()は私のsetitemメソッドを使用するようですが、dictは使用しませんか?カスタムのsetitem関数とgetitem関数が必要な場合、オーバーライドするのに本当に不可欠なメソッドはどれですか?

ABCsを使用すると、デフォルトの実装が提供されないため、絶対にすべてのメソッドを実装する必要がありますか?

2つのことを行うdictを作成したいと思います。

  • intern()すべてのキーと値
  • 一部の値をSQLiteデータベースに保存します

では、UserDictdictABCのどれが私にこれを行うのに最適でしょうか?

41
Gerenuk

実際にデータを保持するカスタムコレクションが必要な場合は、サブクラスdict。これは、インターフェースを拡張したい場合(メソッドの追加など)に特に役立ちます。

ただし、組み込みメソッドはいずれもカスタム___getitem___/___setitem___を呼び出しません。これらを完全に制御する必要がある場合は、代わりに_collections.MutableMapping_抽象基本クラスを実装するカスタムクラスを作成してください。

ABCは、実際のデータを格納する手段を提供せず、一部のメソッドのデフォルト実装を備えたインターフェースのみを提供します。ただし、これらのデフォルトの実装では、カスタム___getitem___および___setitem___が呼び出されます。データを保持するには内部dictを使用し、すべての抽象メソッドを実装する必要があります:___len___、___iter___、___getitem___、___setitem___、および___delitem___。

UserDictモジュールのクラスcollections(Python 2では、モジュールはUserDictとも呼ばれます)は、内部のラッパーです) dictMutableMappingABCの実装。dictの動作をカスタマイズする場合は、この実装が出発点になる可能性があります。

要約すれば:

  • MutableMappingインターフェースを定義します。これをサブクラス化して、dictのように機能するものを作成します。データを保存するかどうか、またどのように保存するかは完全にあなた次第です。
  • serDictは、内部の「実際の」MutableMappingをストレージとして使用するdictの実装です。 dictのようなストレージコレクションが必要であるが、dictによって公開されているいくつかのメソッドをオーバーライドする場合、これはあなたにとって良い出発点かもしれません。ただし、コードを読んで基本的なメソッドがどのように実装されているかを確認し、メソッドをオーバーライドするときに一貫性を保つようにしてください。
  • dictは「本物」です。インターフェイスを拡張する場合は、これをサブクラス化します。通常、データにアクセスする方法は複数あり、APIに一貫性がなくなる可能性があるため、カスタム処理を実行するメソッドをオーバーライドすると危険な場合があります。
49
Ferdinand Beyer

秘密に基づく Python忍者 本のレシピ

UserDictが通常の辞書操作を超えて持つ唯一の特別なことは、単一の属性です。

data:UserDictクラスの内容を保持するための実際の辞書

辞書の項目にアクセスするには、それらを反復処理するか、items()を呼び出す必要があります。 UserDictインスタンスは同じメソッドをサポートしていますが、items()によって返されるビューは著しく異なります。

  >>> from collections import UserDict
  >>> a = UserDict(a=1)
  >>> d = dict(d=3)  # regular dictionary for comparison

  >>> for k in d:
  ...     print(k, d[k])
  ... 
  d 3
  >>> d.items()
  dict_items([('d', 3)])
  >>> for k in a:
  ...     print(k, a[k])
  ... 
  a 1
  >>> a.items()
  ItemsView({'a': 1})

ディクショナリオブジェクトがキー/値のタプルを返すことに注意してください。 UserDictは、実際の辞書オブジェクトを返します。データ属性を使用して辞書にアクセスする機能と同様に、実行している内容によっては、この違いが重要になる場合があります。

1
Vlad Bezden

UserDictクラスは使用しないでください。必要ありません。ドキュメントにあるように、dictを直接サブクラス化することができます。

ただし、 UserDict の場合は、DictMixinモジュールが必要です。

注:DictMixinは正式に非推奨ではありませんが、Python 3)で削除されました。 collections.MutableMappingを使用することをドキュメントで推奨しています。ただし、これには欠点があります。辞書インターフェイスをさらに実装する必要があります。__delitem____getitem____iter____len__、および__setitem__DictMixinを使用すると、変更したいものだけを実装でき、残りはデフォルトの実装を使用します。

from UserDict import DictMixin

class MyDict(DictMixin, dict):
    def __setitem__(self, key, value):
        print key, value # just an example
        # use intern(key) or whatever here
        dict.__setitem__(self, key, value) # or
        # super(MyDict, self).__setitem__(key, value)

m = MyDict()

m['a'] = 'b'
# a b
m.update({'a': 'c'})
# a c

自動的にupdate__setitem__を必要に応じて使用させます。

1
agf