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'
Related videos on Youtube
Author by
zjm1126
Updated on July 08, 2022Comments
-
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 about 14 yearsany simple way ??
-
Matti Virkkunen about 14 yearsIf you want a one-liner, put that into a small helper function.
-
zoli2k about 14 yearsYou should define the exception for
except:
. For example your exception is also triggered when variablea
is not defined. -
Eli Bendersky about 14 years@Goose: empty
except
is evil. It's far better to sayexcept IndexError
-
Eli Bendersky about 14 years@zjm: this is a simple way
-
Vlad the Impala about 14 years@shakov, @Eli Bendersky: you're right. Fixed.
-
kennytm about 14 yearsIs it necessary to span into 3 answers?
-
Eli Bendersky about 14 years@Thomas: IMHO it's inelegant, and the all-catching
except
is worrisome -
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 about 14 yearsThere'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 about 14 years@zjm1126: there's a shorter way if you can use a dict instead of a list. See my answer.
-
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 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 about 14 yearsYou could get away with it if you do
def get_at(array, index, default): try: return array[index] except IndexError: return default
-
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 almost 11 yearswas using it, good to see reliability confirmed. I tend to avoid trying (and catching) as much as possible.
-
Sam Stoelinga over 10 yearsI 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 about 10 yearsOld 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 almost 10 yearsYour 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 almost 10 yearsShouldn't it be "ValueError"?
-
Keyur Padalia almost 10 yearsNo, what makes you think that?
-
froggythefrog over 9 yearsOkay, so I like the lack of verbosity. Could you explain the syntax a little?
-
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. Ifa
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 returneda[4]
if there was such an element` -
Alexander Oh over 8 yearsan interesting way to achieve this. a bit on the unreadable side.
-
David Vartanian almost 8 yearsThis 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 almost 8 yearsUsing exceptions just to return default values isn't a good practice even though this is an easy (not simple) way.
-
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 over 7 yearsWhy does your first answer have additional commas? Playing in the python interpreter:
b,=a[4:] or 'sss',
is the same asb=a[4:] or 'sss'
-
Carson Ip over 7 years@north.mister no. try an
a
with 6 elements, you'll get 2 elements inb
. -
Eric almost 7 yearsTotally agree, exceptions should be reserved for logic/algorithm rather than datastructures/content.
-
Roy over 6 yearsI think instead of depending on the length of the input list, we can do
b, = a[-1:] or ['default value']
-
Laizer about 6 yearswhy avoid try/catch?
-
Toskan over 5 yearsso ugggly... really? no easy way?
-
cowbert over 5 yearsThe 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 over 5 yearsI love the way to use dicts there. Thanks!
-
GenuinePlaceholder over 5 yearsNote: 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 over 4 yearsA shorter one for golfers:
b=[*a[4:],'sss'][0]
-
yo' over 3 years
4 in a
asks whether4
is in the list as a value, not a key! -
Michael Ekoka about 3 yearsThis 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 about 3 yearsbecareful with the dicts method, the get index must be a number, not a string!