Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over `dict` in class like if just referring to `dict`?

In a defined object some values are kept in a dict, and I want to iterate over the contents in that dict as when referring to a plain dict, thus with directly access using [], and loop using e.g. .items(). Code structure is:

class Klass:

    def __init__(self, values):
        self.values = values
        self.more = None

    def __getitem__(self, name):
        return self.values[name]

    def __iter__(self):
        pass  # TBD[How to make this ?]

d = {'alfa': 1, 'bravo': 2, 'charlie': 3}

k = Klass(d)

for key in k:
    print(key)  # Expected to print keys from self.values 

for (key, value) in k.items():
    print(key, value)  # Expected to print key and value from self.values 

for key in k.keys():
    print(key)  # Expected to print key from self.values 

for value in k.values():
    print(value)  # Expected to print value from self.values 

How to write the __iter__ and, other required methods, so this kind of access is possible through an instance of Klass?

like image 669
EquipDev Avatar asked Mar 13 '15 13:03

EquipDev


2 Answers

You'll have to implement the .keys(), .values() and .items() methods yourself; together with __iter__ they can all delegate the actual work to the self.values() dictionary:

class Klass:
    def __init__(self, values):
        self._values = values
        self.more = None

    def __getitem__(self, name):
        return self._values[name]

    def __iter__(self):
        return iter(self._values)

    def keys(self):
        return self._values.keys()

    def items(self):
        return self._values.items()

    def values(self):
        return self._values.values()

I renamed the attribute to avoid masking the .values() method.

The easiest way to delegate __iter__ to iteration over the dictionary (by key) is to use the iter() function to get an iterator for the dictionary object.

To be explicit: __iter__ plays no role in how .keys(), .values() and .items() are handled; the latter are just more methods.

like image 125
Martijn Pieters Avatar answered Nov 04 '22 07:11

Martijn Pieters


    class Klass(dict):
        def __init__(self, *arg, **kw):
            super(Klass, self).__init__(*arg, **kw)
            self.choosebettername = super(Klass, self).keys()

        def __iter__(self):
            return iter(self.choosebettername)

        def keys(self):
            return self.choosebettername

        def itervalues(self):
            return (self[key] for key in self)


    d = {'alfa': 1, 'bravo': 2, 'charlie': 3}

    k = Klass(d)

    for key in k:
        print(key)  # Expected to print keys from self.values 

    for (key, value) in k.items():
        print(key, value)  # Expected to print key and value from self.values 

    for key in k.keys():
        print(key)  # Expected to print key from self.values 

    print(k.values())

    for value in k.values():
        print(value)  # Expected to print value from self.values 
like image 42
Pyglouthon Avatar answered Nov 04 '22 08:11

Pyglouthon