我想写一个容器类
data['a']
和类似属性的访问,例如data.a
;这是寻址的herecollections.OrderedDict
;这是针对here我把解决方案改为1。子类collections.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
带有失败注释的两行将导致以下错误:
^{pr2}$以及
D['c'] = 3
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/collections.py", line 58, in __setitem__
root = self.__root
AttributeError: 'mydict' object has no attribute '_OrderedDict__root'
有解决办法吗?__init__
函数可以修补吗?在
首先,如果你只是想让它正常工作,而不知道你的尝试有什么问题,那么在PyPI、ActiveState等上有多个“AttrDict”实现。搜索其中一个并查看其代码,或者只安装并使用它。在
这不是你想要的。我知道人们推荐它,但它有一些基本的主要问题。其中一个问题正是你所看到的。在
特别是,这意味着您现在已经丢失了所有现有的属性,包括
OrderedDict
本身使用的内部属性(例如,__root
您正在得到的错误)和附加到所有对象的特殊属性(比如__class__
)。在当您仅仅使用
dict
时,您至少在CPython中没有注意到这个问题,因为dict
是用C实现的,它需要操作的特殊成员存储在一个C结构中,而不是存储在__dict__
中,因此您不会丢失它们。但是对于用Python实现的任何需要特殊成员的类,问题就变得显而易见了。在Python对customizing attribute access有特殊的方法。您要做的是实现这些方法:
但是,在这种情况下,即使这样也不能解决所有问题,因为当
OrderedDict
中的代码试图使用__root
时,仍然会调用重写!要解决这个问题,您只需要将这些方法中的一些调用转发到dict,而不需要将所有调用转发到dict。在而“一些”是复杂的,很难得到正确的答案。更简单的解决方案是只封装并委托给
^{pr2}$OrderedDict
,而不是继承:或者,更简单地说,只需使用OrderedDict作为}来完成。在
__dict__
-这是元类的范例,但是如果您想快速地完成这项工作,可以使用__init__
或{后一种解决方案只是使您成为一个普通对象,其属性恰好是有序的,而不是映射。但是转发映射方法也很容易。实现}转发到{},并从{a2}继承以填充API的其余部分。在
__getitem__
、__setitem__
、__delitem__
、__iter__
、和{现在,如果您回过头去查看PyPI上的“AttrDict”并单击实现,您将看到这正是它们所做的:它们将}转发给OrderedDict的{},依此类推。在
__getattr__
和{相关问题 更多 >
编程相关推荐