Импорт в Python является статическим, любое решение? - PullRequest
4 голосов
/ 13 апреля 2009

foo.py:

i = 10

def fi():
    global i
    i = 99

bar.py:

import foo
from foo import i

print i, foo.i
foo.fi()
print i, foo.i

Это проблематично. Почему i не меняется при изменении foo.i?

Ответы [ 4 ]

8 голосов
/ 13 апреля 2009

Что говорит Росс, так это перестроить Фу следующим образом:

_i = 10

def getI():
    return _i

def fi():
    global _i
    _i = 99

Тогда вы увидите, что это работает так, как вы хотите:

>>> import foo
>>> print foo.getI()
10
>>> foo.fi()
>>> print foo.getI()
99

Это также «лучше» в том смысле, что вы избегаете экспорта глобального объекта, но при этом предоставляете ему доступ для чтения.

7 голосов
/ 13 апреля 2009

То, что import делает в bar.py, устанавливает идентификатор с именем i в пространстве имен модуля bar.py, который указывает на тот же адрес, что и идентификатор с именем i в пространстве имен модуля foo.py.

Это важное различие ... bar.i указывает не на foo.i, а на то же пространство в памяти, где хранится объект 10, на который foo.i указывает одновременно , В python имена переменных не являются пространством памяти ... они являются идентификатором, указывающим на пространство памяти. При импорте в bar вы настраиваете локальный идентификатор пространства имен.

Ваш код ведет себя как ожидалось до тех пор, пока не будет вызван foo.fi(), когда идентификатор i в пространстве имен foo.py изменяется так, чтобы указывать на литерал 99, который является объектом в памяти, очевидно, в другом месте, чем 10. Теперь для пространства имен уровня модуля для foo есть i, идентифицирующий объект в памяти, отличный от идентификатора i в bar.py.

У Шейна и Росфабриканта есть хорошие предложения о том, как настроить ваши модули для достижения того, чего вы хотите.

3 голосов
/ 13 апреля 2009

i внутри foo.py является отличным i от значения в bar.py. Когда в bar.py вы делаете:

from foo import i

Это создает новый i в bar.py, который ссылается на тот же объект , что и i в foo.py.

Ваша проблема: Когда вы звоните foo.fi(), и он делает это:

i = 99

Это присваивание заставляет foo.py i указывать на другой целочисленный объект (99). Целочисленные объекты сами по себе неизменны (к счастью), поэтому они изменяют только то, на что указывает foo.py i Не bar.py х i. bar.py s i по-прежнему указывает на старый объект, на который он указывал ранее. (целочисленный неизменяемый объект 10)

Вы можете проверить то, о чем я говорю, поместив следующую команду в bar.py:

print foo.i

должно быть напечатано 99.

0 голосов
/ 13 апреля 2009

Вы можете вызвать функцию вместо ссылки на глобальную переменную.

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