Lara
Lara

Reputation: 3174

Why does the behaviour of these seemingly the same code snippets differ? (Python 3)

I was writing a sudoku solver, and came across this weird behavior. If I do the following:

r = range(1,len(board)+1)
b = block(board,x,y)
nums = [x for x in r if x not in b]

nums will be different from this way of calculating it:

nums = [x for x in range(1,len(board)+1) if x not in block(board,x,y)]

The block is simply as follows:

return sum([col[y*N(board):(y+1)*N(board)] 
            for col in board[x*N(board):(x+1)*N(board)]],
            [])

Where N is just the square-root of the size of the board, and board is just a list of lists of numbers. (The reason for things like N and len all over the place is that it should work for boards that aren't 9x9 too)

My question is simply: Why could these things be different? It's just reading values and storing them in variables, not assigning anything to board itself, so why would it matter if I do b = a and then use a, or just use b to begin with?

Upvotes: 3

Views: 58

Answers (2)

miradulo
miradulo

Reputation: 29710

When you use

r = range(1,len(board)+1)
b = block(board,x,y)
nums = [x for x in r if x not in b]

x is most likely already set to some constant, hence b becomes constant in your list comprehension. When you use your second list comprehension, x has a different value (iterating over r) throughout the comprehension, and overrides whatever x is on your function or module level - hence every check if x is in block(board,x,y) becomes dependent on your comprehension iteration.

Give your list comprehension variable a different name than x, and be careful about overwriting variable names.


Here's a minimal example where you can see that the variable name x is overwritten, and how it affects each call to your function.

>>> r = range(5)
>>> x = 1
>>> b = range(x+1)
>>> [x for x in r if x not in b]
[2, 3, 4]
>>> [x for x in range(5) if x not in range(x+1)]
[]

Upvotes: 3

Tim Pietzcker
Tim Pietzcker

Reputation: 336408

In the first example, b is calculated to be block(board,x,y), using whatever value x has at that moment. This value is then reused for all the iterations of the following list comprehension.

In the second example, x changes throughout the list comprehension, so with each iteration, block(board,x,y) will return a different result.

Upvotes: 3

Related Questions