Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom iteration behavior in dict subclass

I have a class that is a subclass of standard dict:

class Result(dict):

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

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

    def attrs(self):
        return self.__getitem__('_attrs')

A sample representation in this object:

{
    '_attrs': {'id': 1},
    'description': 'testtest',
    'calories': 1234,
    '_content': 'Sample content',
    'name': 'qwerty',
    'price': 12390
}

I want my class to skip records with underscored keys while iteration.

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

'description'
'calories'
'name'
'price'

How can I achieve that?

UPDATE: Besides of correct answer I have also overrided keys() and items() methods to hide underscore keys even if this methods will be used in iteration:

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']]
like image 896
bbrodriges Avatar asked Feb 04 '16 14:02

bbrodriges


People also ask

How do I make custom dictionaries in Python?

Specifically, you may be interested in making custom dictionaries with modified behavior, new functionalities, or both. In Python, you can do this by inheriting from an abstract base class, by subclassing the built-in dict class directly, or by inheriting from UserDict. Create dictionary-like classes by inheriting from the built-in dict class

Which collection should I inherit to make a custom Dict?

If you’re making a variation of list or dict and need to customize just a little bit of core functionality, consider inheriting from collections.UserList or collections.UserDict. In general, if you’re making something custom, you’ll often want to reach for the abstract base classes in collections.abc .

What's the difference between Dict and abstract base classes in Python?

Unlike dict, these update and setdefault methods will call our __setitem__ method and the pop and clear methods will call our __delitem__ method. Abstract base classes might make you think we’re leaving the wonderful land of Python duck typing behind for some sort of strongly-typed OOP land. But abstract base classes actually enhance duck typing.

Why can't I subclass built-in types in Python?

This is indeed a really helpful post! I think an important contributing factor why subclassing built-in types is so unsatisfying is that originally python didn't support subclassing built-in types at all!


1 Answers

Just implement __iter__. It's important to use .keys(), in order to avoid infinite recursion:

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

Then it will be skipped in iteration:

>>> r=Result({1:1,"_foo":2, "bar":3})
>>> for item in r:
...     print(item)
...
1
bar
like image 69
L3viathan Avatar answered Sep 30 '22 19:09

L3viathan