2017-10-08 110 views
4

我试图让Python中的dict般类。覆盖字典()上

当你犯了一个类,你有一定的方法,告诉Python中如何做一个内置类。例如,覆盖__int__方法告诉Python中,如果用户在类的一个实例使用int()什么返回。与__float__相同。你甚至可以控制Python的将被重写__iter__方法(这可以帮助的Python使list S和tuple是你的类的)使类的迭代对象。我的问题是你如何告诉Python如何使你的自定义类的dict?没有特别的__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所以继承没有可能性。有没有其他方法可以做到这一点?

而且,我已经覆盖了__iter__方法已经以便它会返回一个dict_keyiterator对象(被退回什么,当你对一个dict使用iter()),但它似乎仍然没有工作应该如何。

+0

你试过从'collections.abc继承* Mapping'了吗? –

+0

'collections.abc.Mapping'是一类'ABCMeta'。我的很多代码已经建立在'type'元类的基础上,所以很多代码与'ABCMeta'不兼容。我可以通过我的所有代码试图改变它'ABCMeta'工作,但我只是希望有可能是不依赖于像'Mapping'一个抽象类的简单方法。 – 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_,它将遍历'(key,value)'元组的_tuple_。 – ChristianFigueroa

+1

@Christian:好点...但是'Foo'类不是'dict'的正式子类,所以假设它在迭代时的行为与完全一样是不完全合理的。 – martineau

+0

ForeverWintr:FWIW,给你的类(只)一个'__getitem __()'方法还允许从它们的实例创建内置的'dict'类对象。我仍然认为最好是更明确一点,并给这个类一个'to_dict()'方法,而不是依赖于另一个类的某些晦涩的构造参数细节.. – martineau

1

虽然在answer从@ForeverWintr的方法是相当聪明的工作,我认为这是一个有点晦涩难懂,因为它需要的一些关于传递给dict类的构造函数参数的属性的神秘细节优势。

出于这个原因,更好的方法是什么,我在我的意见是说大约只是添加一个方法,你想要做什么(加显示给它如何只是一个名,指示究竟发生了什么)。

示例代码:

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

print(Foo().to_dict()) # -> {'this': 'is', 'more': 'clear'}