Variables visibility and scope

Reading time10 min

In brief

Article summary

In this article, we discuss variables visibility. This denotes the scope in which variables exist and can be used. In particular, we discuss the difference between local and global variables.

Main takeaways

  • Local variables are only visible in the scope of the function that uses them.

  • Global variables are accessible everywhere in the program.

  • Global variables should be avoided in favor of local variables.

Article contents

As seen in session 1, a variable explicitly associates a name with a value and implicitly occupies space in main memory, the size of which depends on the type of variable. The value currently associated with the variable can be accessed through the variable’s name.

Due to memory limitations, not all variables exist throughout the life of a program. A component of the Python interpreter, called the “garbage collector” deletes variables that cannot be used anymore, and thus frees the memory they occupied.

The visibility of a variable determines its lifetime, and two types of visibility are considered in Python, namely local and global variables.

1 — Local vs. global variables

Local variables are defined inside a function and not accessible outside it.

Example

In this example, we define two variables a and b that are local to function example. They only exist inside example and cease to exist once the function/procedure has returned/completed.

# Define a function
def example (a):

    """
        This is an example function with two local variables.
        In:
            * a: An argument of the function.
        Out:
            * None.
    """

    # Define a local variable
    b = 2

    # Print variables
    print(a, b)



# Call it and try to access variables
example(1)
print(a, b)
/**
 * To run this code, you need to have Java installed on your computer, then:
 * - Create a file named `Main.java` in a directory of your choice.
 * - Copy this code in the file.
 * - Open a terminal in the directory where the file is located.
 * - Run the command `javac Main.java` to compile the code.
 * - Run the command `java -ea Main` to execute the compiled code.
 * Note: '-ea' is an option to enable assertions in Java.
 */
public class Main {

    /**
     * This is an example function with two local variables
     *
     * @param a An argument of the function.
     */
    public static void example(int a) {
        // Define a local variable
        int b = 2;
        // Print variables
        System.out.println(a + " " + b);
    }

    /**
     * This is the entry point of your program.
     * It contains the first codes that are going to be executed.
     *
     * @param args Command line arguments received.
     */
    public static void main(String[] args) {
        // Call it and try to access variables
        example(1);
        System.out.println(a + " " + b);
    }

}

Here is the output we get:

Output
1 2
Traceback (most recent call last):
  File "exaple.py", line 22, in <module>
    print(a, b)
NameError: name 'a' is not defined
Main.java:33: error: cannot find symbol
        System.out.println(a + " " + b);
                           ^
  symbol:   variable a
  location: class Main
Main.java:33: error: cannot find symbol
        System.out.println(a + " " + b);
                                     ^
  symbol:   variable b
  location: class Main
2 errors

Global variables are defined outside all functions and accessible anywhere in the code.

Example

Let’s declare a global variable a, but also a local variable called a, and let’s print these:

# Define a global variable
a = 1



# Define a function
def example ():

    """
        Example function with a local variable, also named "a".
        In:
            * None.
        Out:
            * None.
    """

    # Define a local variable
    a = 2

    # Print a to see which one we use
    print(a)



# See what we got
print(a)
example()
print(a)
/**
 * To run this code, you need to have Java installed on your computer, then:
 * - Create a file named `Main.java` in a directory of your choice.
 * - Copy this code in the file.
 * - Open a terminal in the directory where the file is located.
 * - Run the command `javac Main.java` to compile the code.
 * - Run the command `java -ea Main` to execute the compiled code.
 * Note: '-ea' is an option to enable assertions in Java.
 */
public class Main {

    /**
     * Define a global variable (in Java, we use a class-level variable).
     */
    static int a = 1;

    /**
     * Example function with a local variable, also named "a".
     */
    public static void example() {
        // Define a local variable
        int a = 2;
        // Print a to see which one we use
        System.out.println(a);
    }

    /**
     * This is the entry point of your program.
     * It contains the first codes that are going to be executed.
     *
     * @param args Command line arguments received.
     */
    public static void main(String[] args) {
        // See what we got
        System.out.println(a);
        example();
        System.out.println(a);
    }

}

Here is the output we get:

Output
1
2
1
1
2
1

Note that local variables “hide” global variables with the same name.

2 — The global and nonlocal keywords

Python offers two keywords to play with variables visibility.

The global keyword is used to modify a global variable inside a function.

Example

