Loops
Note
There’s a saying: “In C, loops are your friend. In Python, loops are your enemy.”
C++ is a compiled language. In the process of turning C++ code into machine language, the compiler can do many things to automatically optimize your code; for example, it can identify small loops (like the one in our example code fragment) and arrange for it to be executed in a CPU’s memory cache.
Python can’t do this. It has to interpret each line one-by-one. In a loop, it goes through each line, then “backtracks” to the beginning of the loop and freshly interprets each line again.
There are some tricks to get around this. Mostly they involve using Python to call routines written in C.1
As a first step, let’s get rid of one “cheat” that I put into our code
fragements. The while
statement has its uses, but they’re associated
with potentially varying logical conditions like reading a file. If
you’re incrementing a number by a constant interval, then both Python
and C++ have a better way to write a loop.2
# For each user, add a displacement to the distance array
interval = 10
scale = interval + 3
limit = interval + 1
# Assuming we want j=0:
for j in range(0,limit):
distance[j] += scale*j
// For each user, add a displacement to the distance array
int interval = 10;
int scale = interval + 3;
int limit = interval + 1;
// Assuming that we want j=0:
for ( int j=0; j < limit; ++j ) {
distance[j] += scale*j
}
There’s not much more we can do for the C++ code,3 so we’ll focus on the Python version of the rest of this section.
I didn’t supply a defintion for distance
. Given the use of
distance[j]
, it could be simple Python
array. But if
you’ve used Python before, you’re probably screaming at me: “Use
numpy!”
The length of the distance
array isn’t specified in the code
fragment. In theory, it could be larger than limit
. Let’s be general
for the moment, and assume the length of distance
is greater than
limit
.
import numpy as np
distances = 20 # or some other value
# Create a numpy array of length 'distances'
distance = np.zeros((distances))
Given the artificial nature of the original code fragment, the fastest
way to perform this task is to use numpy
’s array features:
# For each user, add a displacement to the distance array
interval = 10
scale = interval + 3
limit = interval + 1
j = 0 # or previously calculated elsewhere
distance[j:limit] += scale * np.arange(j,limit)
This will give us C-level speed. It’s up to you to decide whether this gives us Python-level clarity.4
Here’s a more detailed tutorial on using numpy to perform faster computations.

Figure 98: https://xkcd.com/844/ by Randall Munroe
- 1
At this point in the tutorial, you already know that I’m biased in favor of C++ over Python. So I can’t help but be snide and point out that if you’re using Python to call C, write not write your code in C in the first place?
The usual reason to prefer Python is its development cycle: You can quickly test small fragments and integrate them into your larger program. But now you know ROOT, which has a C++ interpreter that lets you do the same thing.
With that foolishness off my chest, I will continue to support and inform your use of Python. I’ve got at least one more lifetime I can spend learning more about the language!
- 2
I’m now using a lower limit of
j=0
in the loop, which I did not explictly do when I first introduced the fragments. In the “real” world, if the value ofj
was more complicated, it would not change the loop code by much… except that I would not have continued to use the simple letterj
for the name of the variable.- 3
Though as we’ll see in the next section, there’s a way to improve the C++ compilation, as opposed to the code.
- 4
Although we’ve achieved faster code, we haven’t necessarily achieved more robust code. What if the value of
limit
is greater than the length ofdistance
?