如何在python中使用dict的点表示法?

如何在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

我对python非常陌生,我希望我可以使用
符号来访问
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