1

我不太明白变量“current_label”是怎么回事,对我来说,它似乎是在函数“ts_r”的封闭代码中定义的,这会使它从“ts_r”内部可见?但是当我运行下面的代码时,它抱怨在分配之前引用了局部变量'current_label'......请注意,它不会抱怨'visited'或'f',并且如果我初始化'current_label它也不会抱怨' 与 [len(g)]。

def topological_sort(g):

    visited = zeros((len(g)), dtype='int32')
    f = zeros((len(g)), dtype='int32')
    current_label = len(g) # [] so it is seen inside ts_r

    def ts_r(n):
        for nn in [v for v in g[n] if not visited[v]]:
            visited[nn] = 1
            ts_r(nn)
        f[n] = current_label
        current_label -= 1

    for i in range(len(g)):
        if not visited[i]: 
            ts_r(i)

    return f
4

1 回答 1

3

万一你改变了visited可变f 变量。如果current_label您尝试将值重新分配给全局变量而不说明它是全局的。

从外部范围更改变量不需要将它们声明为全局变量,但是将值重新分配给全局变量需要声明它是全局变量 - 否则它被视为局部变量(如果在赋值之前引用,则会出现此类错误)。

让我们看一下代码:

1.    def ts_r(n):
2.        for nn in [v for v in g[n] if not visited[v]]:
3.            visited[nn] = 1
4.            ts_r(nn)
5.        f[n] = current_label
6.        current_label -= 1

在行5中,您将全局变量值分配给f[n],但稍后,6您尝试为该全局变量分配值。您没有告诉 Python 它是全局的,因此它假定它是本地的。但是如果它是本地的,你就不能更早地分配它。

你有两个选择:

  1. (可能不是您要找的那个)将其用作本地:

    def ts_r(n):
        current_label = len(g)  # initialize local variable
        for nn in [v for v in g[n] if not visited[v]]:
            visited[nn] = 1
            ts_r(nn)
        f[n] = current_label
        current_label -= 1
    
  2. 告诉 Python 它是全局变量,并且您想更改全局变量的值:

    def ts_r(n):
        global current_label  # current_label is now global
        for nn in [v for v in g[n] if not visited[v]]:
            visited[nn] = 1
            ts_r(nn)
        f[n] = current_label
        current_label -= 1
    

编辑

更新您的问题后,我看到了嵌套函数,而不是在全局范围内定义的函数。因此,解决方案global不起作用。

在 Python 3.x 中你有nonlocal关键字,但在 Python 2.x 的情况下你需要找到 walkaround。同样,您至少有两种可能性:

  1. 使用包含您要更改的不可变的可变变量(例如,其中包含一个整数的列表)。然后,当您仅引用(并更改)列表的第一个元素时。尝试一下。

  2. 另一种解决方案是为包装函数添加一个属性(函数也是可变的,因此可以更改它,但不会污染全局命名空间)。示例在这里:http: //ideone.com/7jGvM。在您的情况下,它可能如下所示:

    def topological_sort(g):
    
        visited = zeros((len(g)), dtype='int32')
        f = zeros((len(g)), dtype='int32')
        topological_sort.current_label = len(g) # [] so it is seen inside ts_r
    
        def ts_r(n):
            for nn in [v for v in g[n] if not visited[v]]:
                visited[nn] = 1
                ts_r(nn)
            f[n] = topological_sort.current_label
            topological_sort.current_label -= 1
    
        for i in range(len(g)):
            if not visited[i]: 
                ts_r(i)
    
        return f
    
于 2012-05-23T01:26:12.797 回答