一旦在python中反映出来,值就会改变

时间:2014-09-23 04:13:16

标签: python python-2.7

sz = input('Enter the size of the board: ')
board = [[0 for j in xrange(sz)] for i in xrange(sz)]

for row in range(sz):
    for col in range(sz):
        board[row][col] = input()

pqval = 1
steps = 2
start_state = sz , board , pqval ,steps

t=1
for row in range(sz):
    for col in range(sz):
        board[row][col] = t
        t=t+1
board[sz-1][sz-1] = 0
end_state = sz, board , pqval ,steps

print "Here is the starting position: "
print start_state

print "Here is the ending position: "
print end_state

我无法理解为什么更改也会在start_state的board属性中发生,即使它是在之前构建的。我肯定做了一些愚蠢的事。 python的新手来自C / C ++背景,这种行为似乎很奇怪。

如果我希望元组具有所有4个值并且希望更改一个元组的属性而不将其复制到任何地方,那么该怎么办?

1 个答案:

答案 0 :(得分:1)

在Python中,赋值与C ++非常不同;事实上,变量的概念是不同的。

  • 在C ++中,变量是存储值的内存地址,以及类型。您可以获取变量的引用甚至指针。赋值意味着将值从一个变量复制到另一个变量。*
  • 在Python中,值会处理自己的存储和类型;变量只是值的名称。一个值可以有任意数量的名称。**

* ...通常;你可以覆盖它来表示你想要的任何东西。

**好吧,任何正数。一旦它没有名称,它将被垃圾收集器清理。


你可能在简单的情况下知道这一点:

>>> a = [0]
>>> b = a
>>> b[0]
0
>>> a[0] = 1
>>> b[0]
1

但在每个案例中都是如此。所以,当你这样做时:

start_state = sz , board , pqval ,steps

...只是意味着start_state[1]成为同一个board对象的另一个名称。 start_state[1]是一个“复杂目标”而不是一个普通变量的事实并不重要;您通过分配到start_state而不是直接分配给start_state[1]而间接创建它的事实并不重要;它仍然是一个名字。

当然szpqvalsteps也是如此,但你永远不会改变这些值 - 因为你不能;字符串和数字不能改变。

重新分配pqval不会将1变为其他数字; *只会使pqval成为其他号码的名称,而start_state[2]仍然是原来的。同样,重新分配board也不会影响start_state[1]。它只是在原位变异board

*如果你能做到这一点,那将是一个超级大国的地狱,但任何使用它都可能打破宇宙......

当你使用像+=之类的运算符时,这会变得有点棘手,特别是如果你已经习惯了C ++。在C ++中,+=总是意味着改变一个变量,无论它是否意味着改变一个值;当你无法改变变量时,+=就行不通了。在Python中,没有“变异变量”这样的东西;它总是意味着重新分配变量,无论它是否意味着改变一个值;当你无法改变某个值时,+=只会重新分配一个新值。


如果要制作副本,则必须明确地进行复制。例如,任何这些都可行:

start_state = sz, board[:], pqval, steps
start_state = sz, copy.copy(board), pqval, steps
start_state = copy.deepcopy((sz, board, pqval, steps))

或者,或者,您可以使board的工作方式与其他对象相同 - 从不改变它,只将其重新分配给新列表。例如,而不是:

    board[row][col] = t

......你可以这样做:

    board = [[val if i, j != row, col else t for j, val in enumerate(row)]
             for i, row in enumerate(board)]

当然这有点傻,但通常你可以将循环重写为生成新列表的列表理解,并且愚蠢。例如:

board = [[i*sz+j for j in range(sz)] for i in range(sz)]