Python - variable is getting set to 0 and can't figure out why
Question: Okay, so I'm making a little game with pygame and building the map by
generating tiles to a multidimensional array. In order to do that I'm using
two for loops.

    
    
    def create(this, t):
    
        if t == "grasslands":
            for j in range(0, this.numRows):
                for i in range(0, this.numColumns):
                    this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
                this.row.append(this.column)
    

The value for **j * this.tileWidth** is getting passed into the Tile
initialization correctly. After though the **column[whatever].x** value is
still 0. The **y** value gets set just fine, and if I use **i** or any other
value instead of **j** things work just fine. Is this something I'm doing
wrong or something wonky with Python?

**_mapgen.py_**

    
    
    import pygame
    from sprite import *
    from assets import *
    
    class mapG:
    
    def __init__(this, resw, resh):
        this.numRows = 3
        this.numcolumns = 3
        this.tileWidth = 128
        this.tileHeight = 128
    
        this.row = []
        this.column = []
        this.width = this.numRows * this.tileWidth
        this.height = this.numcolumns * this.tileHeight
    
    
    def create(this, t):
    
        if t == "grasslands":
            for j in range(0, this.numRows):
                for i in range(0, this.numcolumns):
                    this.column.append(this.Tile("grass", j * this.tileWidth, i * this.tileHeight))
                this.row.append(this.column)
    
    
    def tileAt(this, x, y):
        pass
    
    def moveRight(this):
        for j in range(0,this.numRows):
            for i in range(0, this.numcolumns):
                this.row[j][i].incX(1)
    
    def Update(this, src):
        for j in range(0,this.numRows):
            for i in range(0, this.numcolumns):
                this.row[j][i].Update(src)
                print(this.row[j][i].y, this.row[j][i].x)
    
    class Tile:
    
        def __init__(this, name, xpos, ypos):
            this.y = ypos
            this.x = xpos
            this.image = assets.tile[name + ".png"]
            this.sprite = sprite(this.image, this.x, this.y, 100, 100)
    
        def incX(this, amount):
            this.sprite.IncX(amount)
    
        def decX(this, amount):
            this.sprite.DecX(amount)
    
        def incY(this, amount):
            this.sprite.IncY(amount)
    
        def decY(this, amount):
            this.sprite.DecY(amount)
    
        def Update(this, src = None):
            if src != None:
                this.sprite.Update(src)
    

**_sprite.py_**

    
    
    import pygame
    import assets
    
    class sprite:
    
    def __init__(this, image, xpos, ypos, width = None, height = None):
    
        this.image = image
        this.x = xpos
        this.y = ypos
        this.width = width
        this.height = height
    
        if this.width != None and this.height != None:
            this.image = pygame.transform.scale(image, (this.width,this.height))
    
    def GetPos(this):
        return (this.x, this.y)
    
    def IncX(this, amount):
        this.x += amount
    
    def IncY(this, amount):
        this.y += amount
    
    def DecX(this, amount):
        this.x -= amount
    
    def DecY(this, amount):
        this.y -= amount
    
    def Update(this, src = None):
        if src != None:
            src.blit(this.image, this.GetPos())
    


Answer: I believe the issue you have comes from your use of the `this.column` variable
in the `create` method.

You're only creating one column list (in `__init__`) and then reusing it for
all the columns of your map. This won't work.

Your `this.row` list ends up having multiple references to the same column
list, which ends up containing all of the `Tile` objects you create. You only
see some of them later, since your iteration code uses predefined dimensions,
rather than actually iterating over the whole of the lists.

To understand this, try to imagine how the iteration progresses for a 2x2 grid
(ignoring the tile dimensions). I'm putting each `i` and `j` value on it's own
line to show how it progresses, and giving the values of `row` and `columns`
after each step side:

    
    
    j=0:
       i=0:
          column.append(Tile(i, j))
          # column is [Tile(0, 0)]
          # row is []
    
       i=1:
          column.append(Tile(i, j))
          # column is [Tile(0, 0), Tile(0, 1)]
          # row is []
    
       row.append(column)
       # column is [Tile(0, 0), Tile(0, 1)]
       # row is [[Tile(0, 0), Tile(0, 1)]]
    
    j=1: # column is not reset!
       i=0:
          column.append(Tile(i, j))
          # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0)]
          # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0)]]
    
       i=1:
          column.append(Tile(i, j))
          # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
          # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]
    
       row.append(column)
       # column is [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]
       # row is [[Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)],
       #          [Tile(0, 0), Tile(0, 1), Tile(1, 0), Tile(1, 1)]]
    

The `row` list contains two references to the same `column` list of four
tiles. Your code had intended to add the first two `Tile(0, 0)` and
`Tile(0,1)` to the first column, then the last two tiles `Tile(1, 0)` and
`Tile(1, 1)` to the second column. But because the same list was used both
times, you end up with all the values together, and then the whole bunch
repeated. When you iterate, you're only seeing the repeated values on the left
part of the diagram above.

Here's how to fix it:

    
    
    def create(this, t):
        if t == "grasslands":
            for j in range(0, this.numRows):
    
                column = [] # Create a new list! This is the key!
    
                for i in range(0, this.numColumns):
                    column.append(this.Tile("grass",
                                  j * this.tileWidth,
                                  i * this.tileHeight))
                this.row.append(column)
    

You can get rid of the line in the constructor that initializes `self.column`
too. It's only needed temporarily, so there's no need to use an instance
variable.

