Getting a default value on index out of range in Python

105,356

Solution 1

In the Python spirit of "ask for forgiveness, not permission", here's one way:

try:
    b = a[4]
except IndexError:
    b = 'sss'

Solution 2

In the non-Python spirit of "ask for permission, not forgiveness", here's another way:

b = a[4] if len(a) > 4 else 'sss'

Solution 3

In the Python spirit of beautiful is better than ugly

Code golf method, using slice and unpacking (not sure if this was valid 4 years ago, but it is in python 2.7 + 3.3)

b,=a[4:5] or ['sss']

Nicer than a wrapper function or try-catch IMHO, but intimidating for beginners.

using slicing without unpacking:

b = a[4] if a[4:] else 'sss'

or, if you have to do this often, and don't mind making a dictionary

d = dict(enumerate(a))
b=d.get(4,'sss')

Solution 4

another way:

b = (a[4:]+['sss'])[0]

Solution 5

You could create your own list-class:

class MyList(list):
    def get(self, index, default=None):
        return self[index] if len(self) > index else default

You can use it like this:

>>> l = MyList(['a', 'b', 'c'])
>>> l.get(1)
'b'
>>> l.get(9, 'no')
'no'
Share:
105,356

Related videos on Youtube

zjm1126
Author by

zjm1126

Updated on July 08, 2022

