Reputation: 5296
foods={}
name="potato"
foods[name]=foods.get(name, 0) +1
print(foods)
I'm creating a dictionary and a string. Then, next line, everything goes insane...
Suddenly it looks like we are supposing that the new string already exists in the new dictionary...
foods[name]=
As I understand from comments here, we're getting the Dictionary's key "name" with value 0,
foods.get(name, 0)
and adding one to the key's value.
+1
How can I reason this so it makes sense?
Related:
How can I add new keys to a dictionary?
Why dict.get(key) instead of dict[key]?
Upvotes: 0
Views: 42
Reputation: 19414
Well I believe the first lines are obvious:
foods = {}
name = "potato"
The important thing to remember here is that dicts are mutuable objects.
Next, what we have is a dict assignment:
foods[name] = x
As described in How can I add new keys to a dictionary?, this basically says: "Associate the value x
to the key name
inside foods
". If name
already exists in foods
with some value, that value will be overridden with x
. If it does not exist in the dict, a new key:value
pair will be created.
This will NEVER raise an error*, because we don't assume anything about the keys - it is not necessary. As explained above, if the key doesn't exist a new pair will be created. If the key exists already, it will be updated. Internally, the dict's __setitem__
method is called to allow this behaviour: foods[name] = x --> foods.__setitem__(name, x)
.
The value in this case is:
foods.get(name, 0) + 1
As described in Why dict.get(key) instead of dict[key]?, The get
method is used if we don't want the code to fail if some keys are missing. It has an optional argument default
(which its default is None
). This means that dict.get(key, default)
works the same as dict[key]
as long as the key exists in the dict! If it doesn't exist already, then default
will be returned instead.
So this line can be read as "add 1 to the value of name
from foods
if it exists in the dict, else just return 1 (0 + 1
)". This is a common construct for implementing some counter. We can use this single line to replace the following cumbersome structure:
if name in foods:
foods[name] += 1
else:
foods[name] = 1
You can now see the direct replacement: If the key exists, get
will return its value, then we add 1 and save it back to the dict - equivalent to foods[name] += 1
. If it doesn't exist in the dict, get
will return 0
, then we add 1 to get 1, and save that in the dict - equivalent to foods[name] = 1
.
Another alternative is to use a defaultdict
with int type:
foods = defaultdict(int)
foods[name] += 1
This encapsulates all that logic and when a key doesn't exist in the dict and we try to access it, the type we provided is called to create a default value. In this case, int()
returns 0
as desired.
* For hashable keys.
Upvotes: 2
Reputation: 227270
The dict.get()
method takes 2 arguments: The key and a default value if that key doesn't already exist in the dict.
So foods.get(name, 0)
means look up the name
key in foods
and return its value, otherwise return 0
.
Upvotes: 2