Chris J Harris
Chris J Harris

Reputation: 1851

Avoiding recursion when setting exceptions

I'm trying to do something relatively simple - to take the OrderedDict class and give it the ability to look up values based on integers or slices. So if I have the following

from collections import OrderedDict

test_dict = OrderedDict()
test_dict['a'] = 'value a'
test_dict['b'] = 'value b'
test_dict['c'] = 'value c'

test_dict[:2]

It would ideally give the result

['value a','value b']

To do this, I'm trying to subclass OrderedDict and then over-ride its getitem method. What I have is the following:

class indexed_dict(OrderedDict):
    def __init__(self):
        pass

    def __getitem__(self, key):
        try:
            return list(self)[key]
        except TypeError: # Because we've entered a number instead of a key
            return self[key]

The trouble with this is that if you try to use it normally - say, test_indexed_dict['a'] - the interpreter starts recursing away, presumably because the except clause asks it to run getitem again. Is there a better method of error handling which doesn't create this problem?

Thanks in advance for any help.

Upvotes: 1

Views: 46

Answers (3)

U13-Forward
U13-Forward

Reputation: 71600

In addition to @Aran_Fey's answer, you need to check values in first try , so function would be:

def __getitem__(self, key):
    try:
        return list(self.values())[key]
    except TypeError:
        return super().__getitem__(key)

And whole class:

class IndexedDict(OrderedDict):
    def __init__(self):
        pass

    def __getitem__(self, key):
        try:
            return list(self.values())[key]
        except TypeError:
            return super().__getitem__(key)

Nothing can be added to @Netwave's answer.

Upvotes: 1

Netwave
Netwave

Reputation: 42746

You can check the type of key, and also just return the slice over the values of the dictionary:

from collections import OrderedDict
class IndexedDict(OrderedDict):
    def __init__(self):
        pass

    def __getitem__(self, key):
        if type(key) is slice:
          return list(self.values())[key]
        else:
            return super().__getitem__(key)

Here you have a live example

Upvotes: 1

Aran-Fey
Aran-Fey

Reputation: 43246

When you do self[key], you're calling your own __getitem__ method again. That causes endless recursion. What you want to do is to call your parent class's __getitem__ method:

def __getitem__(self, key):
    try:
        return list(self)[key]
    except TypeError: # Because we've entered a number instead of a key
        return super().__getitem__(key)

Upvotes: 1

Related Questions