如何在python中为dict使用点表示法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16279212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use dot notation for dict in python?
提问by batman
I'm very new to python and I wish I could do .notation to access values of a dict.
我对 python 很陌生,我希望我可以做.符号来访问dict.
Lets say I have testlike this:
可以说我有test这样的:
>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value
But I wish I could do test.nameto get value. Infact I did it by overriding the __getattr__method in my class like this:
但是,我希望我能做到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')
and this works! when I do:
这有效!当我做:
test.name // I get value.
But the problem is when I just print testalone I get the error as:
但问题是当我test单独打印时,我得到的错误是:
'Sorry no key matches'
Why is this happening?
为什么会这样?
回答by batman
Add a __repr__()method to the class so that you can customize the text to be shown on
__repr__()向类中添加一个方法,以便您可以自定义要显示的文本
print text
Learn more here: https://web.archive.org/web/20121022015531/http://diveintopython.net/object_oriented_framework/special_class_methods2.html
在此处了解更多信息:https: //web.archive.org/web/20121022015531/http: //diveintopython.net/object_orient_framework/special_class_methods2.html
回答by fortran
I assume that you are comfortable in Javascript and want to borrow that kind of syntax... I can tell you by personal experience that this is not a great idea.
我假设您熟悉 Javascript 并想借用这种语法……我可以根据个人经验告诉您,这不是一个好主意。
It sure does look less verbose and neat; but in the long run it is just obscure. Dicts are dicts, and trying to make them behave like objects with attributes will probably lead to (bad) surprises.
它确实看起来不那么冗长和整洁;但从长远来看,它只是晦涩难懂。字典就是字典,试图让它们表现得像具有属性的对象可能会导致(坏)意外。
If you need to manipulate the fields of an object as if they were a dictionary, you can always resort to use the internal __dict__attribute when you need it, and then it is explicitlyclear what you are doing. Or use getattr(obj, 'key')to have into account the inheritance structure and class attributes too.
如果你需要,就好像他们是一个字典来操纵对象的字段,你总是可以诉诸使用内部__dict__当你需要它的属性,然后它被明确清楚自己在做什么。或者使用getattr(obj, 'key')也要考虑到继承结构和类属性。
But by reading your example it seems that you are trying something different... As the dot operator will already look in the __dict__attribute without any extra code.
但是通过阅读您的示例,您似乎正在尝试不同的东西......因为点运算符已经在__dict__没有任何额外代码的情况下查看属性。
回答by Yann
Could you use a named tuple?
您可以使用命名元组吗?
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)
回答by wim
This functionality already exists in the standard libraries, so I recommend you just use their class.
这个功能已经存在于标准库中,所以我建议你只使用他们的类。
>>> from types import SimpleNamespace
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> n = SimpleNamespace(**d)
>>> print(n)
namespace(key1='value1', key2='value2')
>>> n.key2
'value2'
Adding, modifying and removing values is achieved with regular attribute access, i.e. you can use statements like n.key = valand del n.key.
添加、修改和删除值是通过常规属性访问实现的,即您可以使用像n.key = valand 之类的语句del n.key。
To go back to a dict again:
再次返回 dict:
>>> vars(n)
{'key1': 'value1', 'key2': 'value2'}
The keys in your dict should be string identifiersfor attribute access to work properly.
dict 中的键应该是字符串标识符,以便属性访问正常工作。
Simple namespace was added in Python 3.3. For older versions of the language, argparse.Namespacehas similar behaviour.
Python 3.3 中添加了简单命名空间。对于旧版本的语言,argparse.Namespace具有类似的行为。
回答by Aya
You have to be careful when using __getattr__, because it's used for a lot of builtin Python functionality.
使用 时必须小心__getattr__,因为它用于许多内置的 Python 功能。
Try something like this...
尝试这样的事情......
class JuspayObject:
def __init__(self,response):
self.__dict__['_response'] = response
def __getattr__(self, key):
# First, try to return from _response
try:
return self.__dict__['_response'][key]
except KeyError:
pass
# If that fails, return default behavior so we don't break Python
try:
return self.__dict__[key]
except KeyError:
raise AttributeError, key
>>> j = JuspayObject({'foo': 'bar'})
>>> j.foo
'bar'
>>> j
<__main__.JuspayObject instance at 0x7fbdd55965f0>
回答by bruno desthuilliers
__getattr__is used as a fallback when all other attribute lookup rules have failed. When you try to "print" your object, Python look for a __repr__method, and since you don't implement it in your class it ends up calling __getattr__(yes, in Python methods are attributes too). You shouldn't assume which key getattrwill be called with, and, most important, __getattr__must raise an AttributeError if it cannot resolve key.
__getattr__当所有其他属性查找规则都失败时用作后备。当你试图“打印”你的对象时,Python 会寻找一个__repr__方法,因为你没有在你的类中实现它,它最终会调用__getattr__(是的,在 Python 中方法也是属性)。您不应该假设将使用哪个键getattr调用,最重要的是,__getattr__如果无法解析,则必须引发 AttributeError key。
As a side note: don't use self.__dict__for ordinary attribute access, just use the plain attribute notation:
附带说明:不要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)
Now if your class has no other responsability (and your Python version is >= 2.6 and you don't need to support older versions), you may just use a namedtuple : http://docs.python.org/2/library/collections.html#collections.namedtuple
现在,如果您的班级没有其他责任(并且您的 Python 版本 >= 2.6 并且您不需要支持旧版本),您可以只使用 namedtuple :http: //docs.python.org/2/library/ collections.html#collections.namedtuple
回答by Michael H.
In addition to this answer, one can add support for nested dicts as well:
除了这个答案之外,还可以添加对嵌套字典的支持:
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
Note that this does not support dot notation for dicts that are somewhere inside e.g. lists.
请注意,这不支持位于例如列表中的字典的点符号。

