我是python的新手,我希望我可以使用.
表示法来访问dict
的值。
假设我有test
这样的话:
>>> test = dict()
>>> test['name'] = 'value'
>>> print(test['name'])
value
但我希望我能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')
这有效!当我这样做时:
test.name // I get value.
但问题是,当我只打印test
时,我得到错误:
'Sorry no key matches'
为什么会这样?
答案 0 :(得分:65)
此功能已经exists in the standard libraries,因此我建议您只使用他们的课程。
>>> 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
等语句。
再次回到词典:
>>> vars(n)
{'key1': 'value1', 'key2': 'value2'}
dict中的键应为字符串identifiers,以便属性访问正常工作。
Python 3.3中添加了简单命名空间。对于该语言的旧版本,argparse.Namespace
具有类似的行为。
答案 1 :(得分:27)
我认为您对Javascript感到满意,并希望借用这种语法......我可以通过个人经验告诉您这不是一个好主意。
确实看起来不那么冗长和整洁;但从长远来看,它只是模糊不清。 Dicts是dicts,并试图使它们像具有属性的对象一样,可能会导致(坏)意外。
如果您需要操纵对象的字段,就好像它们是字典一样,您可以随时使用内部__dict__
属性,然后它显式清楚你在做什么。或者使用getattr(obj, 'key')
来考虑继承结构和类属性。
但是通过阅读你的例子,似乎你正在尝试不同的东西......因为点运算符已经在__dict__
属性中查找而没有任何额外的代码。
答案 2 :(得分:4)
您可以使用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)
答案 3 :(得分:4)
__getattr__
用作后备。当您尝试“打印”对象时,Python会查找__repr__
方法,并且由于您未在类中实现它,因此最终调用__getattr__
(是的,在Python方法中也是属性)。您不应该假设将调用哪个键 getattr ,最重要的是,__getattr__
必须引发一个AttributeError,如果它无法解析key
。
作为旁注:不要使用self.__dict__
进行普通属性访问,只需使用plain属性表示法:
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并且您不需要支持旧版本),那么您可以使用名称小组:http://docs.python.org/2/library/collections.html#collections.namedtuple
答案 4 :(得分:2)
使用__getattr__
时必须小心,因为它用于许多内置的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>
答案 5 :(得分:2)
您可以使用内置方法argparse.Namespace()
:
import argparse
args = argparse.Namespace()
args.name = 'value'
print(args.name)
# 'value'
您也可以通过 vars(args)
获取原始字典。
答案 6 :(得分:1)
我使用 dotted_dict
包:
>>> from dotted_dict import DottedDict
>>> test = DottedDict()
>>> test.name = 'value'
>>> print(test.name)
value
答案 7 :(得分:0)
在课程中添加__repr__()
方法,以便您可以自定义要在
print text
点击此处了解详情:http://www.diveintopython.net/object_oriented_framework/special_class_methods2.html
答案 8 :(得分:0)
除了this answer,还可以添加对嵌套字典的支持:
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
答案 9 :(得分:0)
对 this answer 稍加补充,您也可以支持列表:
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)
答案 10 :(得分:0)
这是一个使用嵌套项的简单、方便的点符号帮助示例:
def dict_get(data:dict, path:str, default = None):
pathList = re.split(r'\.', path, flags=re.IGNORECASE)
result = data
for key in pathList:
try:
key = int(key) if key.isnumeric() else key
result = result[key]
except:
result = default
break
return result
用法示例:
my_dict = {"test1": "str1", "nested_dict": {"test2": "str2"}, "nested_list": ["str3", {"test4": "str4"}]}
print(data_dict_get(my_dict, "test1"))
# str1
print(data_dict_get(my_dict, "nested_dict.test2"))
# str2
print(data_dict_get(my_dict, "nested_list.1.test4"))
# str4