Thomas Mitchell
Thomas Mitchell

Reputation: 1071

Python list index out of range

I'm having some issues filling a list in Python. I keep getting a list index out of range error. The output of len(network) is 7 so I figured filling it from 0-6 should work to give me a 7x7 list.

def fillNodeTable():
  nodeTable = []
  for x in xrange(0, (len(network) -1)):
    for y in xrange(0, (len(network) -1)):
      nodeTable[x][y].append(Node)
  print nodeTable

So I ended up with this and it works

n = len(network)
nodeTable = [[Node]*n for x in xrange(n)]

When I print the nodeTable to debug I get the following:

<class __main__.Node at 0xb737914c>

Is this just because I'm appending a class to each entry or have I done something else wrong here?

Upvotes: 1

Views: 4650

Answers (5)

lvc
lvc

Reputation: 35089

If we go through your code a step at a time, the problem becomes clearer:

nodeTable = []

So, nodeTable is an empty list. We start a loop, and immediately start another one - so take the first iteration, where x and y are both 0.

 nodeTable[x][y].append(Node)

So this says: find the 0th item in nodeTable, find the 0th item in that, and call append on it. This will error, because nodeTable is empty - it has no 0th item to find. So, the solution is to give it one before we reach this point. This will work:

for x in xrange(0, (len(network) -1)):
     nodeTable.append([])
     for y in xrange(0, (len(network) -1)):):
         nodeTable[x].append(Node)

However, there's still a couple of things to note: first, this will give you (len(network) - 1) * (len(network) -1) copies of Node, arranged in nested lists. If Node is a class like its name suggests, that means you'll get that many copies of that class, not that many individual instances of that class. For that, you would: .append(Node).

The next thing is that, as others have mentioned, this can be written as a nested list comprehension:

[[Node() for y in xrange(0, (len(network -1))] for x in xrange(0, (len(network) -1))]

For exactly the same effect, though probably a bit more efficient.

Third, xrange will assume the 0 if you don't give it explicitly - ie,

 xrange(len(network) - 1)

Is equivalent to your:

 xrange(0, (len(network) - 1))

Finally, xrange(len(network) - 1) probably isn't what you want anyway. This will make nodeTable and each list inside it one element shorter than network. xrange stops before the stop value, not at it. This means you probably want [for x in xrange(len(network))]. But doing it as a list comprehension, we no longer use x or y, which means we don't need them to take numbers in particular:

[[Node() for x in network] for y in network]

, as suggested by @jcollado , will do the same thing.

Upvotes: 1

vinothM
vinothM

Reputation: 195

The way you have defined the list is the problem. You have defined you list as single dimensional list and try to use it as multi dimensional list. Try the below solution.

Code:

def fillNodeTable():

nodeTable = [[[] for i in range(7)] for i in range(7)]
for x in xrange(0, (len(network))):
    for y in xrange(0, (len(network))):
        nodeTable[x][y].append("Node")
for x in xrange(0, (len(network))):
    print
    for y in xrange(0, (len(network))):
        print nodeTable[x][y],

Output:

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node'] ['Node']

Upvotes: 0

Kimvais
Kimvais

Reputation: 39628

The problem is that xrange(0, 6) will give you 6 items, from 0 to 5.

>>> len(xrange(0,6))
6
>>> len(xrange(0,7))
7

Upvotes: 3

jcollado
jcollado

Reputation: 40424

I think you can use a list comprehension since it would be clearer:

nodeTable = [[Node for x in network] for y in network]

Upvotes: 4

ustun
ustun

Reputation: 7041

I think you are porting a MATLAB code. You are getting the out of range error on nodeTable. You initialize it to an empty array.

Try something like this, or use the array classes in numpy:

> a = []
>>> for i in xrange(3):
...     a.append([])
...     for j in xrange(3):
...             a[i].append(i+j)

or

n = 7
a = [[0]*n for x in xrange(n)]

Upvotes: 2

Related Questions