Почему изменение глобального не дает ошибки?
С какой стати Python позволяет изменять не глобальный объявленный список в функции?
RE-ОБНОВЛЕНО
numbers = []
num = 4
def add(n, thisnum=None):
# changing global list without global declaration!
numbers.append(n)
if thisnum:
num = thisnum
print 'num assigned', thisnum
##numbers = ('one', 'two', 'three')
## adding this line makes error:
"""Traceback (most recent call last):
File "J:\test\glob_vals.py", line 13, in <module>
add(i)
File "J:\test\glob_vals.py", line 6, in add
numbers.append(n)
UnboundLocalError: local variable 'numbers' referenced before assignment
"""
for i in (1,2,3,564,234,23):
add(i)
print numbers
add(10, thisnum= 19)
# no error
print num
# let the fun begin
num = [4]
add(10, num)
print num
# prints:
"""[1, 2, 3, 56, 234, 23]
num assigned 19
4
num assigned [4]
[4]
"""
Если я присваиваю присваивание переменной с тем же именем, то действие перед этой строкой становится ошибкой, а не добавленной строкой (думаю, компилятор байтового кода обнаруживает это).
3 ответа
Вы не присваиваете глобальной переменной, вы вызываете метод, который изменяет ее содержимое. Это разрешено
Что вы не можете сделать без global
Ключевое слово это:
def add(n):
#global numbers
numbers = numbers + [n]
Результат:
Traceback (последний вызов был последним): Файл "C:\Users\Mark\Desktop\stackru\python\test.py", строка 8, в добавить (я) Файл "C:\Users\Mark\Desktop\stackru\python\test.py", строка 5, в добавлении числа = числа + [n] UnboundLocalError: локальная переменная 'numbers', на которую ссылаются перед присваиванием
Разница в том, что здесь я не изменяю существующий список - я пытаюсь создать новый список и переназначить его в глобальную область. Но это не может быть сделано без global
ключевое слово.
Что касается вашего обновления:
Следующая строка в порядке, потому что она создает новое локальное имя num
в объеме функции. Это не влияет на значение переменной в глобальной области видимости.
num = thisnum
global x
только провидения x = ...
(а именно, это делает это переназначить глобальный x
вместо создания независимого местного x
). Не влияет x.member = ...
(потому что это вызов метода) или x.mutating_method(...)
, потому что Python (это не проблема статического или динамического, кстати) не может знать (и не волнует), что эти методы модифицируют self
каким-то образом - так что вам нужно будет предотвращать вызовы методов (объектов, на которые указывают) глобальные переменные... что, конечно, бессмысленно.
Что касается обновления: когда вы делаете num = thisnum
вы делаете что-то совершенно отличное от numbers.append(n)
- вы создаете локальную переменную (потому что вы не объявили global num
) и присвоить ему какое-то значение. Это даже не касается num
,
Потому что вы просто добавляете в список.
Доступ и назначение - разные понятия. Когда вы добавляете список, вы просто вызываете метод, который меняет его значение. Предположим, что вы сделали +=
, что будет присваивать.
Если вы должны были сделать это:
>>> numbers = []
>>> def add(n):
numbers += n
>>> n = [1, 2]
>>> add(n)
Это потерпит неудачу, потому что это назначение.
Чтобы исправить это, в add()
функцию, вы добавляете:
>>> def add(n):
global numbers
numbers += n