Search code examples
pythonpython-2.7oopa-stargrid-search

Python saving value as an instancemethod instead of integer


So, I am currently writing a program that randomly generates a grid maze. The following code segment is the class definition of a single "cell" of the grid. I have defined 2 getter methods get_row and get_col, which can retrieve the coordinates of the cell. I believe this is where the issue lies.

class cell: #Node storing each cell of grid
    def __init__(self, rowNum=None, colNum=None):
        self.rowNum = rowNum
        self.colNum = colNum
        self.blocked = 0 # 0 denotes False, all cells are initially unblocked
        self.f = 0 # Distance from start node
        self.g = 0 # Distance from goal node
        self.h = 0 # Total cost ( h = f + g )
        self.parent = None
    def get_row(self):
        return self.rowNum
    def get_col(self):
        return self.colNum
    def isBlocked(self):
        if self.blocked == 0:
            return 0
        if self.blocked != 0:
            return 1

Then, I use the following segment to traverse the grid and randomly determine certain squares as the start and end. I save these coordinates as start_row, start_col, end_row, and end_col.

# List containing all the unblocked cells
unblockedCells = [cell() for i in range(numUnblocked)]

start_row = -1
start_col = -1
end_row = -1
end_col = -1

# Randomly picks 2 unblocked cells to be the starting and ending point
def set_start_and_end():
    global start_row
    global start_col
    global end_row
    global end_col
    ctr1 = 0
    for i in range(totalRows):
        for j in range(totalCols):
            if cellsArray[i][j].blocked == 0:
                unblockedCells[ctr1] = cellsArray[i][j]
                ctr1 = ctr1+1
    
    #Initialize start position
    startIndex = random.randint(0,len(unblockedCells)-1)
    start_row = unblockedCells[startIndex].get_row
    start_col = unblockedCells[startIndex].get_col

    #Initialize target position
    endIndex = random.randint(0, len(unblockedCells)-1)
    end_row = unblockedCells[endIndex].get_row
    end_col = unblockedCells[endIndex].get_col

    print("Start: (",start_row,", ",start_col,") End: (",end_row,", ",end_col,")")

set_start_and_end()

However, when I try to access the values of start_row and start_col later in the program, I receive the error list indices must be integers, not instancemethod

My question is, why are start_row and start_col being stored as instancemethod and not as integers?


Solution

  • Here's a small snippet to illustrate the different options

    class Cell:
    """Doc strings go here btw, not as comments. Also take a look at pep8 naming conventions: https://www.python.org/dev/peps/pep-0008/#naming-conventions"""
        def __init__(self, row_num = None, col_num = None):
            self.row_num = row_num # A public instance member - you can get and set this directly without the need for function
            self._col_num = col_num # A private member. By convention, you should not get or set this directly
        def get_row(self):
        """This is a method, you need so call it using parenthesis i.e. .get_row()"""
            return self.row_num
        @property
        def col_num(self):
        """This is property being used to expose a private member. You don't need parenthesis to call it."""
            return self._col_num
    
    
    my_cell = Cell(1, 2)
    print(my_cell.row_num)  # row_num is a public member, you can just access it directly
    print(my_cell.get_row)  # get_row is a method, so this will print the actual function
    print(my_cell.get_row())  # this calls the function and prints the integer
    print(my_call.col_num)  # because of the property decorator, we don't have to call this function but can treat is as if it was a member. But note it would be weird to name it get_... now as verbs imply functions. 
    

    In your case I would just use a public instance member. There is no need for any of your functions. In fact this whole object looks like it could just have been a named tuple:

    from typing import NamedTuple
    class Cell(NamedTuple):
        row: int
        col: int
        blocked: bool
    

    or if you're using python>=3.8 a dataclass

    from dataclasses import dataclass
    @dataclass
    class Cell:
        row = None
        col = None
        blocked = False