Как сделать кросс-модульную переменную? - PullRequest
115 голосов
/ 27 сентября 2008

Переменная __debug__ удобна отчасти потому, что влияет на каждый модуль. Если я хочу создать другую переменную, которая работает таким же образом, как бы я это сделал?

Переменная (давайте будем оригинальной и назовем ее 'foo') не обязательно должна быть действительно глобальной, в том смысле, что если я изменю foo в одном модуле, она будет обновлена ​​в других. Было бы хорошо, если бы я мог установить foo перед импортом других модулей, и тогда они увидели бы то же значение для него.

Ответы [ 12 ]

1 голос
/ 15 апреля 2012

Я использую это для пары встроенных примитивных функций, которые, по моему мнению, действительно отсутствуют. Одним из примеров является функция поиска, которая имеет ту же семантику использования, что и фильтр, отображение, уменьшение.

def builtin_find(f, x, d=None):
    for i in x:
        if f(i):
            return i
    return d

import __builtin__
__builtin__.find = builtin_find

После запуска (например, путем импорта рядом с точкой входа) все ваши модули могут использовать find (), как будто, очевидно, он был встроен.

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

Примечание: Конечно, вы можете сделать это с помощью фильтра и другой строки, чтобы проверить нулевую длину, или с помощью сокращения в одной странной строке, но я всегда чувствовал, что это странно.

0 голосов
/ 14 апреля 2018

Я подумал, можно ли избежать некоторых недостатков использования глобальных переменных (см., Например, http://wiki.c2.com/?GlobalVariablesAreBad), используя пространство имен класса вместо глобального / модульного пространства имен для передачи значений переменных. Следующий код указывает на то, что эти два метода по существу идентичны. Существует небольшое преимущество в использовании пространств имен классов, как описано ниже.

Следующие фрагменты кода также показывают, что атрибуты или переменные могут динамически создаваться и удаляться как в глобальных пространствах имен / пространствах модулей, так и в пространствах имен классов.

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

Я называю этот модуль «стеной», так как он используется для отскока переменных. Он будет действовать как пространство для временного определения глобальных переменных и общеклассовых атрибутов пустого класса router.

source.py

import wall
def sourcefn():
    msg = 'Hello world!'
    wall.msg = msg
    wall.router.msg = msg

Этот модуль импортирует стену и определяет одну функцию sourcefn, которая определяет сообщение и отправляет его двумя разными механизмами, один через глобальные переменные, а другой через функцию маршрутизатора. Обратите внимание, что переменные wall.msg и wall.router.message определены здесь впервые в соответствующих им пространствах имен.

dest.py

import wall
def destfn():

    if hasattr(wall, 'msg'):
        print 'global: ' + wall.msg
        del wall.msg
    else:
        print 'global: ' + 'no message'

    if hasattr(wall.router, 'msg'):
        print 'router: ' + wall.router.msg
        del wall.router.msg
    else:
        print 'router: ' + 'no message'

Этот модуль определяет функцию destfn, которая использует два разных механизма для получения сообщений, исходящих от источника. Это допускает возможность того, что переменная 'msg' может не существовать. destfn также удаляет переменные после их отображения.

main.py

import source, dest

source.sourcefn()

dest.destfn() # variables deleted after this call
dest.destfn()

Этот модуль вызывает ранее определенные функции последовательно. После первого вызова dest.destfn переменные wall.msg и wall.router.msg больше не существуют.

Вывод из программы:

global: Привет, мир!
маршрутизатор: Привет, мир!
глобальный: нет сообщения
маршрутизатор: нет сообщения

Приведенные выше фрагменты кода показывают, что механизмы module / global и class / class variable по существу идентичны.

Если необходимо совместно использовать большое количество переменных, загрязнение пространства имен можно контролировать с помощью нескольких модулей типа стены, например, wall1, wall2 и т. д. или путем определения нескольких классов маршрутизатора в одном файле. Последнее немного опрятнее, поэтому, возможно, представляет собой незначительное преимущество для использования механизма переменной класса.

...