В случае 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
EDIT
После того как ваш вопрос был обновлен, я видел вложенные функции вместо функций, определенных в глобальной области. Таким образом, решение с global
не будет работать.
В Python 3.x у вас есть ключевое слово nonlocal
, но вам нужно найти walkaround в случае Python 2.x. Опять же, у вас есть по крайней мере две возможности:
Используйте изменяемые переменные ограждающих неизменны вы хотите изменить (например, список с одним целым числом в нем.). Затем, когда вы просто ссылаетесь на (и изменяете) первый элемент списка. Попробуй.
Другим решением является добавление атрибута для функции обертывания (функция также является изменяемой, поэтому вы можете ее изменить, но вы не будете загрязнять глобальное пространство имен). Пример: 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
Позор на кого писал затемненные имена переменных и методов в Python! – mVChr
Я попытался исправить ваши отступы, но я понял, что все еще странно. Можете ли вы исправить это форматирование? – jdi
Готово. Теперь лучше выглядеть. – Frank