Comments

  • zjm1126
    zjm1126 almost 2 years
    a=['123','2',4]
    b=a[4] or 'sss'
    print b
    

    I want to get a default value when the list index is out of range (here: 'sss').

    How can I do this?

  • zjm1126
    zjm1126 about 14 years
    any simple way ??
  • Matti Virkkunen
    Matti Virkkunen about 14 years
    If you want a one-liner, put that into a small helper function.
  • zoli2k
    zoli2k about 14 years
    You should define the exception for except:. For example your exception is also triggered when variable a is not defined.
  • Eli Bendersky
    Eli Bendersky about 14 years
    @Goose: empty except is evil. It's far better to say except IndexError
  • Eli Bendersky
    Eli Bendersky about 14 years
    @zjm: this is a simple way
  • Vlad the Impala
    Vlad the Impala about 14 years
    @shakov, @Eli Bendersky: you're right. Fixed.
  • kennytm
    kennytm about 14 years
    Is it necessary to span into 3 answers?
  • Eli Bendersky
    Eli Bendersky about 14 years
    @Thomas: IMHO it's inelegant, and the all-catching except is worrisome
  • Keyur Padalia
    Keyur Padalia about 14 years
    @KennyTM: They are three different options. I figured, this way the best answer could be voted to the top and the crappy ones disappear into oblivion. It was not intended as rep-baiting, and is actually accepted practice: meta.stackexchange.com/questions/21761/…
  • Keyur Padalia
    Keyur Padalia about 14 years
    There's a discussion on the mailing list about a construct like this: mail.python.org/pipermail/python-dev/2009-August/091039.html
  • Vlad the Impala
    Vlad the Impala about 14 years
    @zjm1126: there's a shorter way if you can use a dict instead of a list. See my answer.
  • Alex Martelli
    Alex Martelli about 14 years
    mylist[-1] should just get the last element, but your "asking permission" get_at code doesn't behave like that. This shows one of the many reasons "asking permission" is just the wrong philosophy: what you're checking might not match what the system would do. I.e., not only are you systematically trying to duplicate work the system does for you, but you can easily get that extra, duplicated work wrong. "asking forgiveness" is much better.
  • Konrad Rudolph
    Konrad Rudolph about 14 years
    @Alex: good catch, didn’t think of that. Python’s poweful list slices syntax makes this slightly more complicated … however, I don’t agree with your extrapolation from this special case that “asking forgiveness” in general is good. I’m of course biased since I’m a huge proponent of static typing. But anyway, that’s just the wrong conclusion. A better conclusion would be that my requirement analysis was insufficient (and perhaps that there’s no good way to get the internal behaviour in a modifiable way without either code duplication or error triggering. Which points to a bad API).
  • Esteban Küber
    Esteban Küber about 14 years
    You could get away with it if you do def get_at(array, index, default): try: return array[index] except IndexError: return default
  • Konrad Rudolph
    Konrad Rudolph about 14 years
    @voyager: I’m aware of that. But as I said in the very first sentence, I’m opposed to deliberately triggering exceptions. I prefer explicitness over implicitness since it reduces sources of confusion (and hence errors) and this means keeping tab on what my methods can and cannot do.
  • Thiago Macedo
    Thiago Macedo almost 11 years
    was using it, good to see reliability confirmed. I tend to avoid trying (and catching) as much as possible.
  • Sam Stoelinga
    Sam Stoelinga over 10 years
    I would like to see the .get method of dicts also in lists, that when you use get and it doesn't exist it just returns None by default.
  • Etse
    Etse about 10 years
    Old answer, but still. Python is one of the few languages where exceptions is seen on as a good thing. It is often used for flow-control where it creates readability.
  • Robert Siemer
    Robert Siemer almost 10 years
    Your first example doesn’t work if the list is longer than 5 elements. And going with a[4:5] is not nice any more...
  • j_c
    j_c almost 10 years
    Shouldn't it be "ValueError"?
  • Keyur Padalia
    Keyur Padalia almost 10 years
    No, what makes you think that?
  • froggythefrog
    froggythefrog over 9 years
    Okay, so I like the lack of verbosity. Could you explain the syntax a little?
  • vlad-ardelean
    vlad-ardelean about 9 years
    a[4:] creates a list of elements, from (including) index 4. This results in an empty list. [1, 2, 3][999:] == [] It's how the slicing operation works. If a was ['123', '2', 4, 5, 6], it would return [5, 6] . He then adds the element 'sss', creating a new list, which is ['sss'] in this case. The final step [0] just takes the first element, thus returning 'sss', but would have returned a[4] if there was such an element`
  • Alexander Oh
    Alexander Oh over 8 years
    an interesting way to achieve this. a bit on the unreadable side.
  • David Vartanian
    David Vartanian almost 8 years
    This is the only way it works at least in Python 3.5. For some reason calling a[4] if 4 in a else 'default value' returns always the default value. But it's very interesting that slicings return always a list (even empty). Thanks Alex!
  • David Vartanian
    David Vartanian almost 8 years
    Using exceptions just to return default values isn't a good practice even though this is an easy (not simple) way.
  • underscore_d
    underscore_d over 7 years
    using splicing without unpacking is what works for me, as otherwise, the returned element was a list of size 1, not a scalar.
  • north.mister
    north.mister over 7 years
    Why does your first answer have additional commas? Playing in the python interpreter: b,=a[4:] or 'sss', is the same as b=a[4:] or 'sss'
  • Carson Ip
    Carson Ip over 7 years
    @north.mister no. try an a with 6 elements, you'll get 2 elements in b.
  • Eric
    Eric almost 7 years
    Totally agree, exceptions should be reserved for logic/algorithm rather than datastructures/content.
  • Roy
    Roy over 6 years
    I think instead of depending on the length of the input list, we can do b, = a[-1:] or ['default value']
  • Laizer
    Laizer about 6 years
    why avoid try/catch?
  • Toskan
    Toskan over 5 years
    so ugggly... really? no easy way?
  • cowbert
    cowbert over 5 years
    The only technical use-case to optimize against raising exception in Python is when the happypath results in the exception being raised. (in example, if len(a) is only rarely > 4, then it's cheaper to use if/then. ). If the happypath is that len(a) > 4, then the only real reason to use the above is shorter code (at the risk of worse readability), but then maep's answer using slices is even shorter...
  • amonowy
    amonowy over 5 years
    I love the way to use dicts there. Thanks!
  • GenuinePlaceholder
    GenuinePlaceholder over 5 years
    Note: this doesn't work for negative indexes, because in python negative indexes just give you the element which is the absolute value from the back
  • mabel
    mabel over 4 years
    A shorter one for golfers: b=[*a[4:],'sss'][0]
  • yo'
    yo' over 3 years
    4 in a asks whether 4 is in the list as a value, not a key!
  • Michael Ekoka
    Michael Ekoka about 3 years
    This is not the simple way, but it's the pythonic way. I don't think it does as good a job of expressing the simple notion "return default value if item not in list" as a dict does with get(key, default_value). I also fail to understand what makes the list so particular that a similar abstraction is taboo. Everybody has to come with their own lambda preamble. To me this looks like a language oversight perpetually excused due to traditionalism.
  • anthony
    anthony about 3 years
    becareful with the dicts method, the get index must be a number, not a string!