Почему присвоение моим глобальным переменным не работает в Python?

У меня ужасные проблемы, когда я пытаюсь понять правила области видимости Python.

С помощью следующего скрипта:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Дает неожиданный (для меня) вывод:

    Перед установкой А
    Значение а 7
    Внутри множества А теперь 42
    После набора А
    Значение а 7

Где я ожидал бы, что последняя печать значения a будет 42, а не 7. Чего мне не хватает в правилах области видимости Python для определения области действия глобальных переменных?

6 ответов

Решение

Глобальные переменные особенные. Если вы попытаетесь присвоить переменной a = value внутри функции он создает новую локальную переменную внутри функции, даже если есть глобальная переменная с тем же именем. Чтобы вместо этого получить доступ к глобальной переменной, добавьте global оператор внутри функции:

a = 7
def setA(value):
    global a   # declare a to be a global
    a = value  # this sets the global value of a

См. Также Обозначение и связывание для подробного объяснения правил именования и связывания в Python.

Хитрость в понимании этого заключается в том, что когда вы присваиваете переменную, используя =, вы также объявляете ее как локальную переменную. Таким образом, вместо изменения значения глобальной переменной a, setA(значение) фактически устанавливает локальную переменную (которая называется a) значением, переданным в.

Это становится более очевидным, если вы попытаетесь вывести значение a в начале setA(value) следующим образом:

def setA(value):
    print "Before assignment, a is %d" % (a)
    a = value
    print "Inside setA, a is now %d" % (a)

Если вы попытаетесь запустить этот Python, вы получите полезную ошибку:

Traceback (последний вызов был последним):
  Файл "scopeTest.py", строка 14, в 
    множество А (42)
  Файл "scopeTest.py", строка 7, в наборе A
    вывести "Перед назначением, a есть%d" % (a)
UnboundLocalError: локальная переменная 'a', на которую ссылаются до назначения

Это говорит нам о том, что Python решил, что функция setA (значение) имеет локальную переменную, которая называется a, и это то, что вы изменяете, когда назначаете ей в функции. Если вы не присваиваете a в функции (как в printA()), тогда Python использует глобальную переменную A.

Чтобы пометить переменную как глобальную, вам нужно использовать ключевое слово global в Python, в той области, в которой вы хотите использовать глобальную переменную. В этом случае это внутри функции setA (значение). Таким образом, сценарий становится:

a = 7

def printA():
    print "Value of a is %d" % (a)

def setA(value):
    global a
    a = value
    print "Inside setA, a is now %d" %(a)


print "Before setA"
printA()
setA(42)
print "After setA"
printA()

Это дополнение к одной строке сообщает Python, что когда вы используете переменную a в функции setA (значение), вы говорите о глобальной переменной, а не о локальной переменной.

Внутри функцииa обрабатывается как локальная переменная, вам нужно определить

глобальный

внутри функции

Python не имеет понятия переменных, как другие языки. У вас есть объекты, которые "где-то", и у вас есть ссылки на эти объекты. = используется для назначения этих объектов ссылкам в текущем пространстве имен.

Вы создаете имя a в пространстве имен функции setA, которое ссылается на объект, к которому относится значение.

При выполнении функции вводится новая таблица символов, используемая для локальных переменных функции. Точнее, все назначения переменных в функции сохраняют значение в локальной таблице символов; тогда как ссылки на переменные сначала смотрят в локальной таблице символов, затем в локальных таблицах символов включающих функций, затем в глобальной таблице символов и, наконец, в таблице встроенных имен. Таким образом, глобальным переменным нельзя напрямую присвоить значение в функции (если они не указаны в глобальном операторе), хотя на них можно ссылаться.

Принятый ответ здесь должен быть полезен:

с использованием globalнеправильно. См . справочник по Python . Вы должны объявить переменную без глобальной, а затем внутри функции, когда вы хотите получить доступ к глобальной переменной, вы объявляете ее global yourvar

Другие вопросы по тегам