Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中访问类似属性的OrderedDict键_Python_Dictionary - Fatal编程技术网

在Python中访问类似属性的OrderedDict键

在Python中访问类似属性的OrderedDict键,python,dictionary,Python,Dictionary,我想写一个容器类 允许索引(字典样式),例如数据['a']和类似属性的访问,例如数据。a;这是针对 保留添加条目的顺序,例如通过子类化集合。OrderedDict;这是针对 我将解决方案改为1。子类化集合。OrderedDict而不是dict,但它不起作用;见下文 from collections import OrderedDict class mydict(OrderedDict): def __init__(self, *args, **kwargs): supe

我想写一个容器类

  • 允许索引(字典样式),例如
    数据['a']
    和类似属性的访问,例如
    数据。a
    ;这是针对
  • 保留添加条目的顺序,例如通过子类化
    集合。OrderedDict
    ;这是针对
  • 我将解决方案改为1。子类化
    集合。OrderedDict
    而不是
    dict
    ,但它不起作用;见下文

    from collections import OrderedDict
    
    class mydict(OrderedDict):
        def __init__(self, *args, **kwargs):
            super(mydict, self).__init__(*args, **kwargs)
            self.__dict__ = self
    
    D = mydict(a=1, b=2)
    
    #D['c'] = 3 # fails
    D.d    = 4
    
    #print D    # fails
    
    带有故障注释的两行会导致以下错误:

        print D
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 176, in __repr__
        return '%s(%r)' % (self.__class__.__name__, self.items())
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 113, in items
        return [(key, self[key]) for key in self]
      File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 76, in __iter__
        root = self.__root
    AttributeError: 'struct' object has no attribute '_OrderedDict__root'
    


    有解决办法吗?
    \uuuuu init\uuuuu
    函数是否可以修补?

    首先,如果您只是想让它正常工作,而不了解您的尝试有什么问题,在PyPI、ActiveState等上有多个“AttrDict”实现。搜索一个并查看其代码,或者安装并使用它


    那不是你想要的。我知道人们推荐它,但它有一些基本的主要问题。其中一个问题正是你所看到的

    特别是,这意味着您现在已经丢失了所有现有属性,包括
    OrderedDict
    本身使用的内部属性(如您收到错误的
    \uuuuuuuroot
    )和附加到所有对象的特殊属性(如
    \uuuuuuu class

    当您仅仅使用
    dict
    时,您至少在CPython中没有注意到这个问题,因为
    dict
    是在C中实现的,它需要操作的特殊成员存储在C结构中,而不是存储在
    \u dict\u
    中,所以您不会丢失它们。但是对于任何用Python实现的需要任何特殊成员的类,问题变得显而易见


    Python有专门的方法来处理。您要做的是实现这些方法:

    class AttrDict(OrderedDict):
        def __getattr__(self, name):
            return self[name]
        def __setattr__(self, name, value):
            self[name] = value
        def __delattr__(self, name):
            del self[name]
    

    但是,在这种情况下,即使这样也不能适用于所有情况,因为当
    OrderedDict
    中的代码尝试使用
    \uuuu root
    时,仍然会调用覆盖!要解决这个问题,您只需要将这些方法中的一些调用转发给dict,而不是所有调用

    “一些”是复杂的,很难正确理解。一个简单得多的解决方案是只封装并委托给
    OrderedICT
    ,而不是继承:

    class AttrDict(object):
        def __init__(self, *args, **kwargs):
            self._od = OrderedDict(*args, **kwargs)
        def __getattr__(self, name):
            return self._od[name]
        def __setattr__(self, name, value):
            if name == '_od':
                self.__dict__['_od'] = value
            else:
                self._od[name] = value
        def __delattr__(self, name):
            del self._od[name]
    
    或者,更简单地说,只需使用OrderedDict作为您的
    \uuuu dict\uuuuu
    ——这是元类的范例,但如果您想快速而不费力地完成它,您可以在
    \uuuuu init\uuuuuu
    \uuuu new\uuuuu
    中完成


    后一种解决方案只是将您变成一个普通对象,其属性恰好是有序的,而不是映射。但是,转发映射方法也很容易。实现
    \uuu getitem\uuuuuuuuuuuuu
    \uuuuuu setitem\uuuuuuuuu
    \uuuuuuu iter\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
    、和
    \uuuuuuuu len\uuuuuuuuuucode>以转发到
    自身,并从继承以填充API的其余部分


    现在,如果你回过头来在PyPI上查找“AttrDict”并点击实现,你会看到它们都是这样做的:它们将
    \uuuu getattr\uuuu
    \uu getitem\uuuuu
    转发给一个OrderedDict的
    \uu getitem\uuuu
    ,等等。

    我早就看到了实现
    AttrDict的两种方法,他们认为这是等效的,但因为简洁而选择了错误的。谢谢你强调了区别和所有的细节。@wap26:这确实是一个黑客行为,我认为人们不应该把它教给那些不理解它为什么有效的人。(如果您确实了解它是如何工作的,并且您也了解描述符,那么您可能可以自己找到解决方法……以及一种使更干净的版本更好的方法。)
    
    class AttrDict(object):
        def __init__(self, *args, **kwargs):
            self._od = OrderedDict(*args, **kwargs)
        def __getattr__(self, name):
            return self._od[name]
        def __setattr__(self, name, value):
            if name == '_od':
                self.__dict__['_od'] = value
            else:
                self._od[name] = value
        def __delattr__(self, name):
            del self._od[name]