Глобальная переменная с импортом - PullRequest
25 голосов
/ 16 января 2011

first.py

myGlobal = "hello"

def changeGlobal():
   myGlobal="bye"

second.py

from first import *

changeGlobal()
print myGlobal

Я получаю вывод

привет

хотя я думал, что это должно быть

прощай

Почему глобальная переменная myGlobal не изменяется после вызова функции changeGlobal()?

Ответы [ 3 ]

18 голосов
/ 16 января 2011

Попробуйте:

def changeGlobal():
    global myGlobal
    myGlobal = "bye"

На самом деле, это тоже не работает.Когда вы import *, вы создаете новый локальный глобальный модуль myGlobal, который защищен от изменений, которые вы намерены (если вы не изменяете переменную, см. Ниже).Вы можете использовать это вместо:

import nice

nice.changeGlobal()
print nice.myGlobal

Или:

myGlobal = "hello"

def changeGlobal():
   global myGlobal
   myGlobal="bye"

changeGlobal()

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

myGlobal = ["hello"]

def changeGlobal():
    myGlobal[0] = "bye"
6 голосов
/ 02 апреля 2011

У меня однажды была такая же проблема, как и у вас, и чтение следующего раздела из Norman Matloff Краткое и безболезненное руководство по Python действительно помогло мне. Вот что вам нужно понять (скопировано из книги Матлоффа):

Python действительно не допускает глобальные переменные в том смысле, в каком это делает C / C ++. Импортированный модуль Python не будет иметь прямого доступа к глобальным переменным в модуле, который его импортирует, и наоборот.

Например, рассмотрим эти два файла: x.py ,

# x.py
import y
def f():
  global x
  x = 6
def main():
  global x
  x = 3
f()
y.g()
if __name__ == ’__main__’:
  main()

и y.py :

# y.py
def g():
  global x
  x += 1

Переменная x в x.py видна по всему модулю x.py , но не в y.py . На самом деле, исполнение линии х + = 1

в последнем случае появится сообщение об ошибке, «глобальное имя’ x ’не определено».

Действительно, глобальная переменная в модуле - это просто атрибут (то есть элемент-член) этого модуля, аналогичный роли переменной класса в классе. Когда модуль B импортируется модулем A , пространство имен B копируется в A . Если модуль B имеет глобальную переменную X, то модуль A создаст переменную с таким именем, начальное значение которой равно модулю B для его переменной это имя во время импорта. Но изменения X в одном из модулей НЕ будут отражены в другом.

Скажем, X изменяется в B , но мы хотим, чтобы код в A позволял получить последнее значение X в B . Мы можем сделать это, включив функцию, скажем, с именем GetX () в B . Предполагая, что A импортирует все из B , тогда A получит функцию GetX () , которая является копией B Функция с этим именем, единственная цель которой - вернуть значение X. Если B не изменит эту функцию (что возможно, например, функции могут быть назначены), функции в двух модули всегда будут одинаковыми, поэтому A может использовать свою функцию для получения значения X в B .

1 голос
/ 11 августа 2016

Глобальные переменные Python не являются глобальными

Как указано выше в wassimans, они, по сути, являются атрибутами в рамках модуля, в котором они определены (или модуля, который содержит функцию, которая их определила).

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

Вторая путаница (ошибка), с которой сталкиваются люди, заключается в том, что каждый модуль (то есть импортированный файл) содержит свое собственное так называемое «глобальное» пространство имен. Я предполагаю, что Python - это то, что мир (глобус) является модулем - возможно, мы ищем «универсальные» переменные, которые охватывают более чем один глобус.

Третья путаница (которую я начинаю понимать сейчас) - где «глобалы» в модуле __main__? Т.е., если вы запускаете python из командной строки в интерактивном режиме, или если вы вызываете скрипт python (введите имя foo.py из командной оболочки) - нет импорта модуля, имя которого вы можете использовать.

Содержимое 'globals ()' или globals (). Keys () - которое дает вам список глобалов - похоже, доступно как: dir (sys.modules ['__main__']) Кажется, что модуль для загруженного скрипта Python (или интерактивного сеанса без загруженного скрипта), названный в: __name__, не имеет глобального имени, но доступен как модуль с именем '__main__' в системный список всех активных модулей, sys.modules

...