dict子类中的自定义迭代行为

bbr*_*ges 4 python python-3.x

我有一个类是标准dict的子类:

class Result(dict):

    """ Dict-like object with special methods """

    def content(self):
        return self.__getitem__('_content')

    def attrs(self):
        return self.__getitem__('_attrs')
Run Code Online (Sandbox Code Playgroud)

此对象中的示例表示:

{
    '_attrs': {'id': 1},
    'description': 'testtest',
    'calories': 1234,
    '_content': 'Sample content',
    'name': 'qwerty',
    'price': 12390
}
Run Code Online (Sandbox Code Playgroud)

我希望我的类在迭代时跳过带有下划线键的记录.

# data is Result()
>>> for item in data:
>>>    print(item)

'description'
'calories'
'name'
'price'
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

更新: 除了正确的答案,我还覆盖了keys()和items()方法来隐藏下划线键,即使这些方法将在迭代中使用:

def __iter__(self):
    for key in self.keys():
        yield key

def keys(self):
    return [key for key in super().keys() if key not in ['_attrs', '_content']]

def items(self):
    return [(key, value) for key, value in super().items() if key not in ['_attrs', '_content']]
Run Code Online (Sandbox Code Playgroud)

L3v*_*han 6

刚刚实施__iter__.使用它很重要.keys(),以避免无限递归:

class Result(dict):
    def __iter__(self):
        for key in self.keys():
            if not(isinstance(key, str) and key.startswith("_")):
                yield key
Run Code Online (Sandbox Code Playgroud)

然后在迭代中跳过它:

>>> r=Result({1:1,"_foo":2, "bar":3})
>>> for item in r:
...     print(item)
...
1
bar
Run Code Online (Sandbox Code Playgroud)