Blog

Links

Python and JavaScript: dicts and objects

posted: May 16, 2020

tl;dr: Both Python and JavaScript provide the superpower of a built-in key-value store data structure...

The fifth in a series of posts highlighting the commonalities of Python and JavaScript.

My favorite data structure in any programming language is the key-value store, sometimes called a hashmap or just a map. This data structure delivers remarkable powers even though what it does is very simple: you give it a value called a key, and it returns another value. Under the hood, it is using some sophisticated mathematics (hash functions) and algorithms to do this in a time- and memory-efficient manner.

As long as the ‘value’ portion of the ‘key-value’ store can be anything else that can be stored in memory, the key-value store data structure achieves superpower status. It can be used to translate or map one string to another string, for example to map U.S. state names to their 2-letter postal abbreviations (or vice versa), or to translate words in one language to another, or to look up the meaning of a word, as in a dictionary.

If the values can be anything stored in memory, then the values can be other key-value store data structures as well as lists or arrays. This means that key-value stores can be used to store all the data about entities such as a person: first name, last name, a list/array of addresses, a list/array of phone numbers, etc.

In mathematics and computer science, pure functions are functions which, when given the same inputs, always produce the same output without any other side effects. The results of pure functions can be calculated once and stored in a key-value data structure, to avoid ever having to run the same calculation again. This is a type of caching. Key-value stores can be used for other types of caching, such as getting information from slow data sources and making it quickly available for subsequent retrievals. Entire databases can be built using key-value stores as the fundamental underlying technology which organizes the data and makes it quickly retrievable. Even graph databases, with explicit relationships between nodes, can be built using key-value stores.

Python and JavaScript both chose to build in a key-value store data structure as a fundamental data type in the language. Java, to its detriment, did not, although there is the HashMap data structure which can be imported from Java.util. Because both Python and JavaScript built it into the language, code in those languages which uses key-value store data structures is much more simple and elegant. In fact, some of the syntax is identical.

Python’s key-value store is the ‘dict’ (short for ‘dictionary’), and JavaScript’s is the ‘object’. As is often the case, I find Python’s terminology to be a bit more precise and accurate. In Python, the word ‘object’ is too generic, because literally every data structure, even boolean True and False, are objects that live in the memory space of the Python interpreter. When Pythonistas talk about objects, they most often mean instantiations of classes in the traditional object-oriented programming sense. True and False are objects created from the class bool. Modern JavaScript also has classes and objects which can be instantiated from classes. The JavaScript array data structure is also an object, as typeof [1, 2] will reveal. But for the rest of this discussion, ‘object’ will refer to the JavaScript key-value store data structure that resembles a Python dict.

Some of the syntax of Python dicts and JavaScript objects is identical. Assuming that the variable me has already been declared in JavaScript, the following statement creates a dict/object in both languages and assigns it to me:

me = {'first_name': 'Chris', 'last_name': 'Shaver'}

This expression will retrieve my first name in both languages:

me['first_name']

And this statement will set my height to 2 in both languages:

me['height'] = 2

To retrieve a collection of all the keys in the dict/object, both languages have a keys() method. Both also have a values() method to retrieve a collection of all the values. To retrieve a collection of the key-value pairs, Python has a items() method whereas JavaScript has an entries() method. But the syntax for invoking these methods is different because of the most visible difference between Python’s dict and JavaScript’s object: the keys.

The keys in a JavaScript object are always strings. You can pass in numbers in an attempt to use numbers for the keys, but JavaScript will just turn those numbers into strings. Python, however, allows the keys to be many data types: strings, integers, floating point numbers, datetimes, even tuples, booleans, and objects instantiated from your own custom classes. The only restriction on a Python key is that the data type has to be hashable. What is hashable? As a starting point, the key has to be immutable: its value can’t change over time. Hashable means that a hash function can be (and is) written for that data type, to turn any instance of the data type into a number that is evenly and randomly distributed across all possible instances.

JavaScript’s limitation of keys always being strings is both a blessing and a curse. On the blessing side it allows shorthand to be used in setting up objects and referencing key-value pairs, specifically dot notation. The example code above is not actually how a JavaScripter would write it; instead they would likely do:

me = {first_name: 'Chris', last_name: 'Shaver'}

There’s no need to put the keys in quotes because JavaScript assumes the keys to be strings. Then dot notation can be used to retrieve and set values:

me.first_name // -> 'Chris'

me.height = 2

Dot notation can’t work in Python to access key-value pairs, because the keys can be almost any type. This simple example creates a Python dict with two key-value pairs:

a = {'1': 'string one', 1: 'integer one'}

Python can’t use dot notation to access the key-value pairs because what pair would a.1 refer to? (In fact even JavaScript can’t use dot notation to access a.1, because although the 1 is interpreted as a string, it’s not a valid binding name. JavaScript also can’t use dot notation when the key is a string with a space in it.) Python avoids this whole problem by not using dot notation at all to access key-value pairs: the way to access each value in the example above is: a['1'] and a[1].

Before JavaScripters get all smug about their ability to use dot notation to access key-value pairs, there are some curses that come with it. The most obvious one is that dot notation cannot also be used to access the methods on a JavaScript object, because that would create too many naming conflicts and restrictions on key values. So to get a collection of the keys in a JavaScript object, the keys() method is invoked by doing, for the original example above:

Object.keys(me)

Whereas Pythonistas get to use dot notation to access the keys() method:

me.keys()

The other curse for JavaScripters is a bit more subtle. The ability of a Python dict to accept keys of many different data types makes it more suitable for duck typing and looking things up when you don’t know or care about the type of the key you are handed. All sorts of key-value pairs of all sorts of types can easily be thrown into a Python dict and accessed later.

But as is the case with JavaScript arrays and Python lists, the similarities of Python dicts and Javascript objects far outweigh the differences. Both languages provide the superpowers of key-value store data structures.

Previous: Lists and arrays

Next: Multi-paradigm languages