2017-10-08 22 views
4

私はPythonでdictのようなクラスを作ろうとしています。クラスのdict()をオーバーライド

クラスを作成するときに、Pythonに組み込みクラスの作成方法を伝える特定のメソッドがあります。たとえば、__int__メソッドをオーバーライドすると、ユーザーがクラスのインスタンスでint()を使用した場合に返される内容がPythonに伝えられます。 __float__と同じです。 __iter__メソッド(Pythonがクラスのlisttupleを作るのを助けることができる)をオーバーライドすることによって、Pythonがクラスの反復可能なオブジェクトを作る方法を制御することさえできます。私の質問は、カスタムクラスのdictを作る方法をPythonにどのように教えてくれるのですか?特別な__dict__メソッドはありません。どうすればそれをやりますか?私は次のような何かをしたい:

class Foo(): 
    def __dict__(self): 
     return { 
      'this': 'is', 
      'a': 'dict' 
     } 

foo = Foo() 
dict(foo) # would return {'this': 'is', 'a': 'dict'} 

私はdictからクラスを継承することを試みたが、それはdicttypeを継承しようとしているので、サブクラスの後のコードでエラーが発生しますので、dict ISNから継承します可能性はない。それを行う他の方法はありますか? (あなたがdictiter()を使用するときに返されるものを)dict_keyiteratorオブジェクトを返すように

また、私はすでに__iter__メソッドをオーバーライドしてきましたが、まだどのようにそれが必要動作するようには思えません。

+0

あなたはcollections.abc 'から継承みました* Mapping'はまだ? –

+0

'collections.abc.Mapping'は' ABCMeta'のクラスです。私のコードの多くはすでに 'type'メタクラスの上に構築されているので、' ABCMeta'と互換性がありません。私はすべてのコードをABCMetaで動作するように変更しようとしましたが、 'マッピング 'のような抽象クラスに頼らない簡単な方法があると思っていました。 – ChristianFigueroa

+0

クラスに '@ staticmethod'を追加するだけです。たとえば、' to_dict'のように名前を付けます。これは明示的に辞書を作るために呼び出すことができます。すなわち 'result = foo_obj.to_dict()'です。 – martineau

答えて

2

dictはペアの反復可能で呼び出すことができますので、あなたはタプルの反復可能を返すために、あなたの__iter__をデザインする場合は、あなたが好きなように、あなたの例では動作します:

class Foo: 
    def __iter__(self): 
     yield from { 
      'this': 'is', 
      'a': 'dict' 
     }.items() 

dict(Foo()) 
{'a': 'dict', 'this': 'is'} 

あなたがしたい場合クラスがPython辞書のように動作するようにします。インスタンスを反復処理してそのキーを反復すると、abc.Mappingで定義されたインタフェースを実装できます。

あなたは__getitem____iter__、および__len__を実装し、abc.Mappingから継承することにより、または__getitem____iter____len____contains__keysitemsvaluesget__eq__、および__ne__のすべてを実装することにより、このいずれかを行うことができます。

+1

'Foo'オブジェクトに' dict'を作成するためには正しく動作しますが、アイテムのキーを反復することはできません。 'for i in Foo()'のようなものは、オブジェクトの_keys_を反復しません。_tuple_の '(key、value)'タプルを反復処理します。 – ChristianFigueroa

+1

@Christian:良い点...しかし、クラス 'Foo'は' dict'の形式的なサブクラスではないので、反復されたときに正しく動作すると仮定すると完全に合理的ではありません。 – martineau

+0

ForeverWintr:クラス(ちょうど)に '__getitem __()'メソッドを与えるFWIWは、組み込みの 'dict'クラスオブジェクトをそれらのインスタンスから作成することを許可します。私はまだもっと明示的で、クラスに 'to_dict()'メソッドを与えることをお勧めします。 – martineau

1

@ForeverWintrからanswerでのアプローチはかなり巧妙であると動作しますが、私はそれがdictクラスのコンストラクタに渡された引数の属性に関する難解な詳細の一部を活用していますので、それは少しあいまいだと思います。

このような理由から、あなたが望むことを行うメソッドを追加することについての私のコメントでは、より良いアプローチが(ちょうどそれが何が起こっているのかを単にどのように名前を付けているかを示しています。

例コード:

class Foo: 
    def to_dict(self): 
     return {'this': 'is', 'more': 'clear'} 

print(Foo().to_dict()) # -> {'this': 'is', 'more': 'clear'} 
関連する問題