# Loop Alternatives

Loops in Python are very slow. Nested loops are especially slow. Some alternatives are available in the standard set of packages that are usually faster..

## List Comprehensions

A list comprehension collapses a loop over a list and, optionally, an if clause.

squares=[x**2 for x in range(10)]


This is equivalent to

squares=[]
for x in range(10):
squares.append(x**2)


With an optional conditional it becomes

positives=[math.sqrt(x) for x in range(-10,11) if x>0]


This is equivalent to

for x in range(-10,11):
if x>0:
positives.append(math.sqrt(x))


List comprehensions may be nested.


list_2d = [[i+j for j in range(1,6)] for i in range(10,16)]


Observe the ordering in the previous example. The inner loop is first.

Exercise

Use math.sin and list comprehensions to generate a list of the sines of the numbers from -1.0 to 1.0 inclusive with an increment of 0.1. Print the result as a table of x, sin(x) using a for loop.

Example solution

import math
xs=[0.1*float(x) for x in range(-10,11)]
sines=[math.sin(x) for x in range(-10,11)]
for i,x in enumerate(xs):
print(x, sines[i])


## Functionals

A functional in this context is a function that takes a function as its argument. Python has functionals that can take the place of loops.

### Map/Reduce/Filter

The map functional applies a function individually to each element of an iterable and returns an iterator (in Python 3). Since we frequently want to do something with the result we can cast it to a list.

float_vals=list(map(float,range(20)))
print(float_vals)


Map is said to broadcast the function across the iterable.

The reduce function takes a binary (two arguments) function and applies it pairwise to each element, working its way down the iterable, to produce a single result. It was removed from core Python in Python 3 but can be imported from the functools module.

from functools import reduce
return x+y
print(sum_it)


The filter functional takes a function that returns a Boolean (True or False) and applies it elementwise to the iterable, returning an iterator.

def is_even(n):
return n%2==0
evens=list(filter(is_even,range(21)))
print(evens)


Map, filter, and reduce are frequently used with lambda functions.

## NumPy

Another way to avoid for loops is to use NumPy. The best speedups are usually achieved when it is possible to use NumPy built-in “vectorized” functions. For more details, see our workshop on High-Performance Python.

Previous
Next