用Python传递的参数

时间:2012-05-23 01:22:25

标签: python

我不太明白变量'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

1 个答案:

答案 0 :(得分:3)

如果visitedf 您更改了可变变量。在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
    
  3. 修改

    更新问题后,我看到了嵌套函数,而不是全局范围内定义的函数。因此,使用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