Python 3引入了视图(参见this question)。他们也被反向移植到Python 2.7。我目前正在Python {2.7}应用程序中继承dict
(尽管目标是将其移植到Python 3)。我想知道是否 - 以及如何 - 我可以将.viewitems()
和类似函数子类化,使它们的行为与原始视图完全相同。
这是我的意图:我有这样的dictonary:
data = my_subclassed_dict
data["_internal"] = "internal_value"
data["key"] = "value"
list(data.keys()) == ["key"]
也就是说,我使用"_"
过滤所有统计信息。这到目前为止工作正常:对于迭代器我只是yield
,对于列表,我使用列表推导来过滤不需要的值。但是,这些项目与dict
之间没有联系(这很好,感觉就像一个字典)。但是,无论如何,这都不起作用:
keys = data.viewkeys()
"key" in keys
del data["key"]
"key" not in keys # This is False !
最后一部分不起作用,因为没有对原始键的引用,因此Python不会注意到。
那么:是否有简单方法来实现这一目标(无需重新实现所有逻辑!)?
这是一个更令人感兴趣的问题,因为我认为它不适用于我的情景。
答案 0 :(得分:2)
view
个对象基本上是“空”代理。他们指向原始字典。
不幸的是,当前的字典视图对象并不是真正可重用的。引自source code:
/* TODO(guido): The views objects are not complete: * support more set operations * support arbitrary mappings? - either these should be static or exported in dictobject.h - if public then they should probably be in builtins */
注意support arbitrary mappings
条目;这些对象不支持任意映射,我们也不能从Python代码创建新实例或子类:
>>> type({}.viewkeys())({})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'dict_keys' instances
>>> class MyView(type({}.viewkeys())): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
type 'dict_keys' is not an acceptable base type
您被迫创建自己的并实现视图对象支持的所有钩子:
class DictKeys(object):
def __init__(self, parent):
self.parent = parent
def __len__(self):
return len(self.parent)
def __contains__(self, key):
return key in self.parent
def __iter__(self):
return iter(self.parent)
等
原始对象实现的方法是:
>>> dir({}.viewkeys())
['__and__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__', '__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__']
__and__
,__or__
,__sub__
,__xor__
,__rand__
,__ror__
,__rsub__
和{{1} }方法为__rxor__
,&
和|
运算符实现覆盖以提供集合操作。
如果您在阅读C代码时相当安全,请查看view objects implementation以了解他们如何实施他们的方法。
答案 1 :(得分:0)
考虑在单独的dict中存储以下划线开头的任何键。您不必实施keys
,iterkeys
,viewitems
等,但您可能需要重新实施许多其他方法。