Почему я не могу изменить другую переменную модулей в Python? - PullRequest
4 голосов
/ 27 ноября 2010

Я пытаюсь разрешить второму модулю изменять переменные первого в циклическом импорте, но, похоже, это не работает.

У меня есть 2 вопроса: 1) Почему нетэта работа / в чем причина этого с точки зрения развития языка и 2) существуют ли простые решения, которые позволяют мне делать то же самое, возможно, немного по-другому?

a.py:

import b

test1 = 'a'
test2 = None
test3 = '3'

if __name__ == '__main__':
  print test1, test2, test3 #prints 'a', None, 3
  b.changeVars()
  print test1, test2, test3 #prints 'a', None, 3 (i.e. nothing has changed)

b.py:

import a

def changeVars():
  print a.test1, a.test2, a.test3 #prints 'a', None, 3
  a.test1 = 'NEW VAR 1'
  a.test2 = 'NEW VAR 2'
  a.test3 = 'NEW VAR 3'

  print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

Ответы [ 2 ]

8 голосов
/ 27 ноября 2010

Происходит следующее: когда b.py пытается import a, для него нет записи в sys.modules, поскольку запись находится под __main__.Это заставляет механизмы импорта повторно импортировать модуль и поместить его под именем a.Итак, теперь есть модуль a и совершенно не связанный модуль __main__.Замена b.py на что-то подобное делает свое дело.

import sys
a = sys.modules['__main__']

def changeVars():
  print a.test1, a.test2, a.test3 #prints 'a', None, 3
  a.test1 = 'NEW VAR 1'
  a.test2 = 'NEW VAR 2'
  a.test3 = 'NEW VAR 3'

  print a.test1, a.test2, a.test3 #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

дает

aaron@aaron-laptop:~/code/tmp$ python a.py
a None 3
a None 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
NEW VAR 1 NEW VAR 2 NEW VAR 3
aaron@aaron-laptop:~/code/tmp$ 

Чтобы получить лучший пример того, что происходит, рассмотрите следующие файлы:

#a.py
import b
import a

test = 'Foo'   

if __name__ == '__main__':
  print test  #prints 'Foo'
  b.changeVars()
  print a.test, test # prints 'Foo', 'Bar'

и

#b.py
import a as a1

import sys
a2 = sys.modules['__main__']

def changeVars():

  print a1.test, a2.test # Prints 'Foo', 'Foo'
  a2.test = 'Bar'
  print a1.test, a2.test # Prints 'Foo', 'Bar'

Какие выходы

Foo
Foo Foo
Foo Bar
Foo Bar

Это ясно показывает, что sys.modules['a'] и sys.modules['__main__'] относятся к двум разным объектам.Решение, вероятно, состоит в том, чтобы поместить следующие строки в качестве a.py

import __main__ as a  # due to Ignacio Vazquez-Abrams 

. Таким образом, для любого другого модуля также будет import a.В целом, хотя, я действительно не понимаю, почему вы хотели бы сделать это.Вероятно, есть лучший способ сделать это.

0 голосов
/ 26 апреля 2014

Лучший способ выполнить такие задачи - объявить переменные в том же модуле, в котором вы хотите их изменить. В этом случае в b.Затем импортируйте b внутрь a, и вы можете делать все, что захотите. Вы можете использовать переменные без изменений, как вы объявили их в a, или вы можете их изменить.Посмотрите на это:

b.py

test1 = 'a'
test2 = None
test3 = '3'

def changeVars():
    global test1,test2,test3
    test1 = 'NEW VAR 1'
    test2 = 'NEW VAR 2'
    test3 = 'NEW VAR 3'

    print test1, test2, test3   #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'

a.py

import b

if __name__ == '__main__':
    print b.test1, b.test2, b.test3   #prints 'a', None, 3
    b.changeVars()
    print b.test1, b.test2, b.test3   #prints 'NEW VAR 1', 'NEW VAR 2', 'NEW VAR 3'


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

...