Python中值的变化到处反映出来

48 阅读3分钟

在Python中,有一个常见的问题是,当在一个元组中改变一个值时,这个改变会反映在所有引用该元组的其他变量中。这使得很难保持变量的独立性,并可能导致难以追踪的错误。例如,以下代码演示了这个问题:

huake_00152_.jpg

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

运行这段代码,你会发现,当你在循环中改变board中的值时,start_state中的board值也会发生改变。这是因为在Python中,元组中的值是引用,而不是副本。这意味着,当你在一个元组中改变一个值时,你实际上是在改变所有引用该元组的其他变量中的值。

解决方案

有几种方法可以解决这个问题。一种方法是使用copy.deepcopy()函数来创建元组的副本。copy.deepcopy()函数会创建一个元组的新副本,其中包含原始元组中所有值的副本。这意味着,当你改变副本中的值时,原始元组中的值不会受到影响。

import copy

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 , copy.deepcopy(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

另一种方法是使用元组的切片操作符来创建元组的副本。元组的切片操作符会创建一个元组的新副本,其中包含原始元组中指定范围的值。这意味着,当你改变副本中的值时,原始元组中的值不会受到影响。

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

最后,你还可以使用列表推导式来创建元组的副本。列表推导式会创建一个列表的新副本,其中包含原始列表中指定范围的值。这意味着,当你改变副本中的值时,原始列表中的值不会受到影响。

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 , [row[:] for row in 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