我不太明白变量'current_label'的含义,对我来说似乎是在函数'ts_r'的封闭代码中定义的,这会使它从'ts_r'中可见?但是当我运行下面的代码时,它会抱怨在赋值之前引用局部变量'current_label'...请注意,它不抱怨'已访问'或'f',并且它赢了'如果我用[len(g)]初始化'current_label',我会抱怨。
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
答案 0 :(得分: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它是全局的,因此它假设它是本地的。但如果它是本地的,你就不能早点分配它。
您有两种选择:
(可能不是您要查找的那个)将其用作本地:
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
告诉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。同样,您至少有两种可能性:
使用包含您想要更改的不可变的可变变量(例如,列表中包含一个整数)。然后,当您只是引用(并更改)列表的第一个元素时。试试吧。
另一种解决方案是为包装函数添加一个属性(函数也是可变的,因此您可以更改它,但不会污染全局命名空间)。示例如下: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