область импортируемых переменных

#python #import #global #python-3.8

Вопрос:

Я столкнулся с ситуацией в скрипте python3.8, когда после импорта множества переменных из внешнего файла в некоторых функциях к ним можно получить доступ нормально, а в других-нет. Например, константа min_time_n_clicks определяется в файле tm_constants.py простым объявлением,

 min_time_n_clicks=10
 

Извините, что это не воспроизводимый пример, так как полный код довольно длинный, это попытка показать, что я попал: в одной функции check_scope я могу получить доступ к переменным с помощью from tm_constants import * функции, в то время как другая функция check_for_limiting их не видит — она попадает

UnboundLocalError: local variable 'min_time_n_clicks' referenced before assignment

С чего бы это? Я никогда не удаляю переменные с помощью del или тому подобного, и в отладчике pycharm, который я использую, оскорбительную переменную ( min_time_n_clicks ) можно увидеть и оценить, даже если она находится в области действия оскорбительной функции . Является ли доступ с использованием точечной нотации предпочтительным методом, и если да, то почему ?

 from tm_constants import *
import tm_constants

def check_scope():

    print(f'ok: {min_time_n_clicks}')
    print(f'ok: {tm_constants.min_time_n_clicks}')

def check_for_limiting():
    print(tm_constants.min_time_n_clicks)
    tm_constants.min_time_n_clicks = 0  # ok 
    print(min_time_n_clicks)
    min_time_n_clicks = 0 # not ok !!!
 

Комментарии:

1. Я не вижу, в чем может быть проблема, и не могу воспроизвести проблему без минимального определения модуля tm_constants .

2. Я не уверен, как вы получаете UnboundLocalError без какого-либо присвоения имени в функции.

3. С tm_constants.py и tmp.py , определенным, как показано (плюс вызовы check_scope() и check_for_limiting(None) ), python3 tmp.py не создает UnboundLocalError .

4. @chepner да , я отредактировал свои функции, ориг. У меня было несколько заданий. Код слишком длинный, чтобы я мог добавить его полностью, и не предназначен для того, чтобы быть воспроизводимым примером

5.По-прежнему никакой ошибки. Однако, если вы попытаетесь напечатать значение глобального min_time_n_clicks перед назначением, вы получите сообщение об ошибке. Это наличие назначения, которое помечает имя как локальное, а не фактическое назначение во время выполнения. То есть вы не можете использовать глобальный и локальный с одинаковым именем в одной и той же области.

Ответ №1:

Это приведет к UnboundLocalError :

 def check_for_limiting(browser):
    print(min_time_n_clicks)
    min_time_n_clicks = 0
 

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

 def check_for_limiting(browser):
    print(min_time_n_clicks)  # Still raises an UnboundLocalError
    if False:
        min_time_n_clicks = 0
 

Если вы намерены назначить глобальную переменную, вам необходимо использовать global для пометки имени как глобального:

 def check_for_limiting(browser):
    global min_time_n_clicks

    print(min_time_n_clicks)
    min_time_n_clicks = 0
 

С точечным доступом проблем нет, потому min_time_n_clicks что в этом случае нет переменной с именем; есть только глобальное имя tm_constants , которое ссылается на объект с именем атрибута min_time_n_clicks . Далее обратите внимание , что прямое назначение min_time_n_clicks не изменит значение tm_constants.min_time_n_clicks , так как это две разные ссылки на один и тот же объект. Изменение одной ссылки не изменяет другую.