Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:嵌套函数中的引用变量';s外部范围(非全局)_Python_Python 3.x_Tree Traversal - Fatal编程技术网

Python:嵌套函数中的引用变量';s外部范围(非全局)

Python:嵌套函数中的引用变量';s外部范围(非全局),python,python-3.x,tree-traversal,Python,Python 3.x,Tree Traversal,我试图递归一棵树并跟踪遍历的路径,直到找到我要查找的元素为止。然而,我遇到两个问题: 虽然我当前的代码返回正确的解决方案,但它有点粗糙。我必须将正在遍历的当前路径推送到final\u path,然后返回final\u path[0]。如果我只是尝试设置final\u path=path,其中final\u path是在外部范围中定义的,则它不起作用。如何引用嵌套函数的外部范围 如果该值不在树中,我将以预先排序的方式遍历整个树。是否有任何方法来构造代码,以便我可以说“如果在遍历结束时,我们没有找到

我试图递归一棵树并跟踪遍历的路径,直到找到我要查找的元素为止。然而,我遇到两个问题:

  • 虽然我当前的代码返回正确的解决方案,但它有点粗糙。我必须将正在遍历的当前路径推送到
    final\u path
    ,然后返回
    final\u path[0]
    。如果我只是尝试设置
    final\u path=path
    ,其中
    final\u path
    是在外部范围中定义的,则它不起作用。如何引用嵌套函数的外部范围

  • 如果该值不在树中,我将以预先排序的方式遍历整个树。是否有任何方法来构造代码,以便我可以说“如果在遍历结束时,我们没有找到目标元素,那么只返回
    []
    而不是完整路径”。我意识到我可以循环检查每个元素,但这似乎是多余的

  • 代码:


    在Python3.x中,只需使用关键字
    nonlocal

    您可以在使用
    global
    的地方使用它:在内部函数的开头:

    def get_path(root, data, path):
        final_path = ...
    
        def pre_order(tree, path):
            nonlocal final_path
            ...
        ...
    
        return final_path
    
    即使在Python2.x中,只要引用一个变量,就会自动授予您对该变量的读访问权,但决不会授予写访问权。请注意,如果引用的对象是可变对象,如列表或字典,则可以在内部函数中进一步修改它

    在Python 3.0中引入了
    非本地
    关键字,您可以对外部函数作用域中定义的变量拥有完全的写访问权。]


    在Python2.x中,将内部函数写入外部作用域列表中的固定元素可能是解决此问题的最佳方法。

    我意识到,我不必反复检查是否找到它。我不知道为什么我之前没想到要加个旗子

    rtrt = {'val': 5, 'left': None, 'right': None}
    lft = {'val': 2, 'left': lftlft, 'right': {'val': 99, 'left': None, 'right': None}}
    rt = {'val': 4, 'left': None, 'right': rtrt}
    T = {'val': 1,'left': lft, 'right': rt}
    
    
    def get_path(root, data, path):
        final_path = []
        found = False
    
        def pre_order(tree, path):
            if tree is None:
                return
    
            path.append(tree['val'])
    
            if tree['val'] == data:
                nonlocal final_path, found
                final_path = path
                found = True
                return found
    
            return pre_order(tree['left'], path[:]) or pre_order(tree['right'], path[:])
    
        pre_order(root, [])
        if not found:
            return []
    
        return final_path
    
    get_path(T, 999, [])
    

    我认为这是因为当您从
    get\u path
    调用
    pre-order
    时,您没有捕获返回值

    下面的结果似乎与我的代码示例相同,如果我将值
    99
    更改为其他数字,则返回值为
    None

    lftlft = {'val': 3, 'left': None, 'right': {'val': 100, 'left': None, 'right': None}}
    rtrt = {'val': 5, 'left': None, 'right': None}
    lft = {'val': 2, 'left': lftlft, 'right': {'val': 99, 'left': None, 'right': None}}
    rt = {'val': 4, 'left': None, 'right': rtrt}
    T = {'val': 1,'left': lft, 'right': rt}
    
    def get_path(root, data, path):
    
        def pre_order(tree, path):
            if tree is None:
                return
    
            path.append(tree['val'])
    
            if tree['val'] == data:
                return path
            return pre_order(tree['left'], path[:]) or pre_order(tree['right'], path[:])
    
        desired_result = pre_order(root, [])
        return desired_result
    
    print (get_path(T, 99, []))
    
    这是一个很好的例子。您可以按要求执行操作,但这实际上是在向函数中添加全局状态。嗯,使用
    final_path
    已经意味着您正在使用全局状态,您应该尽可能避免使用全局状态(在这种情况下也是可能的)

    有几种方法可以解决你的问题。首先,您可以扩展
    final\u路径,而不是追加。也就是说,将
    final\u path.append(path)
    替换为
    final\u path.extend(path)
    。这不是将
    path
    作为元素添加到
    final\u path
    ,而是将
    path
    的所有元素作为
    final\u path
    的元素添加。但你仍然在使用全局状态,这并不好

    相反,您可以使用Python对象的“真实性”,以便可以返回不同的类型。也就是说,您可以返回路径本身,而不是返回
    True
    ,如果返回了路径,则仅附加当前的
    val
    。如果没有找到路径,则返回类似于false的值,如
    []
    。这将创建一个反向路径,但您只需在末尾反向
    路径即可。例如

    def get_path(root, data, path):
    
        def pre_order(tree):
            if not tree:
                # base case, data not found
                return [] # counts as false
            elif tree['val'] == data:
                # base case, found data
                return [data] # counts as true
            else:
                # recursive case
                path = pre_order(tree['left']) or pre_order(tree['right'])
                if path:
                    # data was found, add the current val to the path
                    path.append(tree['val'])
                return path
    
        final_path = pre_order(root)
        final_path.reverse()
        print('finalpath', final_path)
        return final_path
    
    最后,如何编写解决方案的答案是使用关键字
    nonlocal
    。这允许您更改
    final_path
    指向的对象,而不仅仅是改变对象。例如

    def f():
        x = 1
        def g():
            nonlocal x
            x = 2
        g()
        print("x =", x) # prints x = 2
    
    def f():
        x = 1
        def g():
            nonlocal x
            x = 2
        g()
        print("x =", x) # prints x = 2