Which types of objects fall into the domain of "subscriptable"?
It basically means that the object implements the __getitem__()
method. In other words, it describes objects that are "containers", meaning they contain other objects. This includes strings, lists, tuples, and dictionaries.
[
...]
indexing syntax is called a subscript, because it's equivalent to mathematical notation that uses actual subscripts; e.g. a[1]
is Python for what mathematicians would write as a₁. So "subscriptable" means "able to be subscripted". Which, in Python terms, means it has to implement __getitem__()
, since a[1]
is just syntactic sugar for a.__getitem__(1)
. –
Lucielucien hasattr
should work fine, but it's not the Pythonic way to do things; Python practice encourages Duck Typing. Meaning, if you plan on trying to fetch an item from your object using a subscript, go ahead and do it; if you think it might not work because the object is not subscriptable, wrap it in a try
block with an except TypeError
. –
Lucielucien super
seems to be an exception. The object returned by super
can have the attribute __getitem__
, but it is not subscriptable, thus the bracket slicing does not work. –
Psychometry Off the top of my head, the following are the only built-ins that are subscriptable:
string: "foobar"[3] == "b"
tuple: (1,2,3,4)[3] == 4
list: [1,2,3,4][3] == 4
dict: {"a":1, "b":2, "c":3}["c"] == 3
But mipadi's answer is correct - any class that implements __getitem__
is subscriptable
The meaning of subscript in computing is: "a symbol (notionally written as a subscript but in practice usually not) used in a program, alone or with others, to specify one of the elements of an array."
Now, in the simple example given by @user2194711 we can see that the appending element is not able to be a part of the list because of two reasons:-
We are not really calling the method append; because it needs
()
to call it.The error is indicating that the function or method is not subscriptable; means they are not indexable like a list or sequence.
Now see this:-
>>> var = "myString"
>>> def foo(): return 0
...
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable
That means there are no subscripts or say elements in function
like they occur in sequences; and we cannot access them like we typically do, with the help of []
.
Also; as mipadi said in his answer; It basically means that the object implements the __getitem__()
method. (if it is subscriptable).
Thus the error produced:
arr.append["HI"]
TypeError: 'builtin_function_or_method' object is not subscriptable
if “scriptable”
A scriptable object is an object that records the operations done to it and it can store them as a "script" which can be replayed.
For example, see: Application Scripting Framework
if “subscriptable”
Now, if Alistair didn't know what he asked and really meant "subscriptable" objects (as edited by others), then (as mipadi also answered) this is the correct one:
A subscriptable object is any object that implements the __getitem__
special method (think lists, dictionaries).
I had this same issue. I was doing
arr = []
arr.append["HI"]
So using [
was causing error. It should be arr.append("HI")
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.)
gimme_things
raise an exception when it can't do what it was supposed to do. This is scary for beginners, but actually a good pattern to learn. It's better to fail loudly than to pass back bogus information or make the return value ambiguous (as might be the case if you return an empty list when you could not find any items, but also when something unrelated failed; it is often better then to raise an exception for the latter case). –
Imminent Basically this error will appear in case you are modifying or adding any field after type casting for the mentioned object instead of doing it before.
This question is the nr. 1 result on search and it has the most views, so I'll post here.
My case
(404, b'{"url":"https://example.com"}')
Tried to get the first value, accessing obj[0]
returned object is not subscriptable.
As another answer suggested, tried looping through it but got object is not iterable.
Solution
obj.args[0]
Troubleshooting
Call print(dir(obj))
and see if there's a method or attribute that might give you access to the value.
© 2022 - 2024 — McMap. All rights reserved.
hasattr(SomeClassWithoutGetItem, '__getitem__')
to determine if a thing is subscriptable? – Paintbox