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

StackOverflow https://stackoverflow.com/questions/929777

  •  06-09-2019
  •  | 
  •  

Вопрос

У меня возникают ужасные проблемы при попытке понять правила определения области действия 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()

Выдает неожиданный (для меня) результат:

    Before setA
    Value of a is 7
    Inside setA, a is now 42
    After setA
    Value of a is 7

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

Это было полезно?

Решение

Глобальные переменные - это нечто особенное.Если вы попытаетесь присвоить переменной 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(value) фактически присваивает локальной переменной (которая, оказывается, называется 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 (most recent call last):
  File "scopeTest.py", line 14, in 
    setA(42)
  File "scopeTest.py", line 7, in setA
    print "Before assignment, a is %d" % (a)
UnboundLocalError: local variable 'a' referenced before assignment

Это говорит нам о том, что Python решил, что функция setA (value) имеет локальную переменную с именем 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 (value), вы говорите о глобальной переменной, а не о локальной переменной.

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

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

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

глобальный a

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top