Leron
Май 30, 2008 14:43:16
Такая вот штука:
>>> def counter(start):
curr =
def inc():
curr += 1
return curr
return inc
>>> f1 = counter(4)
>>>
>>> f1()
5
>>> f1()
6
Непонятно почему нужно использовать лист а такой код вызывает ошибку:
>>> def counter1(start):
curr = start
def inc():
curr += 1
return curr
return inc
>>> f2 = counter1(4)
>>> f2()
Traceback (most recent call last):
File “<pyshell#42>”, line 1, in <module>
f2()
File “<pyshell#40>”, line 4, in inc
curr += 1
UnboundLocalError: local variable ‘curr’ referenced before assignment
???
Александр Кошелев
Май 30, 2008 15:06:39
Лист это ссылка со всеми вытекающими.
ZAN
Май 30, 2008 15:26:26
Если более подробно, то в первом случае переменная для функции inc является глобальной. Запись вида curr += 1 вызаывает в области видимости функции inc ранее созданный объект. Во втором же случае происходит переопределение переменной curr вызовом curr += 1.
Что происходит дальше, читать здесь ->
http://www.python.org/dev/peps/pep-0227/.А происходит вот что - переопределение переменной говорит интерпретатору о том, что в области видмиости пременная является локальной, но для вызова curr += 1, локальная переменная уже должна хранить значение, чего в действиетльности нет - об этом сообщает нам соответствующий Exception.
ZAN
Май 30, 2008 15:32:21
Вот еще один примерчик для понимания:
>>> a = 1
>>> def inc():
print a
>>> inc()
1
>>> a = 1
>>> def inc():
print a
a = 2
>>> inc()
Traceback (most recent call last):
File “<pyshell#27>”, line 1, in -toplevel-
inc()
File “<pyshell#26>”, line 2, in inc
print a
UnboundLocalError: local variable ‘a’ referenced before assignment
Если существует локальная переменная, то функция будет видеть только ее, поэтому попытка вывести значение глобальной переменной терпит неудачу (второй случай)
Leron
Май 30, 2008 16:24:06
Спасибо, я почитал pep вроде разобралсо:
Jeremy Hylton
If a name is used within a code block, but it is not bound there
and is not declared global, the use is treated as a reference to
the nearest enclosing function region. <> If they(binding operations ) occur within a block, they introduce new local names in the
current block unless there is also a global declaration.
hellt
Май 30, 2008 16:40:39
а можно еще раз пояснить, почему cur = start не является глобальной переменной для inc()?
ZAN
Май 30, 2008 17:03:58
В действительности, во втором случае существуют две одноименные переменные, но внутри функции она не видна, т.к. просмотрев функцию, и заметив в ней присвоение, интерпретатор воспринимает curr только как локальную.
hellt
Май 30, 2008 17:38:06
почему тогда curr += 1 , что эквивалентно curr = curr + 1 —- не попадает по рамки "я нашел присвоение и значит curr ищется локально"?
sry, не могу врубится(
ZAN
Май 30, 2008 20:36:01
Потому, как, я уже писал (об этом еще упоминал Daevaorn), в случае со списком происходит не переопределение переменной, а ее модификация. В данном случае - инкрементация компонента списка с нулевым индексом.
Yurietc
Май 31, 2008 16:36:10
Если нужно в блоке изменить глобальную переменную, нужно использовать инструкцию global.
>>> def counter1(start):
global curr
curr = start
def inc():
global curr
curr += 1
return curr
return inc
>>> f2 = counter(4)
>>> f2()
5