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にグローバルであるとは言わなかったので、ローカルであると想定します。ただし、ローカルの場合は、以前に割り当てることはできません。

2つの選択肢があります。

  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キーワードがありますが、Python2.xの場合はウォークアラウンドを見つける必要があります。繰り返しますが、少なくとも2つの可能性があります。

  1. 変更する不変を囲む可変変数を使用します(たとえば、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 に答える