Everything You Need to Know About Scopes in Python

Understanding scopes can help you avoid some very serious problems. For example, accidentally redefining global variables inside functions or using variables before they are declared can lead to subtle bugs.

To determine the sequence in which Python searches for a variable's value, a rule is used LEGB. This rule represents the order of variable search in the following scopes: Local (local), Enclosing (nested), Global (global) and Built-in (built-in).

About the built-in area right away

The built-in scope in Python contains predefined functions, types, and exceptions that are accessible from anywhere in the program. This scope is loaded automatically when the Python interpreter starts and is accessible from anywhere in the program.

Python provides many built-in functions and attributes. Some of them are:

  1. print() – used to output data to the screen.

  2. len() – returns the length of an object (list, string, etc.).

  3. type() – returns the type of the object.

  4. input() – reads a line of input from the user.

  5. int(), float(), str() – functions for converting data types.

  6. range() – generates a sequence of numbers.

  7. sum() – returns the sum of the elements of a sequence.

  8. min(), max() – return the minimum and maximum elements in the sequence.

  9. sorted() – returns a sorted list.

Local scope

Local scope concerns variables that are declared within a function or lambda expression. These variables are only accessible within the function.in which they are declared, and are destroyed after the function completes execution.

Local variables are declared within a function and are accessible only within that function. Their scope is limited to the function body and they are not accessible outside of it.

def greet():
    message = "Hello, World!"  # kокальная переменная
    print(message)

greet()  # выведет: Hello, World!
print(message)  # ошибка: NameError, так как 'message' недоступна за пределами функции

Lambda expressions can also contain local variables that exist only in the execution context of that lambda.

square = lambda x: x ** 2
print(square(5))  # выведет: 25

Local variables are created each time a function is called and are destroyed after its execution is complete. That is, each time a function is called, new instances of local variables are created, regardless of previous calls.

def counter():
    count = 0  # локальная переменная
    count += 1
    print(count)

counter()  # выведет: 1
counter()  # выведет: 1 (новая переменная 'count' создается при каждом вызове функции)

Application examples

Local variables are great for temporarily storing intermediate results that are only needed within a single function:

def process_data(data):
    temp_result = []  # локальная переменная для временного хранения
    for item in data:
        temp_result.append(item * 2)
    return temp_result

data = [10, 20, 30]
print(process_data(data))  # выведет: [20, 40, 60]

Lambda expressions are often used as arguments to functions, such as map, filter And reduce:

numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # выведет: [1, 4, 9, 16, 25]

Closings allow internal functions to remember the state of their environment:

def outer_function():
    message = "Hello"

    def inner_function():
        print(message)

    return inner_function

my_function = outer_function()
my_function()  # выведет: Hello

Local variables can be used to manage state within a function:

def search_item(data, target):
    found = False  # локальная переменная для отслеживания состояния
    for item in data:
        if item == target:
            found = True
            break
    return found

data = [1, 2, 3, 4, 5]
print(search_item(data, 3))  # выведет: True
print(search_item(data, 6))  # выведет: False

Global scope

The global scope in Python covers all variables defined at the top level of a script or module.

Global variables are declared outside all functions and are available for use anywhere in the program. Their life cycle continues throughout the execution of the program. For example:

global_var = "I am a global variable"

def print_global():
    print(global_var)

print_global()  # выведет: I am a global variable

To read global variables inside a function, no special actions are required. However, to change them, you must use the keyword global. Without this keyword, Python will create a new local variable with the same name as the global variable, but will not change the global variable.

Reading a global variable inside a function:

count = 10

def print_count():
    print(count)  # использует глобальную переменную count

print_count()  # выведет: 10

Modifying a global variable inside a function:

count = 10

def increment_count():
    global count
    count += 1

increment_count()
print(count)  # выведет: 11

Examples of using

Using global variables to store configuration:

config = {
    "host": "localhost",
    "port": 8080
}

def print_config():
    print(f"Host: {config['host']}, Port: {config['port']}")

print_config()
# Выведет: Host: localhost, Port: 8080

Managing state through global variables:

is_logged_in = False

def log_in():
    global is_logged_in
    is_logged_in = True

def log_out():
    global is_logged_in
    is_logged_in = False

def check_login_status():
    return "Logged in" if is_logged_in else "Logged out"

print(check_login_status())  # Выведет: Logged out
log_in()
print(check_login_status())  # Выведет: Logged in

Global variables and multithreading:

import threading

counter = 0
lock = threading.Lock()

def increment():
    global counter
    with lock:
        for _ in range(10000):
            counter += 1

threads = [threading.Thread(target=increment) for _ in range(10)]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

print(counter)  # ожидаемый результат: 100000

Scope within a function

Nested functions are functions defined inside other functions. Nested functions can access variables defined in their outer functions. This ability makes it possible to create closureswhere the inner function remembers the context in which it was created, even after the external function has completed execution.

nonlocal is a keyword used to declare a variable that is in an outer function but not in the global scope. It allows the inner function to change the value of that variable.

def outer_function():
    message = "Hello, World!"

    def inner_function():
        nonlocal message
        message = "Hello, Python!"

    inner_function()
    print(message)

outer_function()  # выведет: Hello, Python!

nonlocal is used to indicate that a variable in the local scope of an inner function should be bound to a variable defined in an outer function. This allows you to modify variables that are in scope between local and global.

def outer_function():
    outer_var = "outer"

    def middle_function():
        middle_var = "middle"

        def inner_function():
            nonlocal outer_var, middle_var
            outer_var = "modified outer"
            middle_var = "modified middle"

        inner_function()
        print(middle_var)

    middle_function()
    print(outer_var)

outer_function()  
# выведет:
# modified middle
# modified outer

Examples

Factory The function returns a nested function that uses variables from the outer function to perform its tasks:

def make_multiplier(factor):
    def multiplier(x):
        return x * factor
    return multiplier

double = make_multiplier(2)
triple = make_multiplier(3)

print(double(5))  # выведет: 10
print(triple(5))  # выведет: 15

A function call counter that keeps track of the number of times a function has been called:

def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter

counter = make_counter()
print(counter())  # выведет: 1
print(counter())  # выведет: 2
print(counter())  # выведет: 3

Decorators often use nested functions to change the behavior of other functions:

def my_decorator(func):
    def wrapper():
        print("Что-то происходит перед функцией.")
        func()
        print("Что-то происходит после функции.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()
# Выведет:
# Что-то происходит перед функцией.
# Hello!
# Что-то происходит после функции.

Scopes and built-in functions allow you to create more structured, bug-free programs.

OTUS experts tell more about programming languages ​​and their features in practical online courses. You can see the full catalog of courses see the link.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *