Global python ошибка

Подскажите пожалуйста почему функция не выводит в консоль значение s

s = "I'm global variable"

def foo():
    print(s)
    s = 'Reset global variable'

foo()

Я предполагал, что когда интерпретатор дойдёт до строки print(s), он поймёт, что в области видимости функции foo такой переменной не существует. Следовательно начнёт искать её во внешней области видимости, но там она есть.

Однако в результате в консоль выводится следующее сообщение об ошибке:

Traceback (most recent call last):
  File "index.py", line 7, in <module>
    foo()
  File "index.py", line 4, in foo
    print(s)
UnboundLocalError: local variable 's' referenced before assignment

Проблема исчезает, если закомментировать строку

s = 'Reset global variable'

но мне всё равно не понятен механизм

insolor's user avatar

insolor

45.9k16 золотых знаков54 серебряных знака95 бронзовых знаков

задан 16 мая 2019 в 6:18

rettoryh13's user avatar

Марк Лутц — «Изучаем Python», глава 20, страница 596

Как известно, имена, которым выполняется присваивание внутри функции,
по умолчанию рассматриваются как локальные – они располагаются в
области видимости функции и существуют только во время работы функции.
Но я еще не говорил, что локальные переменные определяются статически,
во время компиляции программного кода в инструкции def, а не в
соответствии с операциями присваивания, производимыми во время
выполнения. Эта особенность становится причиной появления самых
причудливых сообщений в группе новостей, получаемых от начинающих
программистов. Обычно, если внутри функции имени не присваивается
какое-либо значение, поиск его будет производиться в области видимости
объемлющего модуля. Но посмотрите, что произойдет, если добавить
инструкцию присваивания переменной X после ее использования.

X = 99
>>> def selector():
... print(X) # Переменная еще не существует!
... X = 88 # X классифицируется как локальная переменная
... # То же самое происходит при “import X”, “def X”...
>>> selector()
Traceback (most recent call last):
...текст сообщения об ошибке опущен...
UnboundLocalError: local variable ‘X’ referenced before assignment

Было получено сообщение о том, что переменная не определена, но
причина его появления не очевидна. Этот программный код компилируется
интерпретатором во время ввода в интерактивной оболочке или во время
импорта модуля. Вовремя компиляции Python обнаруживает операцию
присваивания переменной X и делает вывод, что X – это локальное имя
везде в теле функции. Но во время выполнения функции, из-за того, что
к моменту вызова инструкции print операция присваивания еще не
производилась, интерпретатор сообщает о том, что имя не определено.
Согласно этому правилу использования имен, он говорит, что обращение к
локальной переменной X произведено до того, как ей было присвоено
значение. Фактически любая операция присваивания внутри функции
создает локальное имя. Операция импортирования, =, вложенные
инструкции def, вложенные определения классов и так далее – все
трактуются именно таким образом. Проблема возникает из-за того, что
операция присваивания делает имена локальными для всей функции, а не
только для той ее части, которая следует за инструкцией присваивания.

Читать учебники — полезно.

ответ дан 16 мая 2019 в 6:22

Sergey Gornostaev's user avatar

Sergey GornostaevSergey Gornostaev

66.1k6 золотых знаков51 серебряный знак111 бронзовых знаков

В вашем коде не хватает объявления, что вы планируете использовать глобальную переменную локально с помощью директивы global.

s = "I'm global variable"

def foo():
    global s  # here we go!
    print(s)
    s = 'Reset global variable'

foo()

ответ дан 17 мая 2019 в 15:16

Mikhail Kashkin's user avatar

Операция присваивания делает имя s локальным для всей функции foo, а не только для ее части после присваивания. Это потому, что локальные переменные определяются во время компиляции, а не в соответствии с порядком операций использования и присваивания переменных во время выполнения функции.

Чтобы изменить глобальную переменную, передайте ее как аргумент в функцию и верните изменённое значение:

>>> s = "I'm global variable"
def foo(s):
...     print(s)
...     return 'Reset global variable'
...
>>> s = foo(s)
I'm global variable
>>> print(s)
Reset global variable

ответ дан 22 янв 2020 в 0:43

vollkorn's user avatar

How do global variables work in Python? I know global variables are evil, I’m just experimenting.

This does not work in python:

G = None

def foo():
    if G is None:
        G = 1

foo()

I get an error:

UnboundLocalError: local variable 'G' referenced before assignment

What am I doing wrong?

Eric Leschinski's user avatar

asked Aug 15, 2009 at 4:49

1

You need the global statement:

def foo():
    global G
    if G is None:
        G = 1

In Python, variables that you assign to become local variables by default. You need to use global to declare them as global variables. On the other hand, variables that you refer to but do not assign to do not automatically become local variables. These variables refer to the closest variable in an enclosing scope.

Python 3.x introduces the nonlocal statement which is analogous to global, but binds the variable to its nearest enclosing scope. For example:

def foo():
    x = 5
    def bar():
        nonlocal x
        x = x * 2
    bar()
    return x

This function returns 10 when called.

Fed's user avatar

Fed

1,64822 silver badges29 bronze badges

answered Aug 15, 2009 at 4:50

Greg Hewgill's user avatar

Greg HewgillGreg Hewgill

942k181 gold badges1140 silver badges1280 bronze badges

3

You need to declare G as global, but as for why: whenever you refer to a variable inside a function, if you set the variable anywhere in that function, Python assumes that it’s a local variable. So if a local variable by that name doesn’t exist at that point in the code, you’ll get the UnboundLocalError. If you actually meant to refer to a global variable, as in your question, you need the global keyword to tell Python that’s what you meant.

If you don’t assign to the variable anywhere in the function, but only access its value, Python will use the global variable by that name if one exists. So you could do:

G = None

def foo():
    if G is None:
        print G

foo()

This code prints None and does not throw the UnboundLocalError.

Eric Leschinski's user avatar

answered Aug 15, 2009 at 5:04

David Z's user avatar

David ZDavid Z

127k27 gold badges254 silver badges279 bronze badges

You still have to declare G as global, from within that function:

G = None

def foo():
    global G
    if G is None:
        G = 1

foo()
print G

which simply outputs

1

answered Aug 15, 2009 at 4:51

Mark Rushakoff's user avatar

Mark RushakoffMark Rushakoff

248k45 gold badges405 silver badges397 bronze badges

Define G as global in the function like this:

#!/usr/bin/python

G = None;
def foo():
    global G
    if G is None:
        G = 1;
    print G;

foo();

The above python prints 1.

Using global variables like this is bad practice because: http://c2.com/cgi/wiki?GlobalVariablesAreBad

Eric Leschinski's user avatar

answered Aug 15, 2009 at 4:54

Nope's user avatar

NopeNope

34.4k42 gold badges94 silver badges119 bronze badges

Сам код большой так что кратко.
Код запускается с функции, сразу прописаны глобальные переменные «global XX» вот так, потом сразу даю «XX» значение 0,
после идут функции, которые используются в дальнейшем коде, в них есть XX, но при их вызове питон говорит что у него нету значения XX, почему ?
Просили код? вот пример, почему «a» не видит как переменную ?

def aa():
    global a
    a=0
    def bb():
        if a==0:
            a=5
    bb()

в этом случае скажет что у «a» нету значения

If you try to reference a local variable before assigning a value to it within the body of a function, you will encounter the UnboundLocalError: local variable referenced before assignment.

The preferable way to solve this error is to pass parameters to your function, for example:

test_var = 0

def test_func(test_var):
    test_var += 1
    return test_var

test_func(test_var)

Alternatively, you can declare the variable as global to access it while inside a function. For example,

test_var = 0

def test_func():
    global test_var
    test_var += 1
    return test_var

test_func()

This tutorial will go through the error in detail and how to solve it with code examples.


Table of contents

  • What is Scope in Python?
  • UnboundLocalError: local variable referenced before assignment
  • Example #1: Accessing a Local Variable
    • Solution #1: Passing Parameters to the Function
    • Solution #2: Use Global Keyword
  • Example #2: Function with if-elif statements
    • Solution #1: Include else statement
    • Solution #2: Use global keyword
  • Summary

What is Scope in Python?

Scope refers to a variable being only available inside the region where it was created. A variable created inside a function belongs to the local scope of that function, and we can only use that variable inside that function.

A variable created in the main body of the Python code is a global variable and belongs to the global scope. Global variables are available within any scope, global and local.

UnboundLocalError: local variable referenced before assignment

UnboundLocalError occurs when we try to modify a variable defined as local before creating it. If we only need to read a variable within a function, we can do so without using the global keyword. Consider the following example that demonstrates a variable var created with global scope and accessed from test_func:

var = 10

def test_func():
    print(var)

test_func()
10

If we try to assign a value to var within test_func, the Python interpreter will raise the UnboundLocalError:

var = 10

def test_func():
    var += 1
    print(var)
test_func()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [17], in <cell line: 6>()
      4     var += 1
      5     print(var)
----> 6 test_func()

Input In [17], in test_func()
      3 def test_func():
----> 4     var += 1
      5     print(var)

UnboundLocalError: local variable 'var' referenced before assignment

This error occurs because when we make an assignment to a variable in a scope, that variable becomes local to that scope and overrides any variable with the same name in the global or outer scope.

var +=1 is similar to var = var + 1, therefore the Python interpreter should first read var, perform the addition and assign the value back to var.

var is a variable local to test_func, so the variable is read or referenced before we have assigned it. As a result, the Python interpreter raises the UnboundLocalError.

Example #1: Accessing a Local Variable

Let’s look at an example where we define a global variable number. We will use the increment_func to increase the numerical value of number by 1.

number = 10

def increment_func():
    number += 1
    return number

print(increment_func())

Let’s run the code to see what happens:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [19], in <cell line: 7>()
      4     number += 1
      5     return number
----> 7 print(increment_func())

Input In [19], in increment_func()
      3 def increment_func():
----> 4     number += 1
      5     return number

UnboundLocalError: local variable 'number' referenced before assignment

The error occurs because we tried to read a local variable before assigning a value to it.

Solution #1: Passing Parameters to the Function

We can solve this error by passing a parameter to increment_func. This solution is the preferred approach. Typically Python developers avoid declaring global variables unless they are necessary. Let’s look at the revised code:

number = 10

def increment_func(number):

    number += 1

    return number

print(increment_func(number))

We have assigned a value to number and passed it to the increment_func, which will resolve the UnboundLocalError. Let’s run the code to see the result:

11

We successfully printed the value to the console.

Solution #2: Use Global Keyword

We also can solve this error by using the global keyword. The global statement tells the Python interpreter that inside increment_func, the variable number is a global variable even if we assign to it in increment_func. Let’s look at the revised code:

number = 10

def increment_func():

    global number

    number += 1

    return number

print(increment_func())

Let’s run the code to see the result:

11

We successfully printed the value to the console.

Example #2: Function with if-elif statements

Let’s look at an example where we collect a score from a player of a game to rank their level of expertise. The variable we will use is called score and the calculate_level function takes in score as a parameter and returns a string containing the player’s level.

score = int(input("Enter your score between 0 and 100: "))

def calculate_level(score):

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    return level

In the above code, we have a series of if-elif statements for assigning a string to the level variable. Let’s run the code to see what happens:

print(f'Your level is: {calculate_level(score)}')
Enter your score between 0 and 100: 40

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 print(f'Your level is: {calculate_level(score)}')

Input In [11], in calculate_level(score)
      7 elif score > 55:
      8     level = 'intermediate'
----> 9 return level

UnboundLocalError: local variable 'level' referenced before assignment

The error occurs because we input a score equal to 40. The conditional statements in the function do not account for a value below 55, therefore when we call the calculate_level function, Python will attempt to return level without any value assigned to it.

Solution #1: Include else statement

We can solve this error by completing the set of conditions with an else statement. The else statement will provide an assignment to level for all scores lower than 55. Let’s look at the revised code:

score = int(input("Enter your score between 0 and 100: "))

def calculate_level(score):

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    else:

        level = 'beginner'

    return level

In the above code, all scores below 55 are given the beginner level. Let’s run the code to see what happens:

print(f'Your level is: {calculate_level(score)}')
Enter your score between 0 and 100: 40

Your level is: beginner

Solution #2: Use global keyword

We can also create a global variable level and then use the global keyword inside calculate_level. Using the global keyword will ensure that the variable is available in the local scope of the calculate_level function. Let’s look at the revised code.

score = int(input("Enter your score between 0 and 100: "))

level = 'beginner'

def calculate_level(score):

    global level

    if score > 90:

        level = 'expert'

    elif score > 70:

        level = 'advanced'

    elif score > 55:

        level = 'intermediate'

    return level

In the above code, we put the global statement inside the function and at the beginning. Note that the “default” value of level is beginner and we do not include the else statement in the function. Let’s run the code to see the result:

print(f'Your level is: {calculate_level(score)}')
40 

Your level is: beginner

Summary

Congratulations on reading to the end of this tutorial! The UnboundLocalError: local variable referenced before assignment occurs when you try to reference a local variable before assigning a value to it. Preferably, you can solve this error by passing parameters to your function. Alternatively, you can use the global keyword.

If you have if-elif statements in your code where you assign a value to a local variable and do not account for all outcomes, you may encounter this error. In which case, you must include an else statement to account for the missing outcome.

For further reading on Python code blocks and structure, go to the article: How to Solve Python IndentationError: unindent does not match any outer indentation level.

Go to the online courses page on Python to learn more about Python for data science and machine learning.

Have fun and happy researching!

Представим ситуацию. Вы написали функцию, инициализировали переменные где-то и собираетесь сделать тест вашего кода.

У вас все получилось, код запускается без ошибок, хотя, вот незадача, функция делает не то, что надо, а точнее — возвращает не желаемое вами значение. Ко всему этому, вы еще и не знаете, как это происходит. Переменные на месте, структура функции в порядке, в чем причина?

Возможно, вы неграмотно воспользовались областью видимости. Давайте рассмотрим пример:

#набор четных чисел
list_sqrt = [2,4,6,8,10]
#функция для преобразования числа в квадрат
def Sum():
  #однострочник, который возвращает число в квадрате
  list_sqrt = [i*i for i in list_sqrt]
  print(list_sqrt)
if __name__ == '__main__':
  Sum()
list_sqrt = [i*i for i in list_sqrt]
UnboundLocalError: local variable 'list_sqrt' referenced before assignment

Кратко о коде: есть список с числами, с помощью функции нужно, чтобы числа в этом же списке, были возведены в квадрат. Попробуем понять, что ощущает функция во время компилирования: «Хозяин, в строке 6 где происходит списковое включение, в цикле, временная переменная не понимает, по кому она проходит».

Можем сделать вывод, что временная переменная — i, совершает итерации, а точнее не совершает их вообще, по неопределенной последовательности. А с другого места в коде мы видим, что у нас есть нужная последовательность (строка 2). Тогда почему же функцая не делает то, что надо, а точнее вообще не делает? Все дело в области видимости.

В коде была определена глобальная последовательность и функция, которая использует локальную последовательность, т.е. та, которая должна использоваться и распостраняться в границах функции.

Кратко. В коде происходит попытка использования локальной последовательности в функции — как локальной. В чем и ошибка.

Как сделать ее локальной? Ведь без этого ей невозможно воспользоваться в функции? Одним словом — global.

Взглянем на следующий код:

#набор четных чисел
list_sqrt = [2,4,6,8,10]
#функция для преобразования числа в квадрат
def Sum():
  #определение последовательности как глобальной для функции
  global list_sqrt
  #однострочник, который возвращает число в квадрате
  list_sqrt = [i*i for i in list_sqrt]
  print(list_sqrt)

if __name__ == '__main__':
  Sum()

В строке 6 появился один новый элемент, а последовательность все та же. Теперь-то в коде список представляется как глобальный и входит за границы функции, и вывод таков:

[4, 16, 36, 64, 100]

У вас может появиться следующий вопрос: но если последовательность и до этого была в коде глобальной, а после добавления global осталась по-прежнему глобальной, хотя в функции нужен был локальный список, что это за абракадабра?

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

А если в блоке (в нашем случае — функции), обозначить последовательность как глобальную не только для пространства в коде, но еще и в желаемом блоке, то границы функции разваливаются, и распахивается дверь для избранного global’ом. И последовательность становится доступной внутри данного блока.

Итоги

Не забывайте о области видимости, зачастую именно из-за нее функции возвращают не то, что хотелось бы.

Здесь я не углублялся в данную тему и попросту рассказал всё своими словами. Вдобавок я оставляю ссылку на небольшую документацию по этой теме.

На этом — все. Если у вас есть своя тема, которую вы не понимаете, но хотите разобрать, пишите в комментариях, обсудим. Всем удачи и Джедай!

Понравилась статья? Поделить с друзьями:
  • Global cfg not found igo ошибка
  • Glo ошибки индикация
  • Glo коды ошибок
  • Glide3x dll diablo 2 ошибка
  • Glew32 dll ошибка