Глобальная переменная, импортированная из модуля, не обновляется - почему? - PullRequest
1 голос
/ 04 марта 2020

Мне трудно понять, почему импорт глобальной переменной из другого модуля работает должным образом при использовании import, но при использовании from x import * глобальная переменная не обновляется в своем собственном модуле

Представьте, что у меня есть 2 файла: один get ...

start
start

Если я импортирую модуль нормально, он работает как положено

import one
print one.x
one.change("updated")
print one.x

Результат ...

start
updated

Учитывая, что я могу ' я не могу изменить использование глобальных переменных в ony.py (не по моей вине), а two.py должен быть своего рода оболочкой * вокруг one.py, я бы действительно хотел избежать использования пространства имен one. во всем two.py ради одной упрямой переменной.

Если это невозможно, объяснение того, что происходит на уровне новичков, может помочь мне избежать повторного застревания. Я предполагаю, что one.x обновляется, но two.x не уважает обновления, но я не знаю почему.

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Вы можете думать о пакете как о диктовке. Каждая функция и переменная в пакете указываются в качестве ключа в этой инструкции, которую вы можете просмотреть, используя globals().

Когда вы импортируете объект из другого пакета, вы копируете ссылку на объект в свой собственный пакет под именем (обычно одинаковым, другим, если вы import <var> as <name>).

Установкой значение в другом пакете, вы перезаписываете ключ в этом пакете новым значением, но оставляете ссылку на старое.

Аналогия с dicts

Мы можем продемонстрировать процесс с использованием dicts в качестве аналогии:

# Our 'packages'
one = {'x': 'start'}
two = {}

# Equivalent of our import
two['x'] = one['x']   

# Variable updated in `one'
one['x'] = 'updated'

# ... and accessed in `two`
print(two['x'])   # Still 'start'

Мы не ожидаем, что диктат two будет обновлен только потому, что мы перезаписали значение в one.

Что вы можете сделать с it

Вы можете изменять объект до тех пор, пока вы не сломаете указатель, переписав переменную. Например, если x был диктом, вы могли бы изменить значение внутри dict, и две переменные по-прежнему указывали бы на один и тот же объект.

В качестве альтернативы вы могли бы присоединить переменные к функции следующим образом:

def change(value):
    change.x = value

Это делает ту же самую работу, гарантируя, что мы мутируем один и тот же объект.

Лучшим ответом может быть завершение обоих предметов в объекте, если им нужно путешествовать вместе:

class Changer:
    x = 'start'

    @classmethod
    def change(cls, value):
        cls.x = value

Однако в этот момент мы можем изменить значение непосредственно как атрибут:

Changer.x = 'updated'

Что может быть самым простым.

0 голосов
/ 04 марта 2020

Это, вероятно, лучшее, что вы можете сделать внутри two.py:

import one
from one import x

def change(value):
    one.change(value)
    global x
    from one import x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...