Reputation: 48392
I have some simple code that represents a graph using a square boolean matrix where rows/columns are nodes and true represents an undirected link between two nodes. I am initializing this matrix with False values and then setting the value to True where a link exists.
I believe the way I am initializing the list is causing a single bool instance to be referenced by each cell in a given row. The result is that if I set any cell to True all the other cells in that row also become True.
How should I be initializing my square matrix so that all values are false but none are shared by reference with other cells?
import sys
class Graph(object):
def __init__(self, nodeCount, links):
self.matrix = [[False] * nodeCount] * nodeCount
for l in links:
self.matrix[l[0]][l[1]] = True
def __str__(self):
s = " "
for i in range(len(self.matrix)):
s += str(i) + " "
s += "\n"
for r in range(len(self.matrix)):
s += str(r) + " "
for c in range(len(self.matrix)):
s += str(self.matrix[c][r])[0] + " "
s += "\n"
return s
g = Graph(5, [(2,3)])
print g
Also, on GIST
Upvotes: 0
Views: 510
Reputation: 95516
Actually, you've slightly misunderstood the problem. You believe that the boolean references are shared (this is true, but not important-- booleans are immutable, so sharing references to the same object doesn't mean much). What's happened is that the list references are shared, and that's caused your troubles. Let me show you:
Your code is this
[[False] * nodeCount] * nodeCount
What happens is that you get nodeCount
references to a single list with nodeCount
references to False. Multiplying a sequene by an integer gives you a sequence with duplicated references-- they're not copies, they're aliases.
>>> x = [False] * 3
>>> y = [x] * 3
>>> y[0] is y[1]
True
>> # your problem
>>> y[0][0] = True
>>> y[1]
[True, False, False]
So in this case, it means you can't change individual rows, because all the rows are the same list, and changing one row changes all.
to fix this, make new lists for each row:
[[False]*nodeCount for _ in xrange(nodeCount)]
example:
>>> y = [[False]*3 for _ in xrange(3)]
>>> y[0] is y[1]
False
>>> y[0][0] = True
>>> y[1]
[False, False, False]
Upvotes: 5
Reputation: 4578
self.matrix = [[False] * nodeCount] * nodeCount
should be something like
self.matrix = [[False] * nodeCount for _ in range(nodeCount)]
Upvotes: 1