Need help with a two-dimensional array

Hello there! I’m an experienced coder who’s just getting into Python for the first time. I know several versions of BASIC, Pascal, C, C++, C#, PHP, MySQL… and so on. Here’s what I have:

1  2 3  4 5  6 7 8

A X X X X X X X X
B X X X X X T X X
C X X X X X X X X
D X X X X X X X X
E X X X X X X X X
F X X X X X X X X
G X X X X X X X X
H X X X X X X X X

This is a simple two-dimensional array. Row 2 Column 6 is “T”. Doing this in C# or VB is easy. In Python? I’m having trouble.

I created my variable:
ball = [[0]*9]*9

… but ball[2][6] = 2 seems to assign the value to the entire column, which I don’t want. I know that what I’m trying to do is possible, and it’s probably pretty straightforward, but I’m missing something fundamental here.

Can you please direct me to the proper method of creating the variable, and changing one single element? Thanks!

[0] * 9 makes 9 references of the int 0 and places them in a list. All the zeros are the same, but that’s okay because you can’t ever change them. When you put a new element in the list, nothing happens to the old ones.

[[0]*9]*9 makes 9 references of that previous list. This is a problem. Since there’s only one list, when you change an element in it, that change appears over all 9 references to it. You need to have 9 independent lists for your rows. So you need to be a bit more verbose here. Something like…

ball = [[0]*9 for _ in range(9)]
ball[2][6] = "T"

What you’ve bumped into here, David, is one of Python’s fundamentals: Python defaults to treating almost everything as an object. As bowlOfRed mentioned, the ’ * ’ operator replicates list objects. Your value assignment affects all rows because the first list is a reference to a [ [0] * 9 ] 'list of zeroes' object..

The second dimension of your 2-dimensional list is a list of references to the first list of zeroes. One would expect that the rows would be separate instances but they aren’t. This is an interesting feature of Python but can take some getting used to, to say the least.

The elements in the first list object are values (and not objects) because ‘0’ is a pure value, not an object. In other words, this first list is a list of independent instances of the value ‘0’.

This will create a list of independent items in a 9x9 array that you can address individually:

ballField = [[0 for x in range(9)] for y in range(9)]
ballField[1][3] = 1   # note that the coordinates are [Y][X] with top left origin.

The above is a refactored version of BowlOfRed’s code using explicit references so that the parts are more evident.
You’ve no doubt noticed that list indices are Zero-based.

Lists have some interesting behaviors that you can leverage, like using a negative index to wrap around backward starting from the end (in which case, ‘[-1]’ indexes to the last item since the first item is ‘[0]’).

for row in range(len(ballField)):   # prints the ballfield in a square layout.
    print(ballField[row])

Wow. Bowl of Red’s change (to ball = [[0]*9 for _ in range(9)]) worked!! Thanks a lot!

A ‘two-dimensional array’ or ‘flat database’ (such as a single spreadsheet) can be represented by a Python Dictionary, with the key values representing the cells. This script will output columns a – h / row zero, but that’s simply as a visualization; the idea I have (and use) is to see this as a virtual object that can be accessed with simple code, rather than displaying the entire dataset, as the maintenance overhead would be a bit of a mare.

#!/usr/bin/python3

vert = '\t'+'\u2502'+'\t'
columns = ''
rows = ''

lstCol = ['a','b','c','d','e','f','g','h']
lstRow = [0, 1, 2, 3, 4, 5, 6, 7]
dictData = {
    'a0' : 10,
    'b0' : 20,
    'c0' : 30,
    'd0' : '', #empty
    'e0' : 'rob42',
    'f0' : 100,
    'g0' : 200,
    'h0' : 300
    }
dictIndex = ['a0','b0','c0', 'd0', 'e0', 'f0', 'g0', 'h0']

for column in range(len(lstCol)):
    columns += vert + lstCol[column]

rows += str((lstRow[0]))+vert
for row in range(len(dictIndex)):
    rows += str(dictData[dictIndex[row]])+vert

print(columns+vert)
print(rows)

With the above, say you want to total cells f0, g0 and h0:

total = dictData['f0']+dictData['g0']+dictData['h0']

Not sure if this adds anything of value to this thread or even if the above code could be compounded, but take it for what its worth.