Let me present a very simple example first, since this is going to be very useful for us later on. Imagine I have this simple function:
def myFunc():
return [1,2,3]
Question: What is the first element of myFunc
? In other terms, what is myFunc[0]
. Be careful, I am not asking the first element of the output of it, i.e. myFunc()[0]
; my question is the first element of myFunc
itself! The former would be the first element of [1,2,3]
, which is 1
; but the latter will give me a TypeError
, because a function can't be subscripted; akin to the fact that a recipe can produce delicious food, but you can't eat the recipe itself.
Let's take a look at your error message:
TypeError: 'builtin_function_or_method' object is not subscriptable
This means that you are somehow trying to subscript a 'builtin_function_or_method' object. Let's look at your code and understand what this error is due to. Luckily, your call is just one line, hence easy to debug:
testVar.items[0]
What you are doing is to reach the first element of the items
function or method of a dict
. Be careful, not the first element of the outcome, but the function itself. How am I so sure? Because you forgot the parentheses, therefore haven't even called the function yet, i.e. you didn't do testVar.items()[0]
.
Let's look closer at the built-in items
function of dict
s. When we just run testVar.items
, this is the response we get: <function items>
. Let's run the following to get some help about its docstring: ?testVar.items
, which returns the following:
Docstring: D.items() -> list of D's (key, value) pairs, as 2-tuples
Type: builtin_function_or_method
A-ha! We just saw what the error message we had mentioned: builtin_function_or_method
! So the error is really due to your code not being able to call the function properly, but try to get the first element of the function itself.
Let me give a simpler but equivalent example. Say, I have a list x = [2, 3, 1]
and I want to find its smallest element. I can use the built-in function of sort
, and then get the first element in the sorted list. Therefore the proper syntax would be x.sort()[0]
but if I forget the ()
, and write x.sort[0]
I will be trying to get the first element of not the result of the sort
function (because I didn't even call it to get a result!) but the first element of the function itself. Remember the recipe not being edible? Same thing.
In summary: A function can return an iterable which you can subscript, but a function itself is not subscriptable.
Let's play around with this function a little bit. Let's iterate on it as (key, value) pairs per docstring:
for k, v in testVar.items():
print k, v
# Result:
date 1520053431
items [{'macAddress': '98:90:96:9C:94:6C', 'manufacturer': 'intel'}, {'macAddress': '98:90:96:9C:94:52', 'manufacturer': 'intel'}, {'macAddress': '98:90:96:90:94:52', 'manufacturer': 'intel'}]
location {'lat': 39.349887, 'lng': -82.116147}
This makes sense, because we indeed have 3 keys and corresponding 3 values.
Now, how can you get the values corresponding to the key named items
? Notice, this is one of your three keys, but has the same name as the built-in function of dict
s we discussed above. This is where your confusion is coming from.
The error message was due to the items
function, let's discuss how to get the value corresponding to the key named items
. One inefficient way is using the loop syntax I presented above:
for k, v in testVar.items():
if k == 'items':
print v
# Result:
[{'macAddress': '98:90:96:9C:94:6C', 'manufacturer': 'intel'}, {'macAddress': '98:90:96:9C:94:52', 'manufacturer': 'intel'}, {'macAddress': '98:90:96:90:94:52', 'manufacturer': 'intel'}]
There you go, here is your items
! A second and efficient way of doing the same thing is calling the key name, and the values will be returned to us:
testVar['items']
# Result:
[{'macAddress': '98:90:96:9C:94:6C', 'manufacturer': 'intel'},
{'macAddress': '98:90:96:9C:94:52', 'manufacturer': 'intel'},
{'macAddress': '98:90:96:90:94:52', 'manufacturer': 'intel'}]
To wrap-up:
- Pay attention to the cases where your
key
in a dict
has the same name of a built-in function or method.
- You can't do
myDict.key
, but myDict['key']
.
- You can also loop over the
item
function of dict
s as (key, value)
pairs and get the value corresponding to the key. But don't do this, this is inefficient compared to the constant time complexity of myDict['key']
.
- If you are calling
myDict.function
, make sure you actually put that function into action by myDict.function()
. That is, don't eat the recipe, but eat what it produces.