-2

When I try to call print_frontier() that belongs to Frontier class, AttributeError: 'NoneType' object has no attribute 'print_puzzle' occurs, which print_puzzle() is a member function of State class and is called inside print_frontier().

print_frontier() is expected to print all the puzzles stored in self.nodes by printing each puzzle using print_puzzle().

Something worth mentioning is that when I remove the frontier.increase_limit() in the main program, the code succeeded to print a single puzzle as expected, I am afraid that the problem should be inside increase_limit() but I cannot figure out the problem.

class Frontier:

    ...


    def increase_limit(self) -> None:
        nodes_to_remove = []
        nodes_to_add = []
        current_nodes = self.nodes.copy()
        self.nodes.clear()

        for node in current_nodes:

            if node is None:
                raise Exception('"node" is a NoneObject')

            empty_tile_pos = node.get_empty_tile_pos()

            if empty_tile_pos not in [0, 1, 2]:
                nodes_to_add.append(
                    State(node.puzzle, node.path).move_tile('up'))
            if empty_tile_pos not in [6, 7, 8]:
                nodes_to_add.append(
                    State(node.puzzle, node.path).move_tile('down'))
            if empty_tile_pos not in [0, 3, 6]:
                nodes_to_add.append(
                    State(node.puzzle, node.path).move_tile('left'))
            if empty_tile_pos not in [2, 5, 8]:
                nodes_to_add.append(
                    State(node.puzzle, node.path).move_tile('right'))

            nodes_to_remove.append(node)

        for node in current_nodes:
            if node not in nodes_to_remove:
                self.nodes.append(node)

        self.nodes.extend(nodes_to_add)
        self.depth += 1

    def print_frontier(self):
        for node in self.nodes:
            node.print_puzzle()  # calling a function of the State class

Here is the "State" class for reference:

class State:

    ...

    def print_puzzle(self):
        print()
        for tile in self.puzzle:
            if self.puzzle.index(tile) in [2, 5, 8]:
                print(tile, end='\n')
            else:
                print(tile, end=' ')
        print(self.path, end='\n')

And here is the main program when I tested my classes:

start_state = State([0, 2, 4, 5, 7, 6, 8, 3, 1])
frontier = Frontier(start_state)
frontier.increase_limit(). # works well without this line
frontier.print_frontier()

  • 1
    `path = []` in the initializer of `State` is problematic. It is a [mutable default argument](https://stackoverflow.com/q/1132941/4996248). This is unlikely to be the problem which led to that error message. Please give a [mcve] with an emphasis on *minimal*. Before asking the question, you should be able to pare it down to show the essence of the problem. As it is, there is way too much irrelevant code in your question. – John Coleman Oct 01 '20 at 10:44

1 Answers1

0

In the increase_limit method you create a State instance, call a method on that and append the return value of the method to a list.

nodes_to_add.append(
    State(node.puzzle, node.path).move_tile('up')
)

For this to work, move_tile() would need to return self, which is not common in python.
If you don't want to use a temporary variable for the State object, you can do this:

nodes_to_add.append(State(node.puzzle, node.path))
nodes_to_add[-1].move_tile('up')
Wups
  • 2,489
  • 1
  • 6
  • 17