Python重写字典访问方法
我有一个从dict类继承的类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
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'