代码之家  ›  专栏  ›  技术社区  ›  Peter

找不到dict.iteritems(类)的重写

  •  0
  • Peter  · 技术社区  · 8 年前

    我已经换了一个班 __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)) 默认为标准dict迭代,并返回 {'a': {'hidden': 123, 'value': 'what'}, 'b': {'value': 'test'}}

    我试过几个跟踪函数,但它们不够深入,无法找出发生了什么。

    1 回复  |  直到 8 年前
        1
  •  1
  •   Martijn Pieters    8 年前

    这个 dict.iteritems() 方法直接进入 dict 实施。你传入了 双关语 所以这些相同的数据结构都在那里供它访问。你不能无视这种行为。

    不是那个 dict.iteritems() 会用到的 __iter__ ;后者产生 只有密钥 ,不是键值对!

    你应该定义 iteritems 不同的;给予 PY3 布尔变量,即 False 对于python 2, True 否则:

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

    现在 iteritems(object) 翻译成 object.iteritems() object.items() ,并且始终调用正确的方法。

    接下来,扩展字典行为,而不是子类化 双关语 ,我将子类 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']
    

    这实现了所有与 双关语 提供, 除了 对于 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']
    

    只有替补队员 γ迭代 在这种情况下需要实施。

    不管怎样,你 仍然不能使用 dict.iteritems 在这些物体上 ,因为该方法只能与实际的 双关语 物体。


    (*) 集合.mutableMapping 是该类的Python2位置,正式的Python3位置是 collections.abc.MutableMapping 但是也有一些别名来支持与python 2兼容的代码。