While understanding backtracking using 8 queens I came across an issue of list definition in python
def place(board, row, column):
for c in range(column):
if board[c]==row:
return False
elif abs(board[c]-row) == abs(c-column):
return False
return True
def Queens(board, column):
#do stuff
for row in range(8):
if place(board, row, column):
board[column]=row
if column==7:
return True
else:
if(Queens(board, column+1)):
return True
else:
#backtracking
board[column]= -1
if row==8:
return False
def HailHydra(board):
print("------------------****------------------")
data = [['_']*8 for _ in xrange(8)]
for i in xrange(8):
data[i][board[i]]='Q'
for i in xrange(8):
print data[i]
def main():
position = 2
board = [-1]*8
if(position>=0 and position<8):
board[0]=position
if(Queens(board, 1)):
HailHydra(board)
return True
else:
print "Cant have board with initial queen at:", position
return False
else:
print "Invalid input"
return False
main()
This code results in output
------------------****------------------
['_', '_', 'Q', '_', '_', '_', '_', '_']
['Q', '_', '_', '_', '_', '_', '_', '_']
['_', '_', '_', '_', '_', '_', 'Q', '_']
['_', '_', '_', '_', 'Q', '_', '_', '_']
['_', '_', '_', '_', '_', '_', '_', 'Q']
['_', 'Q', '_', '_', '_', '_', '_', '_']
['_', '_', '_', 'Q', '_', '_', '_', '_']
['_', '_', '_', '_', '_', 'Q', '_', '_']
In the above code if we exchange
data = [['_']*8 for _ in xrange(8)]
this line in the main functions with
data = [['_']*8]*8
The output changes to
------------------****------------------
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
['Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q']
According to my understanding of python the two different list definitions should result in same output, but it appears that i missing some details which are resulting the the above mentioned situations.
My question is
What exactly is the difference between the list definitions of the following 2 types
1. [['_']*8 for _ in xrange(8)]
and
2. data = [['_']*8]*8
which led to generations to these 2 different output
3 Answers 3
By typing [['_']*8]*8
you are creating a list of the same list instance:
ls = [['_']*8]*8
ls[5][5] = 'Q'
print ls
Here you can see, 'Q' is placed 8 times.
Comments
The first constructs a list of 8 separate lists. The second constructs a list containing the same list 8 times.
Comments
[['_']*8 for _ in xrange(8)]
and data = [['_']*8]*8
produces actually exactly same output as long as they are not touched
>>> a = [['_']*8 for _ in xrange(8)]
>>> b = [['_']*8]*8
>>> a == b
True
But as @hurturk and @Blotosmetek rightly said, b is actually a copy of same list over and over again. Any change in one list in b, will have same impact on other lists in b.
Whereas a, is list of independent lists.
>>> a[1][1]='Q'
>>> b[1][1]='Q'
>>> a == b
False
>>>