Me, un"Chain"ed

Taming the ChainMap in Python

I am sorry for a slight pause. I am based out of India and we are going through a massive second wave of COVID-19. I had been busy taking care of some issues and persons for the last two weeks. I hope that we will be in a better situation soon and also I hope that such delays won't happen again.


This week I am going to show a neat yet simple trick about a particular Container Datatype from Python. “ChainMap”. This datatype was introduced in Python from 3.3 and although very handy at certain situation, it is used rarely than it should be.

So what is a Chainmap? I also honestly did not know the answer very well until recently. I wanted to create an application where I needed to have a set of configurarion which has both user defined and default values. Also, I needed one more feature, if any user defined value does not make sense (let’s say someone had put the sequence length as float) then it should print a warning and gracefully fall back to the default value. Although there are multiple ways to solve this problem in Python, I wanted an elegant and Pythonic solution and also one which will be more efficient than each time creating a new dict and running multiple `update` calls.

Let’s take a simple example. You need configuration where you need to have two keys and their values. Let’s say the keys are called `model_type` and `sequence_length`. You want that users can supply them (which will be recored as dicts as well) and if they do not then you fall back to the defaults.

default_options = {"model_type": "BERT", "sequence_length": 128}

Now let’s say that your user defined options are looking like this

user_defined_options = {"sequence_length": 256}

To manage them properly here is a small piece of code

from collections import ChainMap

options = ChainMap(user_defined_options, default_options)
print(options)

The output looks like the following

ChainMap({'sequence_length': 256}, {'model_type': 'BERT', 'sequence_length': 128})

Keep in mind that a ChainMap supports all the usual dict methods and also exposes three extra ones, e.g. `maps`, `new_child`, `parent`. If you, now, access the `squence_length` key, it will give you the value from the user defined one. Like so -

options['sequence_length']

will print `256`

So we have achieved our first goal. Now let’s see about the second one. Imagine that your user had entered a value such as 132.5 as sequence length. Here is how you can handle it gracefully

if isinstance(options['sequence_length'], float) is True:
    del options['sequence_length']

And now if you try to access it then it will give you back the default value of 128.

Neat? isn’t it? To learn more head over to the official Python docs.

If you like Python’s Byte, please do not forget to share and like it.

Share Python's Byte


From around the web

Convert images to graphs - https://github.com/LeviBorodenko/img2rag

Learn Datalog Today - http://www.learndatalogtoday.org/

Why Are There 2 Ways to Write the Lowercase Letter ‘A’? - https://redditblog.com/2015/10/13/why-are-there-2-ways-to-write-the-lowercase-letter-a/

JupyterLab LaTeX – live-editing of LaTeX documents in JupyterLab - https://github.com/jupyterlab/jupyterlab-latex