为什么这些看似相同的代码片段的行为有所不同? (Python 3)

时间:2016-05-21 13:19:52

标签: python python-3.x

我正在写一个数独求解器,并遇到了这种奇怪的行为。如果我执行以下操作:

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只是电路板大小的平方根,而电路板只是数字列表的列表。 (像Nlen这样的地方的原因是它应该适用于非9x9的电路板)

我的问题很简单:为什么这些事情会有所不同?它只是读取值并将它们存储在变量中,而不是为板本身分配任何东西,那么为什么我会b = a然后使用a,或者只是使用b来开始?

2 个答案:

答案 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}}