开发者

generating a grid in a function

We made a little script in computer science class for finding the shortest path through a grid of nodes, some interlinked, some not. The griddata is stored in a way that doesn't require to define any new classes, namely in a nested list. For n nodes, the list should have n elements, each being a list with n elements.

grid[a][b] should return the distance from node a to node b, and 0 if the nodes aren't connected or if a and b references to the same node.

for example the list [[0,2,2],[2,0,2],[2,2,0]] would define a grid with 3 nodes, each with a distance of 2 from each other.

Here is the script I wrote that should define such a grid by requesting individual distances from the user:

def makegrid(nodes):
    res=[[0]*nodes]*nodes
    for i in range(nod开发者_高级运维es):
        for j in range(nodes):
            if res[i][j]==0 and not i==j:
                x=raw_input('distance node %d zu node %d: ' % (i,j))
                if x:
                    res[i][j]=res[j][i]=int(x)
                else:
                    res[i][j]=res[j][i]=None
    for i in range(nodes):
        for j in range(nodes):
            if res[i][j] is None:
                res[i][j]=0
    return res

My problem ist that the function isn't quite doing what I intended it to do, and I can't seem to work out why. What it actually does is only running through the requests for the first node, and somehow it does to all the sublists what it should only do to the first (and ignoring that the first element should not be changed).

Can anyone help me figure it out?


 res=[[0]*nodes]*nodes

probably doesn't do what you think it does:

>>> nodes = 3
>>> res=[[0]*nodes]*nodes
>>> res
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> res[0][0] = 'echo'
>>> res
[['echo', 0, 0], ['echo', 0, 0], ['echo', 0, 0]]

Instead of making three separate lists [0,0,0], it gives you three references to the same list:

>>> id(res[0]), id(res[1]), id(res[2])
(4299671960, 4299671960, 4299671960)

Try

res=[[0]*nodes for i in range(nodes)]

instead, and read, e.g., Multiply operator applied to list(data structure) to understand why the difference in mutability of integers and lists explains why the [0]*nodes part seems to behave like you'd expect -- i.e. why the above answer has multiple copies of ['echo', 0, 0], not ['echo', 'echo', 'echo'] -- even though the final "*nodes" doesn't.


I fell for that trap, too. List multiplication does not do what you expect it to. Check out this thread.

Easy workaround using list comprehension instead:

# res=[[0]*nodes]*nodes
res = [[0 for j in range(nodes)] for i in range(nodes)]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