Python: обмен глобальными переменными между модулями и классами в них - PullRequest
35 голосов
/ 26 июля 2010

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

global_mod.py

x = None

mid_access_mod.py

from global_mod import *

class delta:
    def __init__(self):
        print x

bot_modif_mod.py

import mid_access_mod
import global_mod

class mew:
    def __init__(self):
        global_mod.x = 5

def main():
    m = mew()
    d = mid_access_mod.delta()

Это печатает нет, дажехотя все модули совместно используют глобальную переменную х.Почему это так?Похоже, что x оценивается в mid_access_mod.py, прежде чем он будет назначен в bot_modif_mod.py mew ().

Ответы [ 5 ]

38 голосов
/ 26 июля 2010

Это происходит потому, что вы используете неизменяемые значения (целочисленные значения и значения None), а импорт переменных аналогичен передаче данных по значению, а не передаче по ссылке.

Если вы сделали global_mod.x списком и манипулировали его первым элементом, он работал бы так, как вы ожидаете.

Когда вы делаете from global_mod import x, вы создаете имя x в вашем модуле с тем же значением, которое x имеет в global_mod. Для таких вещей, как функции и классы, это работает так, как вы ожидаете, потому что люди (как правило) не назначают эти имена позже.

Как указывает Алекс, если вы используете import global_mod, а затем global_mod.x, вы избежите этой проблемы. Имя, которое вы определяете в своем модуле, будет global_mod, которое всегда относится к нужному модулю, а затем, используя атрибут доступа для получения значения x, вы получите самое последнее значение x.

26 голосов
/ 26 июля 2010

from whatever import * - это , а не хорошая идиома для использования в вашем коде - она ​​предназначена для использования, если вообще когда-либо, в интерактивном сеансе в качестве ярлыка для сохранения некоторого набора текста.По сути, он «снимает» все имена из модуля на тот момент времени - если вы когда-нибудь свяжете какое-либо из этих имен, снимок станет устаревшим и возникнут всевозможные проблемы.И это только начало неразрывного беспорядка, на который вы подписываетесь, используя убогую конструкцию from ... import *.

Хотите мой совет?Забудьте, что вы когда-либо слышали о существующей конструкции, и никогда больше ее не используете.Используйте import global_mod as m и всегда используйте после этого квалифицированные имена, такие как m.x - квалифицированные имена , поэтому намного удобнее и мощнее в Python, чем простые голые имена, что это недаже смешно(as m часть оператора import является полностью необязательной и в основном существует для целей краткости или иногда для решения некоторых проблем со столкновением имен; используйте его, когда и если вы считаете его удобным, поскольку у него нет недостатков, ноне чувствуйте себя вынужденными или даже вынужденными использовать, если вы не чувствуете в этом необходимости).

0 голосов
/ 17 мая 2016

Чтобы решить эту проблему, просто измените from global_mod import * на import global_mod.

И новый mid_access_mod.py будет:

import global_mod

class delta:
    def __init__(self):
        print global_mod.x

Причинадля этого можно найти здесь .

Благодаря тому, что ссылки и привязка имен работают в Python, если вы хотите обновить какой-либо символ в модуле, скажем foo.bar,извне этого модуля и для того, чтобы другой импортирующий код «увидел» это изменение, вы должны импортировать foo определенным образом.

0 голосов
/ 19 октября 2015

Как упоминал Нед Батчелдер, разделяются только значения, а не фактический объект.Если вы хотите поделиться объектом по ссылке, то вы, вероятно, ищете Thread-Local Data.

Например:

import threading

g = threading.local()
g.population = '7 Billion'

Теперь, когда вы хотите получить доступ или изменить переменную g.populationвы получите его обновленное значение при условии, что это тот же поток, из которого вы пытаетесь получить к нему доступ.

Подробнее в документации Python: https://docs.python.org/3/library/threading.html#thread-local-data

0 голосов
/ 06 ноября 2014

Я изменил пример, чтобы использовать список для x, и список присваивает (x [0] = ..), как предложено в верхнем ответе, и печать возвращает то же самое начальное значение (None). «from global_mod import *» - это копия независимо от того, изменяемая она или нет.

Как предлагается в комментарии, «import global_mod» работает, если «mid global_mod.x =» затем используется в mid_access_mod.

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