Python’s SETDEFAULT

When you’ve been designing and writing systems for decades, you’d start seeing “patterns” in your own code, and if you’re lazy and smart, you’d either write a wrapper function to make multiple lines of code a single one …. or discover a built-in function that does exactly what you need.

And this time it’s Python dictionary’s “setdefault” method.

It’s rare to ever need this, but when you do, this really is worth knowing.

Similar to …

If you’re familiar with SQL, you can think of this as “INSERT IF NOT EXIST” type of query. And similar to that, this method “creates” or “inserts” an entry in the dictionary only-if-it-doesn’t-exist. Again, rare that you’d need this but let me give you one use case that might.

Use Case

One of the many (though rare) use case is when you have a simple daemon that monitors an IOT device that sends out its temperature readings from time to time. To demonstrate that, we’ll just stick with the very basics so we won’t be distracted by the real-world intricacies of an actual monitoring system.

Traditional/Typical Code

Here’s a very simplified module that uses a dictionary to store device readings. The keys are the device ids and it contains a list which would contain all the readings for that specific device.

This looks very much like what you’d normally do.

You check if the device id already exist in the dictionary, and if it doesn’t then you create it first and initialize with an empty list.

Test Code

Now, let’s write a function that would run some random simulation and call our recorder function above:

If you run that code, you’ll get this result:

The result isn’t really the point here, we know what it’ll do. But just in case you’re wondering if that code above works, here is your answer 🙂

Using setdefault

Here’s the simplified version of the exact same functionality:

We’ve converted 3 lines into 1 line.

Now, that’s also not the point —- less lines doesn’t always mean better code.

The point is this: if there’s a built-in function that does what you’re trying to do, use it instead of reinventing the wheel.
Why? Because built-in functions in Python is much faster that whatever Python function you’ll write.
Why? Cause those built-in functions are written in C, assuming we’re all using CPython which is what most people use 🙂

Testing setdefault

We’ll use the same wrapper function and pass this new function to it then run the codes.

As expected, it’ll output something like this:

Again, the output isn’t the point of this blog, just want to assure you it works 🙂

Bonus Use Case

Django: Setting Default Headers

If you’re using Django, you could also use this technique to set default headers.

Here’s a very simple example:

And here’s the simulated output:

Obviously this isn’t Django, but the codes should look “familiar” to you and should be enough to give you an idea how you’d implement it on an actual Django project.

Note that in “index”, we didn’t specify the Content-Type and so the default “text/html” will be passed along the browser.

On the “api” end point, we did indicate a different Content-Type and that’s exactly what will be passed.

Take away

Sure you could use the “get” and pass a default, BUT that doesn’t create an entry in the dictionary. It just returns the default value you passed to “get” method if the specified key doesn’t exist. When you need that default to exist in the dictionary (example, when another function will use that dictionary as input), then “get” won’t do, you’ll have to use the “setdefault” instead.

dict.get

Here’s using the “get” to have a default returned to us. Notice that the dictionary retained its content, the default wasn’t added.

In most cases, this is exactly what you want. Most of the time you don’t want to modify data and in those cases, you should really use the “get” method.

dict.setdefault

On the other hand, “setdefault” modifies the dictionary and adds the entry if and only if it doesn’t exist:

What happens if you call it again with another default?

Okay, you might be thinking, what if I call setdefault when it already exist?

Well, it returns the one from the dictionary. Again, it’ll only create (and then return) the default value if and only if that doesn’t exist. If that key already exist via add, or property setting, or even via the setdefault method, then it’d just return what’s in the dict.

Go back to the “v1” function we created earlier, and that’s how it basically works. We just used the built-in since it’s faster and/or more efficient, plus every other Python developer would have access to it.

That’s it for now. Thank you if you got this far 🙂

Leave a Comment