Почему присвоение моим глобальным переменным не работает в Python? - PullRequest
60 голосов
/ 30 мая 2009

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

Ответы [ 5 ]

113 голосов
/ 30 мая 2009

Глобальные переменные являются специальными. Если вы попытаетесь присвоить переменной 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.

12 голосов
/ 30 мая 2009

Хитрость в понимании этого заключается в том, что когда вы присваиваете переменную, используя =, вы также объявляете ее как локальную переменную. Таким образом, вместо изменения значения глобальной переменной 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 (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 (значение) имеет локальную переменную, которая называется 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 (значение), вы говорите о глобальной переменной, а не о локальной переменной.

1 голос
/ 16 января 2010

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

глобальный а

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

1 голос
/ 31 мая 2009

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

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

0 голосов
/ 07 августа 2018

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...