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:
print()
– used to output data to the screen.len()
– returns the length of an object (list, string, etc.).type()
– returns the type of the object.input()
– reads a line of input from the user.int()
,float()
,str()
– functions for converting data types.range()
– generates a sequence of numbers.sum()
– returns the sum of the elements of a sequence.min()
,max()
– return the minimum and maximum elements in the sequence.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.