Let’s adapt the code above, to indicate in example that a is global. Here, the global keyword indicates not to redefine a new variable, but to find an existing one in global memory.

# Define a global variable
a = 1



# Define a function
def example ():

    """
        Example function with access to global variable "a".
        In:
            * None.
        Out:
            * None.
    """

    # Indicate that a exists in the global scope
    global a

    # Update global variable
    a = 2

    # Print global variable
    print(a)



# See what we got
print(a)
example()
print(a)
/**
 * To run this code, you need to have Java installed on your computer, then:
 * - Create a file named `Main.java` in a directory of your choice.
 * - Copy this code in the file.
 * - Open a terminal in the directory where the file is located.
 * - Run the command `javac Main.java` to compile the code.
 * - Run the command `java -ea Main` to execute the compiled code.
 * Note: '-ea' is an option to enable assertions in Java.
 */
public class Main {

    /**
     * Define a global variable (in Java, we use a class-level variable).
     */
    static int a = 1;


    /**
     * Example function with access to global variable "a".
     */
    public static void example() {
        // Update global variable
        a = 2;
        // Print global variable
        System.out.println(a);
    }

    /**
     * This is the entry point of your program.
     * It contains the first codes that are going to be executed.
     *
     * @param args Command line arguments received.
     */
    public static void main(String[] args) {
        // See what we got
        System.out.println(a);
        example();
        System.out.println(a);
    }

}

Here is the output we get:

Output
1
2
2
1
2
2

The nonlocal keyword is used in nested functions to modify a variable in the enclosing scope. This is quite a cornercase situations, however it can be of use when working with nested functions.

Example

Let’s adapt the code above with a nested function. Note that Java handles scopes differently, and there is thus no equivalent.

# Define a global variable
a = 1



# Define a function
def example ():

    """
        Example function with a nested function.
        Note that "inner" cannot be called from outside the body of function "example".
        In:
            * None.
        Out:
            * None.
    """
    
    # Local variable
    a = 2

    # Inner function
    def inner ():
        nonlocal a
        a = 3
    
    # Call inner function
    print(a)
    inner()
    print(a)



# See what we got
print(a)
example()
print(a)

Here is the output we get:

Output
1
2
3
1
1
2
3
1

Visible local and global variables are stored into two separated data structures (i.e., dictionnaries) that can be displayed calling the locals() and globals() functions, respectively.

Important

In general, it is best to avoid using global variables, as they can be a source of errors. For instance, consider the following function:

# Define a global variable
a = 1



# Define a function
def example (b):

    """
        Example function.
        In:
            * b: An argument of the function.
        Out:
            * The product of a and b.
    """

    # Indicate that a exists in the global scope
    global a

    # Update a
    a += 1

    # Return a computation that depends on a and b
    return a * b




# See what we got
res = example(2)
print(res)
res = example(2)
print(res)
/**
 * To run this code, you need to have Java installed on your computer, then:
 * - Create a file named `Main.java` in a directory of your choice.
 * - Copy this code in the file.
 * - Open a terminal in the directory where the file is located.
 * - Run the command `javac Main.java` to compile the code.
 * - Run the command `java -ea Main` to execute the compiled code.
 * Note: '-ea' is an option to enable assertions in Java.
 */
public class Main {

    /**
     * Define a global variable (in Java, we use a class-level variable).
     */
    static int a = 1;

    /**
     * Example function.
     *
     * @param b An argument of the function.
     */
    public static int example(int b) {
        // Update a
        a += 1;
        // Return a computation that depends on a and b
        return a * b;
    }

    /**
     * This is the entry point of your program.
     * It contains the first codes that are going to be executed.
     *
     * @param args Command line arguments received.
     */
    public static void main(String[] args) {
        // See what we got
        int res = example(2);
        System.out.println(res);
        res = example(2);
        System.out.println(res);
    }

}

Calling it twice will lead to two different results (4, then 6), which is not a standard behavior.

To go further

Important

The content of this section is optional. It contains additional material for you to consolidate your understanding of the current topic.

Looks like this section is empty!

Anything you would have liked to see here? Let us know on the Discord server! Maybe we can add it quickly. Otherwise, it will help us improve the course for next year!

To go beyond

Important

The content of this section is very optional. We suggest you directions to explore if you wish to go deeper in the current topic.

  • Java Modifiers

    Some languages, as Java, provides additional strategies to determine access levels to variables and other components.