Переопределенная переменная, импортированная из модуля в python - PullRequest
0 голосов
/ 28 января 2020

a.py:

import sys

h = 'this is h from a.py'

for i in sys.argv:
    if i in ['-h']:
        print(h)

b.py:

import sys
from a import h


h='this is h from b.py'
for i in sys.argv:
    if i in ['-h']:
        print(h)

Тогда я получаю:

>$  python b.py -h
 this is h from a.py
 this is h from b.py

Не должен 'ч 1011 * были отменены? Или a.py получает доступ к аргументу '- h' , данному b.py?

Спасибо

Ответы [ 2 ]

1 голос
/ 28 января 2020

Основной вопрос

Вы можете перезаписать переменную из b.py следующим кодом:

import a
a.h = 'actually replaced value'

Примечание: добавление этого значения к a.py все равно даст следующий результат :

>$  python b.py -h
 this is h from a.py
 this is h from b.py


Создание требуемого поведения

Прежде всего обратите внимание, что вы можете проверить, что значение h изменяется с помощью следующего кода:

a.py:

import sys

h = 'this is h from a.py'

for i in sys.argv:
    if i in ['-h']:
        print(h)


def what_is_h():
    print('h:', h)

b.py:

import sys
from a import h, what_is_h
import a

what_is_h()
a.h = h = 'this is h from b.py'
what_is_h()

for i in sys.argv:
    if i in ['-h']:
        print(h)

Это приводит к следующему:

this is h from a.py
h: this is h from a.py
h: this is h from b.py
this is h from b.py

Первый what_is_h вызов показывает исходное значение h, а второе показывает измененное значение. Проблема в том, что a.py и b.py имеют разные версии переменной h, это называется областью действия. При использовании оператора import python анализирует ваш файл и запускает код. Вы можете предотвратить этот автоматический c запуск кода, поместив его в функцию, импортировав его и запустив из b.py, предпочтительно передавая h в качестве аргумента (поскольку глобальное состояние обычно является плохой практикой в ​​python).

«Что, если я хочу запустить функцию из a.py тоже, но только если я запускаю ее напрямую?»

Теперь, если вам нужна функция выполняется, когда вы запускаете a.py или b.py, но запускаете функцию в a.py, только если она запускается напрямую, вы можете добавить в конец файла скрипта следующее:

if __name__ == '__main__':
    my_function()

Это запустится функция my_function только при выполнении $> python a.py. Обратите внимание, что при импорте a.py он не будет запускаться my_function, если не выполняется иначе.

Как это работает? __name__ - это встроенная глобальная переменная, в которой хранится «имя», которое интерпретатор python дает сценариям python. Файл, который запускается, получает __name__ '__main__'. Теперь при импорте чего-то из a.py __name__ будет равно 'a' и my_function не будет работать.

Дополнительные примечания по стилю и советы для вашего кода

  • равенство:

вместо

if i in ['-h']:
  # ... your code

do

if i == '-h':
  # ... your code

, если вы хотите проверить несколько флагов позже, вы можете изменить его.

  • проверка, находится ли что-то в списке или подобном последовательности объекте:

, если вы хотите только проверить, находится ли -h в sys.args, вы можете сделать:

if '-h' in sys.args:
  # ... your code

вместо

for i in sys.args:
  if i == '-h':
    # ... your code
  • анализ, обработка и обработка аргументов командной строки

Если вы планируете делать более сложные вещи с аргументами есть библиотека, которая должна быть включена по умолчанию при каждой установке python, а именно библиотека argparse .

Надеюсь, я смог помочь.

1 голос
/ 28 января 2020

Когда вы импортируете a, весь код внутри a.py выполняется, поэтому у вас всегда будет напечатанный вывод:

это h из a.py

Чтобы избежать этого, вы можете изменить a.py на:

import sys

h = 'this is h from a.py'

if __name__ == '__main__':
    for i in sys.argv:
        if i in ['-h']:
            print(h)

Таким образом, код внутри предложения if будет выполняться только при вызове python a.py -h, и не когда вы звоните python b.py -h.

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