Skip to content

Specialize Your Own Collection in Python

Mapping, Sequence or Collection in Python: you choose the best one for the data structure you want to build. A simple explanation of everything you need.

Ramón Invarato

We have already created our Python Container (as we saw in the previous article on how to create our own Collection https://jarroba.com/nuestra-propia-coleccion-en-python/ ) and we want it to specialize. In what? Well, that depends on what we need, so the best thing is to know the possibilities and what Python already gives us. As if it were a choose-your-own-adventure story, there are four options (with many variants) starting from Collection:

  • A sequence of data added one after another in numbered positions. The typical Python “List” data type (example: [1, 2, 3] ) will come to mind, which belongs to the specialized class “Sequence”.
  • One piece of data is the key that points to (maps) another piece of data that is the value. That is, keys that map values. Python’s simple type is the “Dict” (example: {“key”: “value”, “another key”: “another value”} ), and it belongs to the specialized class “Mapping”.
  • A set of data has the benefit of storing only values (no keys, like Lists) and no duplicate values (as happens with Dictionary keys, which have to be unique); also, if we have more than one set we can perform set operations by combining them (for example, we can get all the values that exist in one set as well as in the other; which is the result of the “union” of the values of both sets). In Python its simple type is the “Set” (example: set(“value1”, “value2”) ), which belongs to the specialized class “Set”.
  • Our own Collection. From the “Collection” class we can invent any other one that we can’t classify into any of the previous ones.
Python class diagram: Collection inherits from Iterable, Container and Sized; Sequence, Mapping and Set specialize it

Although I have listed four options, the first three (Sequence, Mapping and Set) are really the ones we will need in the vast majority of cases.

And why do these three exist? The creators of Python (and of other programming languages) came to the conclusion that practically all data structures could be represented as Sequences, Mappings and Sets. What if I invent something different? You are free to try and discover new data structures that can’t be represented in any of these three groups, although practically everything can be covered by them:

  • Maybe a class that, given a key, returns a value stored in a file? That would already be a dictionary, a Mapping
  • A matrix or table of rows and columns? That is, a list of lists, a Sequence
  • A tree structure? A Mapping whose keys are the nodes
  • Maybe the decomposition of a JSON? It can be represented as nested dictionaries, and if we create this representation in a single class it could perfectly well be a Mapping (in fact, the “json” library that comes with Python returns a structure of dictionaries and lists when you give it a JSON as text; more information at https://docs.python.org/3.7/library/json.html).

Some data structure might exist that can’t be grouped into any of the three groups above. In any case, we will always be able to create a class ourselves inheriting directly from “Collection”; for everything else, and to make our lives easier, I recommend that you choose to inherit from whichever suits you best: Mapping, Sequence or Set.

In the previous article (https://jarroba.com/nuestra-propia-coleccion-en-python/ ) we saw some examples that we could classify as Mappings, and that is where we will start.

Which One to Choose?

It is important to know the advantages inherited from each class: Mapping, Sequence or Set; so you don’t work in vain by repeating functionality that already exists and is heavily tested. For example, if we want our object to return its values in order and its keys to be the order in which those values were added, then we don’t inherit from “Mapping” but from “Sequence” (as an example, I can think of a class that queries a server for data that we want returned in order, so whoever uses our class that inherits from “Sequence” will use it just like a list even though underneath we programmed it to get the data from a server on the Internet), because practically all of the desired behavior is already programmed and we would only have to focus on adding new behavior.

Below is a comparison image of the three so you can choose correctly (although I included it in the article on https://jarroba.com/resumibles-hashables-en-python/, I think it is important to remind you of it in this article). On the left, in purple, I show an example of each type of class; on the right, their qualities (these are neither good nor bad, they are just what is needed); between two types of classes I use double arrows to show the qualities they share:

Comparison of Python Sequence (list), Set (set) and Mapping (dict), with their traits and the ones they share

The image above is a summary. Let me expand a bit more on their qualities.

Let me remind you of the difference between:

  • Values: the data stored as values in the data structure.
  • Keys: for a dictionary, it is a piece of data that points to a stored value, and for a sequence it is the insertion position (the position is a numeric key that points to the value); sets, however, have no keys.
  • Items: a tuple of both, that is, with the key and the value.

Elements: this term is more abstract and only used in theory (that is, you can NOT call it with a “getElements()” ). It refers to any piece of data stored in the contents of the data structure, in whatever form. That is, instead of saying all the time “Values and/or Keys (and/or Items) of the data structure”, we sum it up as “Elements of the data structure”. You will read it a lot when reviewing theory or documentation, for example “the elements stored in the data structure…” (meaning “the keys and/or values stored inside the data structure”), or the “Elements returned by the data structure…” (watch out here, because it can mean “the Keys and/or the Values and sometimes it even includes the Items returned by the different methods of the data structure”). These terms are so close that “Items” gets confused with “Elements”, and confusing them is wrong. You could say that “Elements” is the vague way of naming the technical terms: Values, Keys and Items. This term comes from the need to somehow name the values held inside dictionaries, lists and sets all at once (and I can assure you it is very hard to name the contents of data structures collectively; when writing this article, for example, dictionaries have keys and values, lists have values and their keys are auto-incrementing numbers, and sets only have values. How do you refer to all these contents of such different data structures? Well, with “Elements” 😊 ).

Qualities of Inheriting from Mapping

  • The key can be of any immutable type (int, String, etc.), that is, the object’s class must inherit from “Hashable” (complete information about “Hashables” at https://jarroba.com/resumibles-hashables-en-python/ ).
  • Values can be of any type, both mutable and immutable (everything you need to know about mutability and immutability at https://jarroba.com/mutables-e-inmutables/), that is, of any type.
  • Iteration (for example, getting the values with a “for” loop) over the contained elements will be random. Before you rush into creating a Mapping class that keeps the insertion order of the elements, note that Python has a dictionary that keeps the insertion order called OrderedDict (more information at https://docs.python.org/3.7/library/collections.html#collections.OrderedDict); what’s more, since Python 3.7 insertion order is guaranteed.
  • Checking whether it has a key is very fast (since it is a “Hash table”, looking up a key is immediate; more information about “Hash Tables” at https://jarroba.com/tablas-hash-o-tabla-de-dispersion/ ).
  • It allows “views” over the keys, the values or the items (if you don’t know what views are, we will cover them later; you will see they are quite useful and simple)

Qualities of Inheriting from Sequence

  • The key can only be an integer (int) that indicates the insertion position of the value.
  • Values can be both mutable and immutable (of any type).
  • Iteration over the contained values follows the insertion order of the values, and you can iterate in reverse (from the last inserted value to the first).
  • Checking whether it has a key is slow (it requires searching one by one through all the contained values).

Qualities of Inheriting from Set

  • It has no keys, only values.
  • Values can only be immutable and it doesn’t store duplicate values (exactly like the keys in dictionaries).
  • Checking whether it has a value is very fast.
  • It allows operations between different sets: and (or inner join), or (or full outer join), xor (or subtraction), less than, greater than, not equal to, equal to, etc.

Choose Wisely What to Specialize In

Now it’s your turn: time to think about which collection to specialize from. To keep this article from getting too long, and because each specialization stands on its own, I will explain each one in a separate article. You have available at www.jarroba.com:

“Specialize Your Own Collection in Python” by Ramón Invarato at jarroba.com, licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0. Registered at Safe Creative.

Ramón Invarato

I design and build data platforms and intelligent systems, and I enjoy sharing that experience here.

You may also like

Building Your Own Collection in Python

Learn how to build your own Collection in Python step by step: Container, Sized and Iterable explained, plus the difference between an Iterator and an Iterable.

May 27, 2018

Python Course – 3. Collections

Learn Python collections: lists, sequences, tuples and dictionaries, with videos, theory slides and hands-on exercises from the jarroba Python course.

Jul 17, 2020

Comments

Leave a comment


This site uses Akismet to reduce spam. Learn how your comment data is processed.