bat*_*man 53 python dictionary nested
我是python的新手,我希望我能用.
符号来访问a的值dict
.
让我们说我test
喜欢这样:
>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value
Run Code Online (Sandbox Code Playgroud)
但是,我希望我能做到test.name
让value
.事实上,我通过覆盖__getattr__
我的类中的方法来做到这一点:
class JuspayObject:
def __init__(self,response):
self.__dict__['_response'] = response
def __getattr__(self,key):
try:
return self._response[key]
except KeyError,err:
sys.stderr.write('Sorry no key matches')
Run Code Online (Sandbox Code Playgroud)
这很有效!当我做:
test.name // I get value.
Run Code Online (Sandbox Code Playgroud)
但问题是当我test
单独打印时,我得到的错误是:
'Sorry no key matches'
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
wim*_*wim 92
此功能已存在于标准库中,因此我建议您只使用他们的类.
>>> from types import SimpleNamespace
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> n = SimpleNamespace(**d)
>>> print(n)
namespace(key1='value1', key2='value2')
>>> n.key2
'value2'
Run Code Online (Sandbox Code Playgroud)
通过常规属性访问可以实现添加,修改和删除值,即您可以使用n.key = val
和等语句del n.key
.
再次回到dict:
>>> vars(n)
{'key1': 'value1', 'key2': 'value2'}
Run Code Online (Sandbox Code Playgroud)
dict中的键应该是字符串标识符,以便属性访问正常工作.
Python 3.3中添加了简单的命名空间.对于该语言的旧版本,argparse.Namespace
具有类似的行为.
for*_*ran 31
我假设您对Javascript感到满意,并希望借用这种语法......我可以通过个人经验告诉您这不是一个好主意.
它确实看起来不那么冗长和整洁; 但从长远来看,它只是模糊不清.Dicts是dicts,并试图让它们表现得像具有属性的对象可能会导致(坏)惊喜.
如果您需要操纵对象的字段,就好像它们是字典一样,您可以随时使用内部__dict__
属性,然后明确清楚您正在做什么.或者getattr(obj, 'key')
也可以考虑继承结构和类属性.
但通过阅读你的例子,似乎你正在尝试不同的东西......因为点运算符已经在__dict__
没有任何额外代码的情况下查看属性.
Mic*_* H. 10
除了这个答案之外,还可以添加对嵌套字典的支持:
from types import SimpleNamespace
class NestedNamespace(SimpleNamespace):
def __init__(self, dictionary, **kwargs):
super().__init__(**kwargs)
for key, value in dictionary.items():
if isinstance(value, dict):
self.__setattr__(key, NestedNamespace(value))
else:
self.__setattr__(key, value)
nested_namespace = NestedNamespace({
'parent': {
'child': {
'grandchild': 'value'
}
},
'normal_key': 'normal value',
})
print(nested_namespace.parent.child.grandchild) # value
print(nested_namespace.normal_key) # normal value
Run Code Online (Sandbox Code Playgroud)
请注意,这不支持位于例如列表中的字典的点符号。
小智 7
class convert_to_dot_notation(dict):
"""
Access dictionary attributes via dot notation
"""
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
test = {"name": "value"}
data = convert_to_dot_notation(test)
print(data.name)
Run Code Online (Sandbox Code Playgroud)
__getattr__
当所有其他属性查找规则都失败时用作后备。当你试图“打印”你的对象时,Python 会寻找一个__repr__
方法,因为你没有在你的类中实现它,它最终会调用__getattr__
(是的,在 Python 中方法也是属性)。您不应该假设将使用哪个键getattr调用,最重要的是,__getattr__
如果无法解析,则必须引发 AttributeError key
。
附带说明:不要self.__dict__
用于普通属性访问,只需使用普通属性表示法:
class JuspayObject:
def __init__(self,response):
# don't use self.__dict__ here
self._response = response
def __getattr__(self,key):
try:
return self._response[key]
except KeyError,err:
raise AttributeError(key)
Run Code Online (Sandbox Code Playgroud)
现在,如果您的班级没有其他责任(并且您的 Python 版本 >= 2.6 并且您不需要支持旧版本),您可以只使用 namedtuple :http : //docs.python.org/2/library/ collections.html#collections.namedtuple
您可以使用一个命名的元组吗?
from collections import namedtuple
Test = namedtuple('Test', 'name foo bar')
my_test = Test('value', 'foo_val', 'bar_val')
print(my_test)
print(my_test.name)
Run Code Online (Sandbox Code Playgroud)
您可以使用内置方法argparse.Namespace()
:
import argparse
args = argparse.Namespace()
args.name = 'value'
print(args.name)
# 'value'
Run Code Online (Sandbox Code Playgroud)
您还可以通过获取原始字典vars(args)
。
小智 -1
__repr__()
向类添加一个方法,以便您可以自定义要显示的文本
print text
Run Code Online (Sandbox Code Playgroud)
在这里了解更多信息: https: //web.archive.org/web/20121022015531/http ://diveintopython.net/object_oriented_framework/special_class_methods2.html