Как поделиться глобальной переменной с ленивой инициализацией? - PullRequest
2 голосов
/ 11 апреля 2020

Вероятно, очень нонби sh вопрос, но он вызывает меня каждый раз ...

Может кто-нибудь объяснить мне, почему следующие печатает "Нет"?

test1.py

test = None

def init():
    global test
    test = 1

test2.py

from test1 import test, init

# test1.test should be getting a value here
init()
# I expect test to be a reference to test1.test 
# but behaves like a copy on import-time ?!
print(test)

Ответы [ 2 ]

2 голосов
/ 11 апреля 2020

Делая test = 1, вы меняете ссылку на test, но предыдущая ссылка (на None) уже уже была импортирована в test2.py. Если вы хотите сохранить его, вы можете, например, использовать объект:

# test1.py
test = {}

def init():
    # you do not need `global` since you are not rewriting the variable
    test['x'] = 1
# test2.py
from test1 import init, test

assert test == {}
init()
assert test['x'] == 1  # works
1 голос
/ 11 апреля 2020

Когда вы используете from test1 import test, вы создаете переменную в локальной области видимости, которая связана со значением test1.test. Присвоение значения test затем заменит его новым значением, но исходное значение test1.test останется прежним. Так что в вашем случае, когда вы вызываете init() в test2.py , на самом деле вместо переменной в вашей локальной области видимости принимается переменная test1.test.

>>> import test1
>>> from test1 import test, init

>>> init()
>>> print(test)
None
>>> print(test1.test)
1

Обратите внимание, что michaeldel написал в своем ответе, что ситуация отличается, когда вы используете изменяемый тип данных (например, list или dict), так как его изменение действительно повлияет на исходную переменную. Мой ответ основан на ответе ThiefMaster на аналогичный вопрос. Вы можете проверить это для более подробного объяснения.

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