Передача переменных в python при использовании из импорта * - PullRequest
3 голосов
/ 30 апреля 2010

Как мне сделать этот отпечаток "baz" при запуске b.py?

a.py

    def foo():
        global bar
        print bar

b.py

    from a import *
    bar = "baz"
    foo()

Ответы [ 4 ]

6 голосов
/ 01 мая 2010

В таком простом примере реальный ответ в большинстве случаев заключается в использовании аргументов функции (как уже упоминалось). Но если бы смысл состоял в том, чтобы проверить правила области видимости Python, то я думаю, что могу уточнить ...

Если вы думаете из контекста C / C ++, вы легко можете быть озадачены тем, как работает импорт Python. Импорт модулей не работает как директивы #include. В C / C ++ компилятор будет использовать директивы #include в качестве маркеров для вставки исходного кода из других файлов исходного / заголовочного файла в текущий исходный файл (это собственная локальная копия включенного источника). В результате при компиляции глобальные переменные будут выделены для этого модуля компиляции, который включает в себя весь #included источник. Вы можете сделать несколько грязных трюков с порядком #include, чтобы создать действительно трудный для понимания код. :-P

Импорт Python не предоставляет экземпляр локального модуля, который разделяет область действия модуля импорта. Вместо этого он предоставляет ссылку на объект одноэлементного модуля, который используется в текущем выполнении интерпретатора. Объект модуля создается при первом импорте. Последующие импорты, будь то в том же модуле или из совершенно разных модулей, просто получают ссылку на этот же объект модуля. «Глобальный» является глобальным в своем модуле. Из других модулей он будет доступен только через ссылку на этот модуль. Например, в a.py вам потребуется импортировать b, чтобы получить доступ к значению «bar».

В вашем примере вы не должны этого делать, поскольку у вас будет циклический импорт. Если вам действительно нужно установить состояние модуля, вы можете установить модуль global из модуля b: a.bar = bar (ад зависимости последовательности).

Не меняйте a.py,

def foo():
    print bar

но измените b.py на:

import a
a.bar = "baz"
a.foo()

В лучше инкапсулированном примере a.py предоставляет функцию для установки своего глобального состояния, чтобы b.py мог просто выполнить a.set_module_state( "baz" ).

2 голосов
/ 30 апреля 2010

Вы не можете. Модуль b не влияет на глобальные переменные из модуля a, хотя модуль b копирует их в свои собственные глобальные переменные.

from a import * в b.py просто делает foo в b ссылкой на тот же функциональный объект, на который foo в a является ссылкой. Это не копирует функцию. Функция не использует внезапно глобалы b при обращении к глобальному имени.

Вместо этого передайте в качестве аргумента:

import a
bar = "baz"
a.foo(bar)

Или, если вы просто хотите изменить a.bar, вы можете назначить это. Это влияет на все звонки на foo(), но не только на b.

1 голос
/ 30 апреля 2010

Это ужасно не в духе питона, но ...

a.py
 def foo():
    print bar

b.py
 from a import *
 a.bar = "baz"
 foo()

Я склонен избегать from <module> import * больше. Ваше программирование вряд ли будет ограничено вашей скоростью набора текста, и добавление имени модуля не должно быть слишком сложным. Установка переменных в другом модуле - это то, что меня не особо волнует. Так что да, лучшая формация будет:

a.py
 def foo(bar):
    print bar

b.py
 import a
 bar = "baz"
 a.foo(bar)

И смотри, печатать еще меньше!

0 голосов
/ 31 октября 2014

В качестве альтернативы, и это плохой Python, если ваш проект действительно требует глобальных переменных, и вам не нужно, чтобы ваши модули были по-настоящему "модульными" (то есть повторно использовались в других проектах без изменений)Вы всегда можете ввести третий модуль globals.py:

a.py

    import globals
    def foo():
        #global bar
        print globals.bar

b.py

    import globals
    from a import *
    globals.bar = "baz"
    foo()

globals.py

    #This module contains global variables
    bar = ""

Это работает, потому что, как указал Джереми, объект модуля создается только при первом его импорте - любойдальнейший импорт, даже из других модулей, просто создает ссылку на тот же объект.

...