By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,066 Members | 1,841 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,066 IT Pros & Developers. It's quick & easy.

2d class member list of objects not updating

P: 88
I have a problem updating self.tiles[][].type in line 29. Once leaving the for loops in Map's __init__, the tiles list "forgets" the update somehow.

- I've tried adding a setter function for "type" in Tile but that didn't work also tried making the "type" a class level variable but that didn't and wouldn't help anyway.
- I don't suspect its something to do with reference since I'm only working on the instances and never go to the class for any variables.
- It might be that the tiles array in map doesn't contain instances in the way I think they do, but idk.

Would appreciate if anyone tell me why it doesn't update the tiles list after the for loops in __init__.

(debugging print's included)
Expand|Select|Wrap|Line Numbers
  1. import tkinter as tk
  2. from tkinter import *
  3.  
  4. class Tile:
  5.     def __init__(self, type, pos = (0, 0), isPath = False): #, cost):
  6.         self.type = type
  7.         self.pos = pos
  8.         self.isPath = isPath
  9.         #self.cost = cost
  10.  
  11.     def getColor(self):
  12.         if (self.isPath):           # Tile is a part of path
  13.             return "red"
  14.         elif (self.type == "."):    # Traversable tile
  15.             return "white"
  16.         elif (self.type == "#"):    # Intraversable tile
  17.             return "brown"
  18.  
  19. class Map:
  20.     def __init__(self, filename):
  21.         self.width = len(open(filename, "r").readline()) - 1            # Find size of first line
  22.         self.height = sum(1 for line in open(filename))                 # Find nr of lines
  23.         self.tiles = [[Tile(".")] * self.width] * self.height           # Ready tile
  24.  
  25.         print("Map.tiles 2d list content:")
  26.  
  27.         with open(filename, "r") as f:                                  # Open given file
  28.             print("Updating in __init__:")
  29.             for y, line in enumerate(f):                                # For every line
  30.                 for x, letter in enumerate(line):                       # For every letter
  31.                     if (letter != "\n"):                                # Ignore newline
  32.                         self.tiles[y][x].type = letter                  # Update tile type
  33.                         print(self.tiles[y][x].type, end = "")
  34.                         self.tiles[y][x].pos = (x, y)                   # Tell tile where it is on map
  35.                         if (letter == "A"):                             # Save start index
  36.                             self.start = (x, y)
  37.                         elif (letter == "B"):                           # Save goal index
  38.                             self.goal = (x, y)
  39.                 print("")
  40.             print("")
  41.  
  42.             print("Just after updating in __init__:")
  43.             for row in self.tiles:
  44.                 for tile in row:
  45.                     print(tile.type, end = "")
  46.                 print("")
  47.         print("")
  48.  
  49.     def AStar(self, start, goal):
  50.         print("")
  51.  
  52.     def drawMap(self, canvas):
  53.         print("When displaying on screen in drawMap:")
  54.         tileDim = (canvas.winfo_width() / self.width, canvas.winfo_height() / self.height)  # Find tile size
  55.         for y, row in enumerate(self.tiles):                                                # For every row
  56.             for x, tile in enumerate(row):                                                   # For every column in said row
  57.                 canvas.create_rectangle(tileDim[0] * x,                                     # Draw tile
  58.                                         tileDim[1] * y, 
  59.                                         (tileDim[0] * x) + tileDim[0], 
  60.                                         (tileDim[1] * y) + tileDim[1], 
  61.                                         fill = tile.getColor())
  62.                 print(tile.type, end = "")
  63.             print("")
  64.  
  65. root = tk.Tk()
  66. root.title("A* Pathfinding")
  67. root.geometry("720x480")
  68.  
  69. canvas = tk.Canvas(root, width = root.winfo_width(), height = root.winfo_height())
  70. canvas.pack(side="top", fill = "both", expand = True)
  71. canvas.update()
  72.  
  73. obj = Map("./boards/board-1-1.txt")
  74. obj.drawMap(canvas)
  75.  
  76. root.mainloop()
  77.  
Output (terminal):
Expand|Select|Wrap|Line Numbers
  1. Map.tiles 2d list content:
  2. Updating in __init__:
  3. ....................
  4. ....................
  5. .........######.....
  6. ...........A..#..B..
  7. .........######.....
  8. ....................
  9. ....................
  10.  
  11. Just after updating in __init__:
  12. ....................
  13. ....................
  14. ....................
  15. ....................
  16. ....................
  17. ....................
  18. ....................
  19.  
  20. When displaying on screen in drawMap:
  21. ....................
  22. ....................
  23. ....................
  24. ....................
  25. ....................
  26. ....................
  27. ....................
  28.  
Sep 19 '18 #1

✓ answered by Xillez

Solved it by making the "self." variables in Map global using the "global" key word (and removing the "self." of course). It might not be a good thing, but it works

Share this Question
Share on Google+
3 Replies


Expert 100+
P: 618
Some simple print statements should show the problem. For example
Expand|Select|Wrap|Line Numbers
  1. self.tiles[y][x].type = letter
  2. print(self.tiles[y][x])
  3.  
  4. ## this should likely be
  5. self.tiles[y][0][0].type
  6. """ as the class instance is in the first position,
  7.  offset=0, of the sub-list, and the first/only position
  8.  in that sub-list.  print() self.tiles[y][0][0] and/or 
  9.  self.tiles[y][0][0].type to test for yourself
  10.  self.tiles = [[Tile(".")] * self.width] * self.height
  11. """
  12.  
  13. ## A dictionary would work better here IMHO
  14. self.tiles={}
  15. self.tiles[Tile(".")]=self.width] * self.height           
  16.  
Sep 19 '18 #2

P: 88
Appreciate the answer but...

I tried printing with self.tiles[y][0][0] with and without .type and it says "Tile object does not support indexing". The [][][] tries to fetch the a position within a 3d list, but since [[] * width] * height makes a 2d list this is understandable, so the object lies in the inner list.

As far as I understand the code should be correct (coming from a c++/java programming background, which of course doesn't mean that python behaves the same)

But the main problem is that the the 2d list "tiles" looses it's updated state once exiting the for loops updating them (in __init__). I have a print out within the same function and yet it prints only dots... so I suspect it might be something with the self and it not being a Tile object but something else, OR, it might be something with the list (or the initialization of it) that doesn't allow me to update them.
Sep 20 '18 #3

P: 88
Solved it by making the "self." variables in Map global using the "global" key word (and removing the "self." of course). It might not be a good thing, but it works
Sep 20 '18 #4

Post your reply

Sign in to post your reply or Sign up for a free account.