List comprehension and generator expressions
List comprehension and generator expressions are important Python features that allow you to do implicit enumeration in a concise fashion. To give a simple example, the following list comprehension builds a list containing the squares of the numbers from 1 through 5:
gurobi> [x*x for x in [1, 2, 3, 4, 5]] [1, 4, 9, 16, 25]A generator expression is very similar, but it is used to generate an
Iterable
(something that can be iterated over). For example,
suppose we want to compute the sum of the squares of the numbers from
1 through 5. We could use list comprehension to build the list, and
then pass that list to sum
. However, it is simpler and more
efficient to use a generator expression:
gurobi> sum(x*x for x in [1, 2, 3, 4, 5]) 55A generator expression can be used whenever a method accepts an
Iterable
argument (something that can be iterated over). For
example, most Python methods that accept a list
argument (the
most common type of Iterable
) will also accept a generator
expression.
Note that there's a Python routine for creating a contiguous list of
integers: range
. The above would typically be written as
follows:
gurobi> sum(x*x for x in range(1,6))Details on the
range
function can be found
here.
List comprehension and generator expressions can both contain more
than one for
clause, and one or more if
clauses. The
following example builds a list of tuples containing all x,y
pairs where x
and y
are both less than 4 and x
is
less than y
:
gurobi> [(x,y) for x in range(4) for y in range(4) if x < y] [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]Note that the
for
statements are executed left-to-right, and
values from one can be used in the next, so a more efficient way to
write the above is:
gurobi> [(x,y) for x in range(4) for y in range(x+1, 4)]
Generator expressions are used extensively in our Python examples,
primarily in the context of creating multiple constraints at once
using the addConstrs
method.