O que é Scope em Python e como ele funciona?

Em Python, o escopo determina o ponto em que você pode acessar uma variável. É o que controla o tempo de vida de uma variável e como ela é resolvida em diferentes partes do código. Para determinar corretamente o escopo, Python segue a regra LEGB, que significa o seguinte:
  • Escopo local (L): Variáveis definidas em funções ou classes.
  • Escopo envolvente (E): Variáveis definidas em funções envolventes ou aninhadas.
  • Escopo global (G): Variáveis definidas no nível superior do módulo ou arquivo.
  • Escopo embutido (B): Nomes reservados em Python para funções, módulos, palavras-chave e objetos predefinidos.
Python usa a regra LEGB para resolver o escopo das variáveis no seu programa. Vamos nos aprofundar em cada uma dessas regras para que você tenha uma melhor compreensão do processo. Escopo local significa que uma variável declarada dentro de uma função ou classe só pode ser acessada dentro dessa função ou classe. Aqui está um exemplo:
def my_func():
    my_var = 10
    print(my_var)
Neste caso, a função my_func tem seu próprio escopo que não pode ser acessado de fora da função. Chamar my_func irá exibir 10, mas imprimir my_var fora da função resultará em um NameError:
def my_func():
    my_var = 10 # Locally scoped to my_func
    print(my_var)

my_func() # 10

print(my_var) # NameError: name 'my_var' is not defined
Escopo envolvente significa que uma função que está aninhada dentro de outra função pode acessar as variáveis da função na qual está aninhada. Por exemplo:
def outer_func():
    msg = 'Hello there!'

    def inner_func():
        print(msg)

    inner_func()

outer_func() # Hello there!
Neste exemplo, a função interna, inner_func, pode acessar livremente a variável msg definida na função externa, outer_func. No entanto, observe que funções externas não podem acessar variáveis definidas dentro de funções aninhadas:
def outer_func():
    msg = 'Hello there!'
    print(res)

    def inner_func():
        res = 'How are you?'
        print(msg)

    inner_func()

outer_func() # NameError: name 'res' is not defined
Isso acontece porque res está com escopo local em inner_func. Além disso, note que outer_func tenta imprimir res antes de inner_func ser chamada. Uma solução é inicializar res como uma string vazia no escopo envolvente, que está dentro de outer_func. Então, dentro de inner_func, torne res uma variável não local com a palavra-chave nonlocal:
def outer_func():
    msg = 'Hello there!'
    res = ""  # Declare res in the enclosing scope

    def inner_func():
        nonlocal res  # Allow modification of an enclosing variable
        res = 'How are you?'
        print(msg)  # Accessing msg from outer_func()

    inner_func()
    print(res)  # Now res is accessible and modified

outer_func()

# Output:
# Hello there!
# How are you?
Escopo global refere-se a variáveis que são declaradas fora de qualquer função ou classe que podem ser acessadas de qualquer lugar no programa. Aqui, my_var pode ser acessado em qualquer lugar, até mesmo dentro de uma função onde ele não está definido:
my_var = 100

def show_var():
    print(my_var)

show_var() # 100
print(my_var) # 100
E se você quiser tornar uma variável com escopo local definida dentro de uma função acessível globalmente, você pode usar a palavra-chave global:
my_var_1 = 7

def show_vars():
    global my_var_2
    my_var_2 = 10
    print(my_var_1)
    print(my_var_2)

show_vars() # 7 10

# my_var_2 is now a global variable and can be accessed anywhere in the program
print(my_var_2) # 10
Você também pode usar a palavra-chave global para modificar uma variável global:
my_var = 10  # A global variable

def change_var():
    global my_var  # Allows modification of a global variable
    my_var = 20

change_var()

print(my_var)  # my_var is now modified globally to 20
Finalmente, built-in scope refere-se a todas as funções, módulos e palavras-chave internas do Python e estão disponíveis em qualquer lugar do seu programa:
print(str(45)) # '45'
print(type(3.14)) # <class 'float'>
print(isinstance(3, str)) # False
Este módulo não possui perguntas. Marque como concluído.