__debug__
Переменная удобна отчасти потому , что она влияет на каждый модуль. Если я хочу создать другую переменную, которая работает таким же образом, как бы я это сделал?
Переменная (давайте будем оригинальными и назовем ее «foo») не обязательно должна быть по-настоящему глобальной, в том смысле, что если я изменю foo в одном модуле, он обновится в других. Было бы хорошо, если бы я мог установить foo перед импортом других модулей, и тогда они увидели бы для него то же значение.
hasattr(__builtin__, "foo")
.Если вам нужна глобальная кросс-модульная переменная, возможно, будет достаточно простой глобальной переменной уровня модуля.
a.py:
b.py:
c.py:
Тест:
Пример из реальной жизни : global_settings.py Django (хотя в приложениях Django настройки используются путем импорта объекта
django.conf.settings
).источник
a.py
содержитmain()
? Это имеет значение?if __name__=="__main__"
в нем охрану, чтобы избежать запуска неожиданного кода при импорте.id()
для проверки личности)Я считаю, что существует множество обстоятельств, при которых это имеет смысл и упрощает программирование, имея некоторые глобальные объекты, которые известны в нескольких (тесно связанных) модулях. В этом духе я хотел бы немного остановиться на идее наличия модуля глобальных объектов, который импортируется теми модулями, которым необходимо ссылаться на них.
Когда есть только один такой модуль, я называю его «g». В нем я назначаю значения по умолчанию для каждой переменной, которую собираюсь рассматривать как глобальную. В каждом модуле, который использует любой из них, я не использую «from g import var», так как это приводит только к локальной переменной, которая инициализируется из g только во время импорта. Я делаю большинство ссылок в форме g.var и "g." служит постоянным напоминанием о том, что я имею дело с переменной, потенциально доступной для других модулей.
Если значение такой глобальной переменной должно часто использоваться в какой-либо функции в модуле, тогда эта функция может сделать локальную копию: var = g.var. Однако важно понимать, что присвоения переменной var являются локальными, а глобальная g.var не может быть обновлена без явной ссылки на g.var в назначении.
Обратите внимание, что у вас также может быть несколько таких глобальных модулей, совместно используемых разными подмножествами ваших модулей, чтобы держать вещи под более строгим контролем. Причина, по которой я использую короткие имена для своих глобальных модулей, заключается в том, чтобы не перегружать код их вхождениями. Имея лишь небольшой опыт, они становятся достаточно мнемоническими, имея всего 1 или 2 символа.
По-прежнему возможно назначить, скажем, gx, когда x еще не определен в g, и тогда другой модуль может получить доступ к gx. Однако, хотя интерпретатор разрешает это, этот подход не так прозрачен, и я избегаю Это. По-прежнему существует возможность случайного создания новой переменной в g в результате опечатки в имени переменной для присвоения. Иногда изучение dir (g) полезно для обнаружения каких-либо неожиданных имен, которые могли возникнуть в результате такой случайности.
источник
Определите модуль (назовите его globalbaz) и определите в нем переменные. Все модули, использующие этот «псевдоглобальный», должны импортировать модуль «globalbaz» и обращаться к нему, используя «globalbaz.var_name».
Это работает независимо от места изменения, вы можете изменить переменную до или после импорта. Импортированный модуль будет использовать последнее значение. (Я тестировал это на игрушечном примере)
Для пояснения, globalbaz.py выглядит примерно так:
источник
Вы можете передать глобальные объекты одного модуля другому:
В модуле A:
В модуле B:
источник
Глобальные переменные обычно плохая идея, но вы можете сделать это, присвоив
__builtins__
:Кроме того, сами модули представляют собой переменные, к которым вы можете получить доступ из любого модуля. Итак, если вы определяете модуль с именем
my_globals.py
:Тогда вы можете использовать это откуда угодно:
Использование модулей вместо модификации,
__builtins__
как правило, является более чистым способом создания глобальных объектов такого рода.источник
__builtins__
это особенность CPython, вам действительно не следует ее использовать - лучше используйте__builtin__
(илиbuiltins
в Python3), как показывает принятый ответВы уже можете сделать это с помощью переменных уровня модуля. Модули одинаковы независимо от того, из какого модуля они импортируются. Таким образом, вы можете сделать переменную переменной уровня модуля в любом модуле, в который имеет смысл поместить ее, и получить к ней доступ или назначить ее из других модулей. Было бы лучше вызвать функцию для установки значения переменной или сделать ее свойством какого-либо одноэлементного объекта. Таким образом, если вам в конечном итоге понадобится запустить какой-то код при изменении переменной, вы можете сделать это, не нарушая внешний интерфейс вашего модуля.
Обычно это не лучший способ сделать что-то - использование глобальных переменных - редко, - но я думаю, что это самый чистый способ сделать это.
источник
Я хотел опубликовать ответ, что есть случай, когда переменная не будет найдена.
Циклический импорт может нарушить работу модуля.
Например:
first.py
second.py
main.py
В этом примере это должно быть очевидно, но в большой кодовой базе это может сбивать с толку.
источник
Это похоже на изменение
__builtin__
пространства имен. Сделать это:Не используйте
__builtins__
напрямую (обратите внимание на лишние «s») - очевидно, это может быть словарь или модуль. Благодаря ΤΖΩΤΖΙΟΥ за указание на это можно найти больше здесь .Теперь
foo
доступен для использования везде.Обычно я не рекомендую делать это, но использование этого зависит от программиста.
Назначение для него должно быть выполнено, как указано выше, просто установка
foo = 'some-other-value'
установит его только в текущем пространстве имен.источник
Я использую это для пары встроенных примитивных функций, которых, как мне казалось, действительно не хватало. Одним из примеров является функция поиска, которая имеет ту же семантику использования, что и filter, map, reduce.
После запуска (например, путем импорта рядом с вашей точкой входа) все ваши модули могут использовать find (), как если бы, очевидно, он был встроен.
Примечание. Вы можете сделать это, конечно, с фильтром и другой строкой для проверки нулевой длины или с помощью сокращения в какой-то странной строке, но мне всегда казалось, что это странно.
источник
Я мог бы получить изменяемые (или изменяемые ) переменные кросс-модуля , используя словарь:
При запуске
test_wait_app_up_fail
фактическая продолжительность тайм-аута составляет 3 секунды.источник
Мне было интересно, можно ли избежать некоторых недостатков использования глобальных переменных (см., Например, http://wiki.c2.com/?GlobalVariablesAreBad ), используя пространство имен класса, а не пространство имен global / module для передачи значений переменных. , Следующий код указывает на то, что эти два метода практически идентичны. Как поясняется ниже, использование пространств имен классов дает небольшое преимущество.
Следующие фрагменты кода также показывают, что атрибуты или переменные можно динамически создавать и удалять как в глобальных пространствах имен / модулей, так и в пространствах имен классов.
wall.py
Я называю этот модуль «стеной», поскольку он используется для отражения переменных. Он будет действовать как пространство для временного определения глобальных переменных и общеклассовых атрибутов пустого класса «router».
source.py
Этот модуль импортирует стену и определяет одну функцию,
sourcefn
которая определяет сообщение и передает его с помощью двух разных механизмов, одного через глобальные переменные, а другого через функцию маршрутизатора. Обратите внимание, что переменныеwall.msg
иwall.router.message
определены здесь впервые в своих соответствующих пространствах имен.dest.py
Этот модуль определяет функцию,
destfn
которая использует два разных механизма для получения сообщений, отправленных источником. Это допускает возможность того, что переменная msg может не существовать.destfn
также удаляет переменные после того, как они были отображены.main.py
Этот модуль последовательно вызывает ранее определенные функции. После первого вызова
dest.destfn
переменныхwall.msg
иwall.router.msg
больше не существует.Вывод программы:
global: Привет, мир!
маршрутизатор: Привет, мир!
global: нет сообщений,
маршрутизатор: нет сообщений
Приведенные выше фрагменты кода показывают, что механизмы переменных модуль / глобальный и класс / класс по существу идентичны.
Если необходимо совместное использование большого количества переменных, загрязнением пространства имен можно управлять либо с помощью нескольких модулей настенного типа, например, wall1, wall2 и т. Д., Либо путем определения нескольких классов типа маршрутизатора в одном файле. Последний вариант немного аккуратнее, поэтому, возможно, представляет собой незначительное преимущество для использования механизма переменных классов.
источник