2014-04-12 93 views
2

我有一個從dict類繼承的類devices。設備是詞典的詞典。我想通過使用方法調用語法來訪問它的鍵和值,以及使用正常的語法。即Python重寫字典訪問方法

class Devices(dict): 
    def __init__(self): 
     self['device'] = {'name':'device_name'} 
    def __getattr__(self, name): 
     value = self[name] 
     return value 
... 

mydevices = Devices() 
mydevice = mydevices.device #works and mydevices['device'] also works 

#But what code do I need for the following? 
name = mydevices.device.name 
mydevices.device.name = 'another_name' 

我知道,如果我重寫__getattr____setattr__方法我能做到這一點,但你可以從我的代碼看,我不知道如何訪問一個嵌套的字典。 有誰知道如何做到這一點?

謝謝,labjunky

+0

我很驚訝,你說這個代碼在所有工作。它有一些問題。也許你有另一個名爲'Devices'的類(半)工作代碼呢? –

+0

是的你是對的,編輯。 – labjunky

回答

2

所以你的答案是非常完整無論如何。你可以定義你想要的那種結構:

class Devices(dict): 
    def __init__(self,inpt={}): 
     super(Devices,self).__init__(inpt) 

    def __getattr__(self, name): 
     return self.__getitem__(name) 

    def __setattr__(self,name,value): 
     self.__setitem__(name,value) 

然後,使用情況是:

In [6]: x = Devices() 

In [7]: x.devices = Devices({"name":"thom"}) 

In [8]: x.devices.name 
Out[8]: 'thom' 

基本上只是窩您屬性查找詞典。

+0

有沒有一個更一般的方式做到這一點,沒有添加任何東西到構造函數? – labjunky

+0

@labjunky你的意思是沒有超級電話?或者你的意思是你想要在初始化程序中定義字典的內容? – ebarr

+0

其實它確定你擁有它的方式。謝謝。 – labjunky

1

一般來說,要訪問字典值使用dictionary[key]而不是dictionary.key。在第一種情況下,屬性方式起作用,因爲您將覆蓋__getattr__而不是__getitem__。這就是爲什麼它只適用於你的課程,但不適用於內部詞典。

現在,查閱字典中__getitem____getattr__是屬性,就像dict.keys其中單詞keys是屬性),你需要小心一點。你需要調用字典類的__getitem__(否則你將有無限遞歸)。有兩種方法可以實現它。第一個將是持久的,如果你選擇改變你反對世襲:

def __getitem__(self, name): 
    value = super(Devices,self).__getitem__(name) 
    return value 

另一種方法是:

def __getitem__(self, name): 
    value = dict.__getitem__(self, name) 
    return value 

如果你仍然想使用屬性來訪問值,你就必須更換與你的類字典,只要你使用它(所以self['device'] = {'name':'device_name'}將成爲self['device'] = MyDictClass({'name':'device_name'})


BTW:請注意,您必須在的錯誤。行self = {'device':{'name':'device_name'}}__init__實際上並沒有做任何事情。 (它將字典放在本地變量self中,但只要退出該功能,該變量就會消失。)

您應該使用改變對象本身的操作。即:

def __init__(self): 
    self['device'] = {'name':'device_name'} 
+0

感謝您注意錯誤。 – labjunky

1

你可以使用這個棘手的類,它是dict一個子類,它的鍵可以accssed無論是作爲項目(d[k])或屬性(d.k):

class Struct(dict): 
    def __init__(self,*args, **kwargs): 
     dict.__init__(self,*args, **kwargs) 
     self.__dict__ = self # yes, it is tricky 

的這裏的關鍵是,口譯員在致電__[gs]etattr__之前會檢查__dict__,所以你甚至不需要重寫它們。

現在你可以這樣做:

class Devices(Struct): 
    pass 

devices = Devices() 
devices.device = Struct(name='devicename') 
devices.device.name = 'anothername'