2017-10-08 104 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'}