为什么 class 节点不在方法调用之外保存 children? Python

Why are class nodes not saving children outside of method call? Python

回购: https://github.com/icarus612/mazeRunner-PY/tree/stack-overflow

问题: 我不知道为什么节点不在运行器方法调用之外保存它们的 children。

项目:我正在用几个classes构建一个迷宫跑道,一个节点class用于存储迷宫中的点,一个迷宫class 进入迷宫并评估什么是墙,什么是空间,以及跑步者 class 绘制迷宫地图,找出是否有可能的路线,然后解决路线。还有一个求解器脚本可以接受命令行输入。最初我已经建立了一个工作 "runner" 但它没有给出正确的路线,所以我回到了绘图板(如果有人可以告诉我跑步者没有给出正确的路线那也很酷但这不是手头的问题)

为什么节点不保存在方法外children?

此处的代码将是针对我 运行 遇到的问题的精简版。

节点class:

class Node:
    def __init__(self, value):
        self.value = value 
        self.children = []
        self.visited = []

    def add_visited(self, node):
        self.visited.append(node)   

    def add_child(self, child_node):
        self.children.append(child_node) 

    def add_path(self, node_path):
        if not self.path:
            self.path = node_path
        else:
            self.path = self.path if len(self.path) < len(node_path) else node_path

    def remove_child(self, child_node):
        self.children.discard(child_node)

亚军Class:

class Runner:
    def __init__(self, maze):
        self.open_nodes = []
        self.visited = []
        self.start = None
        self.end = None
        self.maze = maze
        self.completed = False
        self.mapped_maze = []
        self.node_paths = []
        self.find_end_points()
        self.get_open_nodes()

    def get_open_nodes(self):
        p = self.maze.layout
        for x in range(len(p)):
            for y in range(len(p[x])):
                if p[x][y] != self.maze.wall_char:
                    self.open_nodes.append(Node((x, y)))
        for i in self.open_nodes:
            self.look_around(i)
            print(i.children) #should print something !and does!:)

    def find_end_points(self):
        for x in range(len(self.maze.layout)):
            for y in range(len(self.maze.layout[x])):
                p = self.maze.layout[x][y]
                if p == self.maze.start_char:
                    self.start = Node((x, y))
                elif p == self.maze.end_char:
                    self.end = Node((x, y))

    def look_around(self, node):
        for i in self.open_nodes:
            if i.value[0]-1 == node.value[0] and i.value[1] == node.value[1]:
                node.add_child(i)
            if i.value[0]+1 == node.value[0] and i.value[1] == node.value[1]:
                node.add_child(i)
            if i.value[1]-1 == node.value[1] and i.value[0] == node.value[0]:
                node.add_child(i)
            if i.value[1]+1 == node.value[1] and i.value[0] == node.value[0]:
                node.add_child(i)       

    def make_node_paths(self, point=None):
        if point == None:
            point = self.start
        print(point.value, point.children)
        for i in point.children:
            if i.value not in point.visited:
                point.add_visited(point.value)
                if point.value == self.end.value:
                    self.node_paths.append(point.path)
                    self.completed = True

                self.make_node_paths(i)

迷宫Class:

class Maze:
    def __init__ (self, layout=None, start_char="s", end_char="e", wall_char="#", open_char=" ", build=(10, 10)):
        self.wall_char = wall_char
        self.start_char = start_char
        self.end_char = end_char
        self.open_char = open_char
        self.layout = layout
        if layout:
            self.width = len(layout[0])
            self.height = len(layout)
        else:
            self.build_new(build[0], build[1])

求解器脚本:

maze = Maze(build=(20, 20)) 

runner = Runner(maze)
print(runner.start.value, runner.start.children) #point that should be logging something !but doesnt!:(
runner.make_node_paths()
complete = "Yes" if runner.completed else "No"
print(f"Is maze possible? {complete}")

两个打印语句的控制台:

[<node.Node object at 0x101060780>] #what runner.start.children should be
[<node.Node object at 0x1010604a8>, <node.Node object at 0x100d253c8>]
[<node.Node object at 0x1010604e0>, <node.Node object at 0x1010606d8>]
[<node.Node object at 0x1010604a8>, <node.Node object at 0x100d25400>]
[<node.Node object at 0x100d25470>]
[<node.Node object at 0x1010601d0>, <node.Node object at 0x100d254a8>]
[<node.Node object at 0x1010604e0>, <node.Node object at 0x100d25518>]
[<node.Node object at 0x1010606d8>, <node.Node object at 0x100d25438>, <node.Node object at 0x100d25588>]
[<node.Node object at 0x100d25400>, <node.Node object at 0x100d25470>]
[<node.Node object at 0x101060710>, <node.Node object at 0x100d25438>, <node.Node object at 0x100d255c0>]
[<node.Node object at 0x101060780>, <node.Node object at 0x100d254e0>]
[<node.Node object at 0x100d254a8>, <node.Node object at 0x100d25518>]
[<node.Node object at 0x100d253c8>, <node.Node object at 0x100d254e0>, <node.Node object at 0x100d25550>]
[<node.Node object at 0x100d25518>, <node.Node object at 0x100d25588>]
[<node.Node object at 0x100d25400>, <node.Node object at 0x100d25550>]
[<node.Node object at 0x100d25470>]

(1, 1) [] #runner.start.value and what runner.start.children comes in as

其他说明: 我没有包括一些跑步者 class 和大多数获取输入的求解器脚本以及大多数构建迷宫的迷宫脚本。我遇到的问题是,当我创建节点并在初始方法中为这些节点 children 保存时,如您所见,已注销,但是当我尝试在求解器函数的下一行中将其注销时我蹲下了。我什至不知道我在这里看的是什么类型的问题。这是记忆还是我保存它们的方式有问题?我试图将它们从集合中切换到数组中,但这也不起作用。如果它全部在同一个方法中,它似乎有效,但如果它在 2 个单独的方法中则无效。它就像它在退出方法后丢失那些 children 一样。

更新:

我发现这个 link 回答了我的问题,但没有真正给出答案:nested classes in Python

读完这篇文章后,我想知道我是否需要让 classes 以某种方式相互扩展?它提供了对可能发生的事情的洞察,但没有真正回答我如何解决我的问题,而且我没有使用扩展的 classes。我已经尝试寻找方法来确保副本是深层副本,但即使使用 copy.deepcopy 代码也保持不变

问题在于我如何在 find_end_points 函数中保存 self.start 和 self.end。


    def find_end_points(self):
        def check(node_val):
            if node_val not in [i.value for i in self.open_nodes]:
                node = Node(node_val) 
            else:
                for i in self.open_nodes:
                    if i.value == node_val:
                        node = i
            return node
        for x in range(len(self.maze.layout)):
            for y in range(len(self.maze.layout[x])):
                p = self.maze.layout[x][y]
                if p == self.maze.start_char:
                    self.start = check((x, y))
                elif p == self.maze.end_char:
                    self.end = check((x, y))

是新函数,现在我得到了正确的开始值和结束值以及保存给它们的子项。这不是在方法中保存全局或局部变量的问题。