Which types of objects fall into the domain of \"subscriptable\"?
As a corollary to the earlier answers here, very often this is a sign that you think you have a list (or dict, or other subscriptable object) when you do not.
For example, let's say you have a function which should return a list;
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
Now when you call that function, and something_happens()
for some reason does not return a True
value, what happens? The if
fails, and so you fall through; gimme_things
doesn't explicitly return
anything -- so then in fact, it will implicitly return None
. Then this code:
things = gimme_things()
print("My first thing is {0}".format(things[0]))
will fail with "NoneType
object is not subscriptable" because, well, things
is None
and so you are trying to do None[0]
which doesn't make sense because ... what the error message says.
There are two ways to fix this bug in your code -- the first is to avoid the error by checking that things
is in fact valid before attempting to use it;
things = gimme_things()
if things:
print("My first thing is {0}".format(things[0]))
else:
print("No things") # or raise an error, or do nothing, or ...
or equivalently trap the TypeError
exception;
things = gimme_things()
try:
print("My first thing is {0}".format(things[0]))
except TypeError:
print("No things") # or raise an error, or do nothing, or ...
Another is to redesign gimme_things
so that you make sure it always returns a list. In this case, that's probably the simpler design because it means if there are many places where you have a similar bug, they can be kept simple and idiomatic.
def gimme_things():
if something_happens():
return ['all', 'the', 'things']
else: # make sure we always return a list, no matter what!
logging.info("Something didn't happen; return empty list")
return []
Of course, what you put in the else:
branch depends on your use case. Perhaps you should raise an exception when something_happens()
fails, to make it more obvious and explicit where something actually went wrong? Adding exceptions to your own code is an important way to let yourself know exactly what's up when something fails!
(Notice also how this latter fix still doesn't completely fix the bug -- it prevents you from attempting to subscript None
but things[0]
is still an IndexError
when things
is an empty list. If you have a try
you can do except (TypeError, IndexError)
to trap it, too.)