🐍 Beware of Python dict.get()
Tags: python, tips, beginners, webdev
Published: 2019-03-11 09:33:01

---
title: "🐍 Beware of Python dict.get()"
published: True
description: 
tags: ["python", "tips", "beginners", "webdev"]
canonical_url: "https://medium.freecodecamp.org/beware-of-python-dict-get-98d7ffe6667e"
series: "Python tips"
cover_image: "https://thepracticaldev.s3.amazonaws.com/i/vb05riwd4sorskyyb309.jpeg"
---


If you think that `value = my_dict.get('my_key', 'default_value')` is equivalent 
to `value = my_dict.get('my_key') or 'default_value'` you should probably read this 😃. If you know why it’s not the same, then you probably won’t learn something here.

## The good thing:

As anyone using Python 3 should know, the dict API is very clear and simple. I can declare a dict like this:

```python
my_car = {'wheels': 4, 'brand': 'Tesla'}
```

It is simple, quick and easy. Retrieving values is as easy:

```python
my_car.get('brand')
>'Tesla'
my_car['brand']
>'Tesla'
```

But to retrieve values I prefer the .get() for two reasons. First, there will be no exceptions raised if the key you want to access is not here (it will return `None`). Second, you can pass a default value to the method that will be returned if the key is not present in the dict :

```python
my_car['color']
>KeyError: 'color'

my_car.get('color')
>

my_car.get('color', 'black')
>'black'
```

### And the tricky one:

Now I’m going to show you what happened in the real world while fixing a bug for [ShopToList](https://www.shoptolist.com) in a method I wrote that uses a [lib](https://github.com/scrapinghub/extruct) that extracts metadata from an HTML page (in this case an e-commerce page).

To make things short, the data I expected should look like this (simplified example):

```python
data_from_extruct = {    
    'title': 't-shirt',    
    'brand': 'french-rocket',    
    'color': 'green',    
    'offer': {        
          'amount': 20,        
          'currency': '€'
    }
}
```

The easiest way to get the price from this data is:

```python
    price_from_extruct = data_from_extruct['offer']['amount']
    > 20
```
But as I said before, this solution is not robust at all. This is the real world, and in the real world the data from extruct will not always come with an offer and with a price in that offer. A better way to do this is to use dict.get:

```python
price_from_extruct = data_from_extruct.get('offer').get('amount')
```
This is still not good enough because if there is no offer in the data, you will try to perform the second .get('amount') on `None` and it will raise an error. A way to avoid that is to do:

```python
price_from_extruct = data_from_extruct.get('offer',{}).get('amount')
```
Here, if we don’t have offer in the data, the first get will return `{}` (empty dict) instead of `None`, and then the second get will be performing against an empty dict and will return `None` . All is great, it seems that we have a robust way to extract the price fromthe data that is not consistently formatted. Of course sometimes the value will be none but at least this code should never break.

Well, we are wrong. The catch comes from the behavior of the default parameter. Remember that the default value will be returned if, and only if, the key is **absent** from the dict.

What it means is that if the data you receive looks like this:

```python
data_from_extruct = {    
    'title': 't-shirt',    
    'brand': 'french-rocket',    
    'color': 'green',    
    'offer': None
}
```
Then the previous snippet will break:

```python
price_from_extruct = data_from_extruct.get('offer',{}).get('amount')
> AttributeError: 'NoneType' object has no attribute 'get'
```
Here the default value of get('offer', {}) was not returned because the key offer was in the dict. It was just set to None.

Of course Python is awesome so there are lots of simple way to fix this. The following snippet is just one of them:

```python
offers_from_extruct = data_from_extruct.get('offer') or {}
price_from_extruct = offers_from_extruct.get('amount')
```
Of course, this can also break if the content of offer is a list, for example. But for the sake of the example, we will stop here.

## Thank you for reading

I hope this short post will help you save time in the future. I wish I knew this before spending a shameful amount of time trying to fix a certain bug this week.

Please tell me in the comments if you liked the post and don't forget to [subscribe](https://www.daolf.com/stay_updated/) to my newsletter, there is more to come (And you'll also get the first chapters of my next ebook for free 😎).

If you like JS, I've just published [something you might like](https://dev.to/daolf/things-you-should-know-about-js-events-4k2l).

And if you prefer git, [I got you covered](https://dev.to/daolf/git-series-13-understanding-git-for-real-by-exploring-the-git-director--5bd0).