我正在写一个数独求解器,并遇到了这种奇怪的行为。如果我执行以下操作:
r = range(1,len(board)+1)
b = block(board,x,y)
nums = [x for x in r if x not in b]
nums
与计算它的方式不同:
nums = [x for x in range(1,len(board)+1) if x not in block(board,x,y)]
block
如下:
return sum([col[y*N(board):(y+1)*N(board)]
for col in board[x*N(board):(x+1)*N(board)]],
[])
其中N
只是电路板大小的平方根,而电路板只是数字列表的列表。 (像N
和len
这样的地方的原因是它应该适用于非9x9的电路板)
我的问题很简单:为什么这些事情会有所不同?它只是读取值并将它们存储在变量中,而不是为板本身分配任何东西,那么为什么我会b = a
然后使用a
,或者只是使用b
来开始?
答案 0 :(得分:3)
在第一个示例中,b
计算为block(board,x,y)
,使用x
当时的值x
。然后,该值将重复用于以下列表推导的所有迭代。
在第二个示例中,block(board,x,y)
在整个列表理解中发生了变化,因此每次迭代时,ok
都会返回不同的结果。
答案 1 :(得分:3)
使用时
x
b
很可能已设置为某个常量,因此x
在列表理解中变为常量。当您使用第二个列表推导时,r
在整个理解过程中具有不同的值(迭代x
),并覆盖函数或模块级别上的任何x
- 因此每次检查是否block(board,x,y)
中的x
变得依赖于您的理解迭代。
为列表推导变量指定一个与x
不同的名称,并注意覆盖变量名称。
这是一个最小的示例,您可以看到变量名称>>> 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)]
[]
被覆盖,以及它如何影响您对函数的每次调用。
{{1}}