【问题标题】:Using an ordered dict as object dictionary in python在python中使用有序字典作为对象字典
【发布时间】:2010-10-02 02:06:49
【问题描述】:

我不知道为什么这不起作用:

我正在使用来自PEP 372 的odict 类,但我想将其用作__dict__ 成员,即:

class Bag(object):
    def __init__(self):
        self.__dict__ = odict()

但由于某种原因,我得到了奇怪的结果。这有效:

>>> b = Bag()
>>> b.apple = 1
>>> b.apple
1
>>> b.banana = 2
>>> b.banana
2

但尝试访问实际字典不起作用:

>>> b.__dict__.items()
[]
>>> b.__dict__
odict.odict([])

而且变得更奇怪了:

>>> b.__dict__['tomato'] = 3
>>> b.tomato
3
>>> b.__dict__
odict.odict([('tomato', 3)])

我觉得自己很愚蠢。你能帮帮我吗?

【问题讨论】:

    标签: python ordereddictionary


    【解决方案1】:

    sykora 的答案中的所有内容都是正确的。这是具有以下改进的更新解决方案:

    1. 即使在直接访问a.__dict__ 的特殊情况下也能正常工作
    2. 支持copy.copy()
    3. 支持== 和!= 运算符
    4. 使用 Python 2.7 中的 collections.OrderedDict。

    ...

    from collections import OrderedDict
    
    class OrderedNamespace(object):
        def __init__(self):
            super(OrderedNamespace, self).__setattr__( '_odict', OrderedDict() )
    
        def __getattr__(self, key):
            odict = super(OrderedNamespace, self).__getattribute__('_odict')
            if key in odict:
                return odict[key]
            return super(OrderedNamespace, self).__getattribute__(key)
    
        def __setattr__(self, key, val):
            self._odict[key] = val
    
        @property
        def __dict__(self):
            return self._odict
    
        def __setstate__(self, state): # Support copy.copy
            super(OrderedNamespace, self).__setattr__( '_odict', OrderedDict() )
            self._odict.update( state )
    
        def __eq__(self, other):
            return self.__dict__ == other.__dict__
    
        def __ne__(self, other):
            return not self.__eq__(other)
    

    【讨论】:

      【解决方案2】:

      如果您正在寻找一个对 OrderedDict 具有属性访问权限的库,orderedattrdict 包可以提供此功能。

      >>> from orderedattrdict import AttrDict
      >>> conf = AttrDict()
      >>> conf['z'] = 1
      >>> assert conf.z == 1
      >>> conf.y = 2
      >>> assert conf['y'] == 2
      >>> conf.x = 3
      >>> assert conf.keys() == ['z', 'y', 'x']
      

      披露:我创作了这个库。认为它可能对未来的搜索者有所帮助。

      【讨论】:

        【解决方案3】:

        我能找到的与您的问题最接近的答案是http://mail.python.org/pipermail/python-bugs-list/2006-April/033155.html。

        基本上,如果__dict__ 不是实际的dict(),那么它会被忽略,并且属性查找失败。

        替代方法是使用 odict 作为成员,并相应地覆盖 getitem 和 setitem 方法。

        >>> class A(object) :
        ...     def __init__(self) :
        ...             self.__dict__['_odict'] = odict()
        ...     def __getattr__(self, value) :
        ...             return self.__dict__['_odict'][value]
        ...     def __setattr__(self, key, value) :
        ...             self.__dict__['_odict'][key] = value
        ... 
        >>> a = A()
        >>> a
        <__main__.A object at 0xb7bce34c>
        >>> a.x = 1
        >>> a.x
        1
        >>> a.y = 2
        >>> a.y
        2
        >>> a.odict
        odict.odict([('x', 1), ('y', 2)])
        

        【讨论】:

        • 哇,没想到这是一个真正的python错误。谢谢!
        猜你喜欢
        • 2021-12-17
        • 1970-01-01
        • 1970-01-01
        • 2023-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-29
        相关资源
        最近更新 更多