Can't get around "IndexError: list index out of range"

MonkeeSage MonkeeSage at gmail.com
Sun Oct 8 20:32:10 CEST 2006


On Oct 8, 5:57 am, Steven D'Aprano
<s... at REMOVE.THIS.cybersource.com.au> wrote:
> No, *less* often. That's the point -- it is fairly common for people to
> want dictionary lookup to return a default value, but quite rare for them
> to want sequence lookup to return a default value. A sequence with a
> default value would be, in some sense, equivalent to an infinite list:

Ah, yes. Infinite dictionaries are much better! I guess you could think
of it like providing a infinitely indexed list (or infinitely keyed
dict), but a better way to think of it is as providing a
non-terminating exception where the default value is the exceptional
case. And I don't see why it would be so rare to do something like:

if sys.argv.get(1): ...

With list.has_index() / get(), the following (pretty common I think)
idiom:

try:
  data = some_unknown_seq[2]
except IndexError:
  data = None
if data: ...

Can become:

data = some_unknown_seq.get(2)
if data: ...

Perhaps list.get() wouldn't be used as often as dict.get(), but it
would be used a fair amount I think. Looking at the standard library
(2.5 source), I find 30 places where "except IndexError" appears, and
two places where a comment says that some method "raises IndexError" on
some condition. I haven't looked at the context of them, but I'd wager
that many of them would benefit from list.has_index() and / or get().
Here is my script to search the libs:

import os, re
found = {}
for path, dirs, files in os.walk('./Lib'):
  for afile in files:
    afile = open(os.path.join(path, afile))
    lines = afile.readlines()
    afile.close()
    for line in lines:
      match = re.search(r'((except|raises) IndexError)', line)
      if match:
        found[afile.name] = match.group(1)
for item in found.items():
  print '%s (%s)' % item
print 'Found %d matches' % len(found)

> dict.get() doesn't raise KeyError. That's the whole point of get(), it
> returns a default value instead of raising KeyError.

Right. Exactly. Accessing a non-existent key raises a KeyError, but
dict.get() short-curcuits the exception and gives you a default value
(which is None unless explicitly changed). So instead of trying the key
and catching a KeyError, you can use a simple conditional and ask if
d.has_key(key), or assign d.get(key) and test the assignee. So, why
isn't there a list.has_index() / get()?

> If you don't care enough to even make a formal feature
> request, let alone a PEP, then why should people who care even less
> actually write the code?

I'm thinking about it. I just wanted to see if anyone knew of, or could
come up with, a good reason why it isn't / shouldn't be there.
Apparently not (at least not one that doesn't also bite the dict
convenience methods), so I'll probably go ahead and make a feature
request in the next few days.

Regards,
Jordan




More information about the Python-list mailing list