Home > Blockchain >  Why does Python act like my dict is a list?
Why does Python act like my dict is a list?

Time:06-13

Edit

Thanks all! Changed the _sort function and now it works.

Original post

I'm trying to create a sorted dict class as a way to mess around with dunder methods. I know collections.OrderedDict exists.

When I try to overload __getitem__ or __setitem__, Python acts as if I am trying to index a list with a string key. Here is my code for the class:

class SortedDict:
    def __init__(self, **kwargs):
        self.map = dict(kwargs)
        self._sort()

    def __str__(self):
        return str(self.map)

    def __getitem__(self, key):
        return self.map[key]

    def __setitem__(self, name, value):
        self.map[name] = value

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

    def add(self, **kwargs):
        for key in kwargs:
            self.map[key] = kwargs[key]
        self._sort()

        indices = dict()
        for key in kwargs.keys():
            indices[key] = self.index(key)
        return indices

    def remove(self, *args):
        for key in args:
            self.map.pop(key)

    def index(self, key: str):
        keys = list()
        for dict_key in self.map.keys():
            keys.append(dict_key)
        return keys.index(key)

    def contains(self, key: str):
        return key in self.map

    def _sort(self):
        self.map = sorted(self.map)

When I execute the following code to test __getitem__:

from sorted_dict import SortedDict
test_dict= SortedDict(test1=1, test2=2, a=2, b=3)
print(test_dict['test1'])

I get this error:

Traceback (most recent call last):
  File "c:\Users\Chris\Desktop\Code\DMC2\mapping_editor\tree.py", line 16, in <module>
    print(test_dict['test1'])
  File "c:\Users\Chris\Desktop\Code\DMC2\mapping_editor\sorted_dict.py", line 11, in __getitem__
    return self.map[key]
TypeError: list indices must be integers or slices, not str

I get a similar error when trying to use __setitem__. I am using VS code, and when I hover my cursor over self.map in either of those functions the type is shown as dict[str, Any] | list[str]. If I print the type of self.map in either of the functions, it prints <class 'list'>, but when I print the class of self.map in the constructor it prints as <class 'dict'>, which is what I would expect. When I print self.map in the __setitem__ or __getitem__ functions it prints as a list of the keys, but in the constructor it prints as a dictionary would. What am I missing?

CodePudding user response:

As mentioned in the comments sorted(self.map) returns a list of the sorted map keys. To get a sorted dictionary you can do

def _sort(self):
    self.map = dict(sorted(self.map.items()))

This will give you {'a': 2, 'b': 3, 'test1': 1, 'test2': 2}.

  • Related