Quickie Dev #12: A step-by-step custom Python list-displayer tutorial

Lists are one of the most frequent data structures in Python… so how can we print them in a pretty way? 🙂

This article is also available on Medium.

When you write a Python program, you are bound to create a list at one point. Lists are just one of the most basic features of this language: they are very easy to use, they can be passed to other functions and modified in place, they can contain different types of variables…

Basically, lists are the default container for most Python programmers (perhaps along with dicts).

Of course, sometimes, you’ll be better off with a specific data structure to really optimise your code and avoid algorithm slow-downs (I talked about this a while ago in an article about data structures in Python)… but more often than not, lists are already good enough for a first go!

But something can sometimes be annoying with lists, and that’s how they show up in the console when you print them:

Obviously, this condensed display is ideal for the majority of the situations, so it’s great as the default representation… but what if we wanted to have something a bit prettier?

Today, let’s see how to create our own Python list displayer, step-by-step!

Step 1: Printing one item per row

To begin with, let’s make sure that we only have one item per row. This will make the list more readable when we start to have lots of items:

Thanks to this basic display_list() function, we now have one item on each row – it’s quicker to identify each and it can be really helpful if the items are long to print.

Step 2: Adding prefixes to the rows

But of course, we don’t just want to stack the items below each other like this! Most “formatted” lists have a little character at the beginning of each item row to clearly show that it’s a new item. In HTML, for example, we have the <ul> tag that creates an unordered list and adds a little bullet to each line:

We can do the same in our console and print a given character at the beginning of each row:

As you can see, our display_list() can be configured very quickly just by passing in another character as the prefix variable. But what if we wanted to have some predefined formats? Like the “dash” - or the “bullet” ?

You might be aware that Python doesn’t really have enums, so we can’t define a static list of formats in our code. However, a trick that is often used to “simulate” enums is to have a class contain static data: this way, the data is “scoped” by the class and it feels a bit like we had grouped this data in one single unit of logic.

Here, for example, we could define the following:

Note: for the bullet, I’m using a unicode character – that’s why I have to add the u character before my string 🙂

This way, in our function, we could set the “dash” as the default and then call one or the other in our main routine:

Note that we can still use plain characters too if we want – the ListPrefix enum-like structure is just a handy catalogue of possible prefixes that can give you some ideas 🙂

Step 3b: Making the prefixes dynamic!

We already have quite a nice display of our list, now. But the next step is to improve our prefixes and have them depend on the current item.

For example, what if we want to make an ordered list (like the <ol> HTML tag)?

Here, we can’t just pass in one character anymore: we have to define a function that computes the proper result depending on the row!

So let’s go ahead and improve our ListPrefix class a bit:

Here, I’ve just added one new element, the ARABIC format, that will print the items with an Arabic number (0, 1, 2, 3…) as the prefix. I’m using two tricks:

  • the prefix is defined using a lambda function: this a small anonymous function that contains a single expression and returns its value, but that can take in parameters just like a normal Python function
  • I’m wrapping this lambda function in a staticmethod() so that it doesn’t require a class instance to work (because remember we are “faking” our enum with a class, so we are actually in a class context at that point and functions are, by default, class methods that expect the instance as first parameter with the self keyword)

In our display_list() function, we’ll need to “standardise” our prefixes so that they all behave the same. I’ll simply check to see if the prefix is a basic string and, if it is, wrap it into a constant lambda that returns the string.

Thanks to this little pre-processing, I can now “call” all of my prefixes, passing in the current index of the row – most of the prefixes will ignore this info, but they all have the same format so the program won’t have issues running:

Note: to get both the index and the value of each item, I’m using the built-in enumerate() Python function that automatically returns a tuple with this couple of info for each item in an iterable.

You can of course do the same with other common numbering schemes, offset the display to start off from “1.” and not “0.”, or find even more crazy custom ideas of prefixes!

Step 4: Custom formatting based on the item value

Finally, it can be interesting to have an auto-formatter that applies a specific style to some items in your list based on a condition.

Let’s see how to colour some of our items based on their value! For this, I’ll be re-using a technique I mentioned in a previous article about formatting Python debugs: ANSI colour codes.

More generally speaking, ANSI escape codes are specific sequences of characters that are somewhat cross-platforms and can be embedded in your strings to modify their appearance. Instead of being simply printed to the console, those sequences are interpreted by the shell to change the font or the background colour, change the font style, move the cursor around in the terminal, etc.

Here, we’ll only focus on the colour codes that look like this:

These codes are just added around strings to change their colour:

colored_str = Colors.GREEN + 'A green string!' + Colors.RESET

Note: for more info on the ANSI colour codes, be sure to check my previous article 😉

We can now update our display_list() function to handle an optional formatter – the idea is simply to have a function that either returns the string as is or wraps it in additional colour codes to change its display (once again, I’m standardising the variable to always have a callable):

And finally, if we define a formatter and pass it to the display_list(), we’ll get a nice formatted result!

You can easily pass in a list of formatters and have multiple conditions checked at the same time:

Be careful, though, because if some item ticks multiple boxes, then this code will “combine” the formatters together which can lead to unexpected results… To have it stop at the first match, you can add a break at the end of the for-loop on formatters 😉

Conclusion

This little list displayer is very basic, and it could be extended to have lots of other functionalities — but it’s already a quick way of printing lists in a nicer way and even do some auto-formatting!

I hope you liked this quick tutorial, and of course feel free to tell me if you have ideas of other Python tools I could talk about!

Leave a Reply

Your email address will not be published. Required fields are marked *