Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Scope of variable confusion
#1
Hi all,

Here's a simple code:

global check

check = 0

def sample_fcn():
  check += 1

sample_fcn()

print(check)
The result is UnboundLocalError: local variable 'check' referenced before assignment .

I'm guessing when the function runs and tries to add 1 to check, the program doesn't know what it's adding 1 to? Why didn't the first line make it available to the function, though?

Even if I add return check to the end of the function (to make sure the function actually returns something), I get the same exception.

And in case it matters, the reason I didn't put check = 0 inside the function is because I wanted to count the number of times the program runs through that function.
Reply
#2
The global keyword tells Python to look for the following symbols in the global scope instead of the local scope. Placing "global check" at the top of the file does not do anything at all because you are currently in the global scope.

global only makes sense inside a function. Here the "global check" tells Python that the "check" inside this function is the global variable "check".
def sample_fcn()
    global check  # The global has to be inside the function
    check += 1
Reply
#3
(Feb-23-2022, 09:55 PM)deanhystad Wrote: The global keyword tells Python to look for the following symbols in the global scope instead of the local scope. Placing "global check" at the top of the file does not do anything at all because you are currently in the global scope.

global only makes sense inside a function. Here the "global check" tells Python that the "check" inside this function is the global variable "check".
def sample_fcn()
    global check  # The global has to be inside the function
    check += 1

Thanks so much!
Reply
#4
Using the global keyword is highly discouraged in Python.
If you think you must use it, then you are doing something wrong.
Reply
#5
(Feb-24-2022, 10:53 AM)ThomasL Wrote: Using the global keyword is highly discouraged in Python.
If you think you must use it, then you are doing something wrong.

Why? What would be another way to accomplish the same thing?
Reply
#6
Global variables are not bad. Sometimes they are the right solution to a problem. But using lots of global variables can make you code difficult to work with.

The problem with a global variable is that the variable is defined in one place and used somewhere else that may be nowhere near the definition. If you want to know everything that modifies your global variable you need to search for all occurrences of the name and then verify that the each of those is actually referencing the global and not some local variable that has the same name. And since the variable is global it is visible to anyone who imports your module. A global variable can be changed by code you did not write.

Instead of a global variable you can pass a value as an argument and return the modified value.
def sample_fcn(check):
    return check + 1
You can make a function variable
def sample_fcn():
    sample_fcn.check_count += 1

sample_fcn.check_count = 0
sample_fcn()
print(sample_fcn.check_count)
You can make a class.
class Sample():
    def __init__(self):
        self.check = 0

    def fcn(self):
        self.check += 1

x = Sample()
x.fcn()
print(x.check)
Reply
#7
I'll just ask one more question and then try to let this simmer. What you said about using global keyword to "look for variable in the global scope" makes most sense to me, deanhystad.

However, I just read a DC article that seems to conflict a bit with that by claiming variables defined globally are available locally. So... what's the difference between this:

check = 0
 
def sample_fcn():
  print(check)

and

check = 0
 
def sample_fcn():
  check += 1
  print(check)
When calling sample_fcn(), the first prints 0. The second gives UnboundLocalError: local variable 'check' referenced before assignment. It was assigned globally, though.

It does make sense to me that if I define a variable locally with the same name was one that was globally initialized, it won't be the same as the latter--it'll be a local variable with the same name.
Reply
#8
(Feb-24-2022, 12:50 PM)Mark17 Wrote: Why? What would be another way to accomplish the same thing?

Let me tell you a story. Long ago the company where I worked had a large information system built. When it was ready we saw the programmers had used lots of global variables. What was the problem? A bug was found in one part of the system and it was repaired. But after that the use of the variables had changed and this influenced other parts of the program. This again caused bugs to be found. This kept on happening for years until at last the information system was replaced.

So what has to be done to prevent this kind of troubles? Large books have been written about the rules to prevent these problems. But as I have a simple mind I believe I can simplify the case by showing how to apply the rules on a function, because functions are the building blocks for larger programs. I leave it to you to think about classes, modules etc.
  • A function has input (parameters) and output (return value).
  • A function does not interfere with the main program other than by its parameters and its return value.
  • A function does not have side effects.

Now about your question. How should you use a function without global variables?
def sample_fcn(local_number):
    local_number += 1
    return local_number

check = 0
check = sample_fcn(check)
print(check)

Sorry deanhystad, you were typing faster than I did. And had more examples to do it right.
Mark17 likes this post
Reply
#9
There are different rules for accessing and assigning.

When looking to resolve a name Python looks in this order: local scope, enclosed scope, global/module scope, built-in scope. This is why Python functions and modules can use "input" and "print". These names exist in the built-in scope and can be seen by everyone.

When assigning a variable, Python uses the local scope unless otherwise directed.

Here I do something horrible and assigned the input variable to a module function instead of the built-in.
def input(x):
    return x**2

print(input(2))
Now this module cannot use the built-in input() because python resolves the "input" name in the global/module scope.

Here I do something less horrible and only assign the input variable to an enclosed function inside an enclosed scope. Outside the scope of my_func, input() works as before.
def my_func(x):
    def input(x):
        return x**2

    return input(x)

print(my_func(2)) 
print(input(2))
Reply
#10
(Feb-24-2022, 03:29 PM)deanhystad Wrote: There are different rules for accessing and assigning.

When looking to resolve a name Python looks in this order: local scope, enclosed scope, global/module scope, built-in scope. This is why Python functions and modules can use "input" and "print". These names exist in the built-in scope and can be seen by everyone.

When assigning a variable, Python uses the local scope unless otherwise directed.

I'm finding this a bit too complex for me to understand... can you apply this explanation to the two seemingly conflicting examples I gave in my last post? I think that would crystalize things for me.

Thanks!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to create a variable only for use inside the scope of a while loop? Radical 10 1,680 Nov-07-2023, 09:49 AM
Last Post: buran
  Library scope mike_zah 2 831 Feb-23-2023, 12:20 AM
Last Post: mike_zah
  Variable scope issue melvin13 2 1,529 Nov-29-2021, 08:26 PM
Last Post: melvin13
  Variable scope - "global x" didn't work... ptrivino 5 3,029 Dec-28-2020, 04:52 PM
Last Post: ptrivino
  Python Closures and Scope muzikman 2 1,799 Dec-14-2020, 11:21 PM
Last Post: muzikman
  Block of code, scope of variables and surprising exception arbiel 8 3,397 Apr-06-2020, 07:57 PM
Last Post: arbiel
  Help with Global/Coerced Variable (Understanding Scope) Rev2k 6 3,477 Jan-09-2020, 03:43 AM
Last Post: Rev2k
  Solving a scope issue profconn1 4 2,561 Nov-01-2019, 07:46 PM
Last Post: profconn1
  Namespace and scope difference Uchikago 9 4,579 Jul-03-2019, 03:36 PM
Last Post: Uchikago
  what is scope for python? samexpert 2 2,233 Jun-24-2019, 01:03 PM
Last Post: metulburr

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020