如何在python中使用dict的点表示法?
我对python非常陌生,我希望我可以使用如何在python中使用dict的点表示法?,python,dictionary,nested,Python,Dictionary,Nested,我对python非常陌生,我希望我可以使用符号来访问dict的值 假设我有这样的测试: >>> test = dict() >>> test['name'] = 'value' >>> print(test['name']) value class JuspayObject: def __init__(self,response): self.__dict__['_response'] = response
符号来访问dict
的值
假设我有这样的测试
:
>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value
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')
但是我希望我能做test.name
来获得值。事实上,我这样做是通过重写类中的\uu getattr\uuu
方法实现的:
>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value
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')
这很有效!当我这样做时:
test.name // I get value.
但问题是,当我单独打印test
时,我得到的错误如下:
'Sorry no key matches'
为什么会发生这种情况?在类中添加一个\uu repr\uu()
方法,以便您可以自定义要显示的文本
print text
在这里了解更多信息:我假设您熟悉Javascript,并且希望借用这种语法。。。根据个人经验,我可以告诉你,这不是一个好主意
它看起来确实不那么冗长和整洁;但从长远来看,这只是一个模糊的概念。dict就是dict,试图让它们表现得像具有属性的对象可能会导致(糟糕的)意外
如果需要像操作字典一样操作对象的字段,则可以在需要时始终使用内部\uuu dict\uuu
属性,这样就可以清楚地知道您在做什么。或者使用getattr(obj,'key')
来考虑继承结构和类属性
但是通过阅读你的例子,你似乎在尝试不同的东西。。。因为点运算符已经在\uuuu dict\uuuu
属性中查找,没有任何额外的代码。您可以使用
此功能已经存在,因此我建议您只使用他们的类
>>> from types import SimpleNamespace
>>> d = {'key1': 'value1', 'key2': 'value2'}
>>> n = SimpleNamespace(**d)
>>> print(n)
namespace(key1='value1', key2='value2')
>>> n.key2
'value2'
添加、修改和删除值是通过常规属性访问实现的,也就是说,您可以使用诸如n.key=val
和del n.key
之类的语句
要再次返回到dict,请执行以下操作:
>>> vars(n)
{'key1': 'value1', 'key2': 'value2'}
dict中的键应该是字符串,以便属性访问正常工作
Python 3.3中添加了简单名称空间。对于较旧版本的语言,具有类似的行为 使用\uuu getattr\uuuu
时必须小心,因为它用于许多内置Python功能
试试这样的
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>
类JuspayObject:
定义初始化(自我,响应):
自我记录[回应]=回应
def_u_ugetattr_u_u(self,key):
#首先,尝试从_响应返回
尝试:
返回自我。记录[应答][键]
除KeyError外:
通过
#如果失败,则返回默认行为,这样我们就不会破坏Python
尝试:
返回self.\uuuu dict\uuuu[key]
除KeyError外:
提高属性错误,键
>>>j=JuspayObject({'foo':'bar'})
>>>傅家杰
“酒吧”
>>>j
\uuuu getattr\uuu
在所有其他属性查找规则失败时用作回退。当你试图“打印”你的对象时,Python会寻找一个\uuuu repr\uuu
方法,因为你没有在你的类中实现它,它最终会调用\uu getattr\uuu
(是的,在Python中方法也是属性)。您不应该假设将使用哪个键调用getattr,最重要的是,\uuuu getattr\uuuuu
如果无法解析键,则必须引发AttributeError
作为旁注:对于普通属性访问,不要使用self.\uu dict\uu
,只需使用普通属性表示法:
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)
现在,如果您的类没有其他职责(并且您的Python版本>=2.6,并且您不需要支持较旧的版本),那么您可以只使用一个namedtuple:此外,还可以添加对嵌套dict的支持:
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
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))
elif isinstance(value, list):
self.__setattr__(key, map(NestedNamespace, value))
else:
self.__setattr__(key, value)
请注意,这不支持列表中某个位置的DICT的点表示法。您可以使用内置方法:
您还可以通过vars(args)
获取原始dict,只需添加一小部分即可支持列表:
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
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))
elif isinstance(value, list):
self.__setattr__(key, map(NestedNamespace, value))
else:
self.__setattr__(key, value)
我使用带点的dict包:
>>> from dotted_dict import DottedDict
>>> test = DottedDict()
>>> test.name = 'value'
>>> print(test.name)
value
当您请求不在您的dict中的属性时,您需要调用超级类getattr。@DavidHeffernan像OP的示例这样的老式类是否有超类?@Aya不知道。如果没有,请使用新样式类。谁还会使用旧式类?@DavidHeffernan好吧,在标准Python库中仍然有很多旧式类,例如cgi.py
\uuuu getattr\uuu
仅在没有匹配其他查找规则的情况下用作备用,因此无需查找self,如果调用了\uuuu getattr\uuuu
,则已完成此操作。如果查找self.\u response['key']失败,只需提高AttributeError
。@Brunodesshuilliers看起来你是对的。奇怪。也许这在PythonV1.5的时代才是必要的。一个坏的惊喜的例子是:如果dict中有一个恰好是Python关键字的键,例如字符串'for'
,那么属性访问失败,并且没有优雅的方法来正确处理这种情况。整个想法从一开始就被打破了。另一方面,自动完成使得代码更高效,更不容易出错。如果可以预定义dict结构,这将非常有效。Javascript非常优雅。@QianChen Javascript可以优雅,也可以混乱(像大多数语言一样)。肯定是一团糟的是,试图将Python当作JavaScript(或任何两种其他语言)来使用。如果在给定的语言中有一种预期的方式来做某些事情,那么偏离这种方式只会带来痛苦。这是一种通过点符号访问数据结构的有趣方式,但它似乎与JSON或dict并不特别兼容。有些LIB在封面下使用命名元组,提供JSON和dict支持。尝试或Python >=3.6,从输入NealDube元组考虑<代码>也有一个很好的极小值,我也发布了。i、 e.访问myobj.subdct.subdct