Photo by David Clode on Unsplash

“import dis” never sucks

There are lots of situations, when you need to understand, what happens at which point of execution. Let’s assume you have such code:

Let’s assume that this code is OK. (well, it’s not, right?) What it does? How exactly python will interpret this code? This can be found out using module dis. It can be used like this.

Mostly, this “disassembled” code made obvious to read. First, we load constant value 1, then print item, then print new line, then load constant value None and return it. Mostly obvious, for this particular example. But you have more complicated bytecode or you want to understand this better, you can always look for more details at the documentation: python 2 and python 3.

Let’s then prepare our code for disassembling. We want to analyze, what ill it actually do if we run such comprehension with function call inside. Here’s the code:

Pretty much, huh? However, this “disassembly” is still readable and understandable. Let me show you this:

— First, we initialize create empty list; [0]
 — Then, we load globals to initialize range iterator; [3-9]
 — We iterate through that iterator like using for-loop; [24-34]
 — We load function, constant, and call function with that argument; [19–25]
 — Than create list and append data to previous lis;t [31]
 — Then jump back to 13 and iterate through it until iterator is exhausted; [34]
 — Return the value. [37]

Not so hard from that perspective. Now it is obvious that this implementation is pretty suboptimal: the same function is called in each iteration, and in each iteration the list is created. Pretty awful. It’s time to fix it.

Python has pretty great feature: multiplying list to a number. It can be used like this this:

It can fix our problem. But I am not a super-mind and I can mistake. You should check this (you pretty should always). One way to do it is to use timeit. But this is note about `dis`.

Now you see that this thing simply must be way much faster than previous. It loads function and argument, calls function and then builds list for that only ones. That’s the thing we found out using dis.

If you have some doubts that your code could probably be slow — simply try to disassembly it, especially when you are figuring out some code that you can’t simply run time execution benchmark due to some reasons. It’s pretty simple yet powerful tool, and it will allow you to understand better how interpreter works. And will allow you to write faster and cleaner code with less headache.

import dis never sucks :)


Small disclaimer: I am not a native English speaker, so I can make grammar or other mistakes. If you find one, feel free to correct me using private notes.

Thanks for attention, you were reading note on usage of dis module in python. If you like it, clap and follow me. I try to write about my experience pretty regularly.

For more information on the topic, I strongly recommend to read the python documentation.