无法找到覆盖dict.iteritems(类)(Unable to find override for dict.iteritems(class))

编程入门 行业动态 更新时间:2024-10-24 08:30:42
无法找到覆盖dict.iteritems(类)(Unable to find override for dict.iteritems(class))

我有一个替换__iter__的类来隐藏多余的不需要的数据。 通过将iteritems设置为dict.iteritems或dict.items取决于python版本),我已将剩余的代码向后兼容,然后我可以调用iteritems(class_object) ,但它似乎不适用于我类。

用一个例子来解释会更容易:

class Test(dict): def __init__(self, some_dict): self.some_dict = some_dict super(self.__class__, self).__init__(self.some_dict) def __iter__(self): for k, v in self.some_dict.iteritems(): yield k, v['value'] test_dict = { 'a': {'value': 'what', 'hidden': 123}, 'b': {'value': 'test'} }

如果我做Test(test_dict).__iter__() ,那么它正确地返回{'a': 'what', 'b': 'test'}

如果我将iteritems = __iter__添加到类中,那么它在Test(test_dict).iteritems()

但是,无论我尝试做什么,执行dict.iteritems(Test(test_dict))默认为标准字典迭代,并返回{'a': {'hidden': 123, 'value': 'what'}, 'b': {'value': 'test'}}

我已经尝试了几个跟踪函数,但是他们没有足够深入地弄清楚发生了什么。

I've got a class that has replaced __iter__ to hide extra unneeded data. I've made the rest of my code backwards compatible by setting iteritems to either dict.iteritems or dict.items depending on the python version, and I can then call iteritems(class_object), but it doesn't seem to work well with my class.

It'll be easier to explain with an example:

class Test(dict): def __init__(self, some_dict): self.some_dict = some_dict super(self.__class__, self).__init__(self.some_dict) def __iter__(self): for k, v in self.some_dict.iteritems(): yield k, v['value'] test_dict = { 'a': {'value': 'what', 'hidden': 123}, 'b': {'value': 'test'} }

If I do Test(test_dict).__iter__(), then it correctly returns {'a': 'what', 'b': 'test'}

If I add iteritems = __iter__ to the class, then it also works when doing Test(test_dict).iteritems()

However, no matter what I try, doing dict.iteritems(Test(test_dict)) defaults to the standard dict iterating, and returns {'a': {'hidden': 123, 'value': 'what'}, 'b': {'value': 'test'}}

I've tried a couple of trace functions but they don't go deep enough to figure out what's going on.

最满意答案

dict.iteritems()方法直接进入了dict实现的内部数据结构。 你传入了一个dict的子类,这样就可以访问相同的数据结构。 您无法重写此行为。

不是说dict.iteritems()会使用__iter__ ; 后者产生 ,而不是键值对!

您应该iteritems不同的方式定义iteritems ; 给定Python 2的PY3布尔变量为False ,否则为True :

from operator import methodcaller iteritems = methodcaller('items' if PY3 else 'iteritems')

现在, iteritems(object)会根据需要转换为object.iteritems()或object.items() ,并始终调用正确的方法。

接下来,为了扩展字典行为,而不是子类化dict ,我会继承collections.MutableMapping (*)

from collections import MutableMapping class Test(MutableMapping): def __init__(self, some_dict): self.some_dict = some_dict.copy() def __getitem__(self, key): return self.some_dict[key] def __setitem__(self, key, value): self.some_dict[key] = value def __delitem__(self, key): del self.some_dict[key] def __len__(self): return len(self.some_dict) def __iter__(self): for k, v in self.some_dict.iteritems(): yield k, v['value']

这实现了dict提供的所有相同方法, 除了 copy和dict.fromkeys()类方法。

你可以从collections.UserDict()继承,它添加了这两个剩余的方法:

try: # Python 2 from UserDict import UserDict except ImportError: from collections import UserDict class Test(UserDict): def __iter__(self): for k, v in self.data.iteritems(): yield k, v['value']

在这种情况下只需要一个替代的__iter__实现。

无论哪种情况,您仍然无法在这些对象上使用dict.iteritems ,因为该方法只能用于实际的dict对象。


(*) collections.MutableMapping是该类的Python 2位置,官方Python 3位置是collections.abc.MutableMapping但是有一些别名支持Python 2兼容代码。

The dict.iteritems() method reaches straight into the internal data structures of the dict implementation. You passed in a subclass of dict so those same data structures are there for it to access. You can't override this behaviour.

Not that dict.iteritems() would ever use __iter__; the latter produces keys only, not key-value pairs!

You should instead define iteritems differently; given a PY3 boolean variable that is False for Python 2, True otherwise:

from operator import methodcaller iteritems = methodcaller('items' if PY3 else 'iteritems')

Now iteritems(object) is translated to object.iteritems() or object.items(), as needed, and the correct method is always called.

Next, to extend dictionary behaviour, instead of subclassing dict, I'd subclass collections.MutableMapping (*):

from collections import MutableMapping class Test(MutableMapping): def __init__(self, some_dict): self.some_dict = some_dict.copy() def __getitem__(self, key): return self.some_dict[key] def __setitem__(self, key, value): self.some_dict[key] = value def __delitem__(self, key): del self.some_dict[key] def __len__(self): return len(self.some_dict) def __iter__(self): for k, v in self.some_dict.iteritems(): yield k, v['value']

This implements all the same methods that dict provides, except for copy and the dict.fromkeys() class method.

You could instead inherit from collections.UserDict(), which adds those two remaining methods:

try: # Python 2 from UserDict import UserDict except ImportError: from collections import UserDict class Test(UserDict): def __iter__(self): for k, v in self.data.iteritems(): yield k, v['value']

Only an alternate __iter__ implementation is needed in that case.

In either case, you still can't use dict.iteritems on these objects, because that method can only work with actual dict objects.


(*) collections.MutableMapping is the Python 2 location of that class, the official Python 3 location is collections.abc.MutableMapping but there are aliases in place to support Python 2-compatible code.

更多推荐

本文发布于:2023-07-31 00:00:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1340328.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Unable   iteritems   dict   class   override

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!