Where does the 2 come from?

values = [[3 - x for x in range(2)] for y in range(5)]
print(values)

[[3, 2], [3, 2], [3, 2], [3, 2], [3, 2]]

I understand “3 minus something” and “x for x in range(2)” equals 3 minus a variable for a loop consisting of two numbers and I understand the second “for y in range(5)” means that the previous loop will repeat 5 times… but why would anyone just assume the value of the variable to be a “1”?

Is this just a standard thing, “anytime you see an integer being added to, subtracted from, mutliplied or divided by a variable, just assume the variable is a one”?

Iterating over range(2) yields yields integers from 0 up to but excluding 2, i.e. 0 and 1.

[3 - x for x in range(2)]

is:

[(3 - x) for x in range(2)]

so that’s:

[(3 - 0), (3 - 1)]

or:

[3, 2]

3 Likes

In addition to the above, remember that statements are evaluated right-to-left, so for x in range() will evaluate before 3 - x

That is not true in general.

It is not even true in general for list comprehension syntax.

[a for a in range(b) for b in range(3)]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined

Should be:

[a for b in range(3) for a in range(b)]
# returns [0, 0, 1]

Comprehension syntax evaluates left-to-right starting at the first for clause, and then evaluates the left-most expression. So the above example is equivalent to:

result = []
for b in range(3):
    for a in range(b):
        result.append(a)

Maybe I didn’t explain myself carefully enough; the point I was making is that, with say x = input() the input is taken first, then attached to x. Likewise, with for x in range(y) the y is evaluated first, then attached to x.

Hell no. That would pretty much defeat the purpose of variables:

x = 1000
print(1 + x)

That better print 1001, and not 2, or Python variables would be pointless.

We can break your code snippet into two pieces: an inner loop, and an outer loop.

The inner loop is [3 - x for x in range(2)]. As Matthew explains, range(2) evaluates to something like [0, 1] (the default starting value is 0, and the ending value, 2, is excluded).

So inside the inner loop, x takes the values 0 and then 1, and the expression 3 - x evalues to 3 and then 2, which are collected inside a list, giving [3, 2].

The the outer loop for y in range(5) runs the entire inner loop five times, which is why you get a list of five equal lists.

Although the value of y is not used, it takes the values 0, 1, 2, 3, and lastly 4, giving us five loops, each of which contributes [3, 2] as the result.

Until you get used to the syntax, list comprehensions are sometimes too terse to be easy to follow. We can expand your nested list comprehension into a pair of nested loops, which might be easier to understand.

# values = [[3 - x for x in range(2)] for y in range(5)]

# Outer loop.
values = []
for y in range(5):
    # Inner loop.
    result = []
    for x in range(2):
        result.append(3 - x)
    values.append(result)