Python重写字典访问方法

Python重写字典访问方法,python,dictionary,overriding,Python,Dictionary,Overriding,我有一个从dict类继承的类devices。devices是一本词典词典。我希望通过使用方法调用语法以及正常语法来访问它的键和值。i、 e class Devices(dict): def __init__(self): self['device'] = {'name':'device_name'} def __getattr__(self, name): value = self[name] return value ... m

我有一个从dict类继承的类
devices
。devices是一本词典词典。我希望通过使用方法调用语法以及正常语法来访问它的键和值。i、 e

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'
我知道如果我重写
\uuuu getattr\uuuu
\uuuu setattr\uuuu
方法,我可以实现这一点,但正如您从我的代码中看到的,我不确定如何访问嵌套字典。 有人知道如何做到这一点吗


谢谢,labjunky

所以你的答案很完整。您可以定义所需的结构类型:

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'

基本上只需嵌套属性查找字典。

通常,要访问字典值,请使用
dictionary[key]
而不是
dictionary.key
。在第一种情况下,属性方式起作用,因为您覆盖了
\uuuu getattr\uuuu
而不是
\uuuu getitem\uuuu
。这就是为什么它只适用于您的类,而不适用于内部字典

现在,要访问
\uuuuu getitem\uuuuuuuuuuuuuuuu
中的字典(
\uuuuuuuuuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是属性,就像
dict.keys
中的单词
keys
是属性),您需要小心。您需要调用dictionary类的
\uuuu getitem\uuu
(否则将有无限递归)。实现这一目标有两种方法。如果您选择将对象更改为遗传,则第一个将是持久的:

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\u name'}
将变成
self['device']=MyDictClass({'name':'device\u name'})


顺便说一句:请注意,
\uuuu init\uuuuu
中的
self={'device':{'name':'device\u name'}
行实际上什么都不做。(它将字典放在局部变量
self
中,但一旦退出该函数,该变量就会消失。)

您应该使用更改对象本身的操作。例如:

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

您可以使用这个棘手的类,它是dict的子类,其密钥可以作为项(
d[k]
)或属性(
d.k
)进行访问:

这里的关键是解释器在调用
\ugs]etattr\uuuu
之前会检查
\uuu dict\uuuu
,因此您甚至不需要覆盖它们

现在您可以执行以下操作:

class Devices(Struct):
    pass

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

我很惊讶你竟然说这段代码可以工作。它有很多问题。也许你还有另一个类叫做
Devices
with(semi-)在其中运行代码?是的,你是对的,经过编辑。有没有一种更通用的方法可以做到这一点,而不向构造函数添加任何内容?@labjunky你的意思是没有
super
调用?还是你的意思是你想要在初始化器中定义词典的内容?实际上,你的方式可以。谢谢。
class Devices(Struct):
    pass

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