4

Pythonの組み込み型の特殊関数を上書きする方法はありますか?たとえば、組み込みのdictから継承するSpecialDictクラスを作成したいと思います。次のように、ユーザーが特別な辞書のキーと値の両方に対してカスタム検証関数を定義できるようにしたいです。

def __init__(self, keyValidator = True, valueValidator = True):
    self.keyValidator = keyValidator
    self.valueValidator = valueValidator

これを使用して、次のように、updateメソッドでの値の追加をインターセプトできます。

def update(self,key,value):
    assert (self.keyValidator(key))
    assert (self.valueValidator(key))
    self[key] = value

しかし、誰かが先に進んで[]をアクセスとして使用することにした場合、これは機能しません。または、誰かが辞書リテラルを使用してオブジェクトを作成した場合。

mySpecialDict = SpecialDict
mySpecialDict['hello'] = 54
4

4 に答える 4

4

辞書リテラルはまさにそれであるため、誰かがyour のインスタンスを辞書リテラルとして作成することはできません。SpecialDict普通の辞書。

のような角括弧表記のある項目の設定に関してはmySpecialDict['hello'] = 54、ちょうど に対応しmySpecialDict.__setitem__('hello', 54)ます。同様に、角括弧表記のアイテムを取得することは、__getitem__メソッドの呼び出しに対応します。これは、どのクラスでも当てはまりmySpecialDictます。それが通常の辞書であろうと、組み込みのサブクラス化されたクラスであろうと、dictまったく関係のないクラスであろうと。したがって、これらのメソッドを実装して、その動作を変更することができます (必要な場合は、通常の実装を使用super(SpecialDict, self).__setitem__(key, value)またはdict.__setitem__(self, key, value)参照します)。

遭遇する問題の 1 つは、他の dict メソッドの組み込み実装の一部 (すべて?) がオーバーライドされた__setitem__orを尊重しないこと__getitem__です。したがって、それらを継承することはできません。それらすべてをオーバーライドし、基本操作のバージョンに関してそれらを完全に再実装するか、少なくともスーパークラス呼び出しの「周り」で検証を実行する必要があります。

実際には、ビルトインの dict をサブクラス化せ、代わりにまたは基本クラスを使用して辞書インターフェースを取得する、通常の辞書をラップするカスタムの「dict のような」オブジェクトを実装する方が、はるかに苦痛の少ない方法です。このアプローチを使用すると、約 6 つの基本的なメソッドを自分で実装するだけで済み (ラップされた辞書への呼び出しに検証ロジックをプラグインすることで実装できます)、それらに基づいて他のメソッドの適切な定義を取得できます。http://docs.python.org/library/collections.html#collections-abstract-base-classesを参照してくださいcollections.Mappingcollections.MutableMapping

于 2012-05-18T00:17:12.990 に答える
2

特別なメソッドをオーバーライドして、オペレーター__getitem__の独自の動作を実装できます。[]詳細については、これを参照してください。

于 2012-05-17T22:46:37.070 に答える
0

メソッドをオーバーライドして、親オブジェクトの (つまりs) メソッドにアクセスするために__setitem__(self, key, val) 使用できます。super(SpecialDict, self).__setitem__dict

class SpecialDict(dict):
    def __init__(self, keyValidator = lambda x:True, valueValidator = lambda x:True):
        self.keyValidator = keyValidator
        self.valueValidator = valueValidator
    def __setitem__(self, key, val):
        assert (self.keyValidator(key))
        assert (self.valueValidator(val))
        super(SpecialDict, self).__setitem__(key, val)

ラムダをデフォルト値として使用することにも注意してください。単純にTrueorFalseを使用すると、呼び出すことができないため、エラーが発生します。

于 2012-05-17T22:49:55.107 に答える
-1

雷!

私はモバイルデバイスを使用しているので、完全な答えを出すことはできませんが、調べ__getitem____setitem__

于 2012-05-17T22:47:04.157 に答える