Почему изменение глобального не дает ошибки? - PullRequest
1 голос
/ 11 декабря 2010

С какой стати Python позволяет изменять не глобальный объявленный список в функции?

ОБНОВЛЕНО

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 ]

5 голосов
/ 11 декабря 2010

Вы не присваиваете глобальной переменной, вы вызываете метод, который изменяет ее содержимое.Это разрешено.

То, что вы не можете сделать без ключевого слова global, таково:

def add(n):
    #global numbers
    numbers = numbers + [n]

Результат:

Traceback (most recent call last):
  File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 8, in 
    add(i)
  File "C:\Users\Mark\Desktop\stackoverflow\python\test.py", line 5, in add
    numbers = numbers + [n]
UnboundLocalError: local variable 'numbers' referenced before assignment

Разница в том, что здесьЯ не изменяю существующий список - я пытаюсь создать новый список и переназначить его в глобальную область.Но это невозможно сделать без ключевого слова global.


Относительно вашего обновления:

Следующая строка в порядке, поскольку она создает новое локальное имя num в области действия.функция.Это не влияет на значение переменной в глобальной области видимости.

num = thisnum
1 голос
/ 11 декабря 2010

global x только заполняет x = ... (а именно, это заставляет это переназначить глобальный x вместо создания независимого локального x).Это не влияет на x.member = ... (потому что это вызов метода) или x.mutating_method(...), потому что Python ( this не является вопросом статического или динамического, кстати) не может знать (и не знает)не заботятся), что эти методы каким-то образом модифицируют self, поэтому вам нужно будет предотвращать вызовы методов (объектов, на которые указывают) глобальные переменные ... что, конечно, бессмысленно.

Относительнообновление: когда вы делаете num = thisnum, вы делаете что-то совершенно отличное от numbers.append(n) - вы создаете локальную переменную (потому что вы не объявили global num) и присваиваете ей какое-то значение.Это даже не касается глобального num.

0 голосов
/ 11 декабря 2010

Поскольку вы просто добавляете к списку.

Доступ и назначение - это разные понятия.Когда вы добавляете список, вы просто вызываете метод, который меняет его значение.Предположим, что вы сделали +=, это будет назначение.

Если бы вы сделали это:

>>> numbers = []
>>> def add(n):
      numbers += n

>>> n = [1, 2]
>>> add(n)

Сбой, потому что это назначение.

Чтобы исправить это, в функцию add() добавьте:

>>> def add(n):
        global numbers
        numbers += n
...