Escopo em Python
Aprenda sobre escopo em Python e a regra LEGB: escopos local, delimitador, global e embutido, com exemplos, armadilhas e as palavras-chave global/nonlocal.
Entendendo o Escopo em Python
Escopo determina onde um nome de variável é visível e por quanto tempo ele existe. Todo nome que você cria — uma variável, uma função, uma classe — pertence a exatamente um escopo. Quando Python encontra um nome, ele pesquisa os escopos em uma ordem estrita até encontrá-lo ou lançar um NameError.
Esta página aborda:
- Os quatro níveis de escopo e a regra de busca LEGB
- As palavras-chave
globalenonlocal - Armadilhas comuns: sombreamento,
UnboundLocalErrore vazamento de nomes - Como inspecionar escopos em tempo de execução
A Regra LEGB
Python resolve nomes em quatro camadas, pesquisadas da mais interna para a mais externa:
| Nível | Significa | O que contém |
|---|---|---|
| L | Local | Nomes definidos dentro da função atual |
| E | Delimitador (Enclosing) | Nomes em qualquer função delimitadora (externa), para funções aninhadas |
| G | Global | Nomes definidos no nível superior do módulo atual |
| B | Embutido (Built-in) | Nomes pré-carregados pelo Python — print, len, range, type, etc. |
Python para na primeira correspondência. Se nenhuma correspondência for encontrada em nenhuma camada, um NameError é lançado.
Escopo Local
Um nome é local quando é atribuído dentro de uma função. Ele é criado quando a função é chamada e destruído quando a função retorna. Nomes locais são invisíveis fora da função.
def greet():
message = "Hello, World!" # local variable
print(message) # accessible here
greet()
# Output: Hello, World!
print(message) # NameError: name 'message' is not definedPor que o escopo local é importante
O escopo local permite usar nomes simples e descritivos como total, result ou i dentro de cada função sem que nenhum deles entre em conflito entre si ou com o código do módulo.
def calculate_area(radius):
pi = 3.14159 # local to this function
area = pi * radius ** 2
return area
def calculate_volume(radius, height):
pi = 3.14159 # completely separate local 'pi'
volume = pi * radius ** 2 * height
return volume
print(calculate_area(5)) # 78.53975
print(calculate_volume(5, 10)) # 785.3975Ambas as funções usam pi de forma independente. Não há conflito.
Escopo Delimitador (Enclosing)
Quando uma função é definida dentro de outra função, a função interna pode ler nomes da função externa (delimitadora). Este é o E no LEGB.
def outer():
color = "blue" # enclosing variable
def inner():
print(color) # reads from enclosing scope
inner()
outer()
# Output: blueA função interna pode ler color sem nenhuma palavra-chave especial, porque Python sobe automaticamente para o escopo delimitador.
Modificando uma variável delimitadora com nonlocal
Ler uma variável delimitadora é automático, mas atribuir a ela requer a palavra-chave nonlocal. Sem ela, Python trata a atribuição como a criação de uma nova variável local, não como a modificação da variável delimitadora.
def make_counter():
count = 0 # enclosing variable
def increment():
nonlocal count # declare intent to modify the enclosing 'count'
count += 1
return count
return increment
counter = make_counter()
print(counter()) # 1
print(counter()) # 2
print(counter()) # 3Cada chamada a counter() modifica a mesma variável count. Esse padrão é a base dos closures — consulte Python Closures para uma análise mais aprofundada.
Escopo Global
Nomes definidos no nível superior de um módulo (fora de qualquer função) são globais. Eles são acessíveis de qualquer lugar no mesmo módulo, inclusive dentro de funções.
language = "Python" # global variable
def display_language():
print(language) # reads global without any keyword
display_language()
# Output: PythonModificando uma variável global com global
Você pode ler uma variável global de dentro de uma função sem nenhuma palavra-chave. Mas se quiser atribuir a ela, deve declará-la com global primeiro:
total = 0 # global variable
def add_to_total(n):
global total # declare intent to modify the global
total += n
add_to_total(5)
add_to_total(3)
print(total) # 8Sem global total, a linha total += n lançaria um UnboundLocalError porque Python trataria total como uma variável local que ainda não foi atribuída.
Para mais informações sobre variáveis globais, consulte Python Global Variables.
Quando evitar global
Usar global extensivamente torna o código mais difícil de testar e compreender. Prefira retornar valores de funções e passar dados como argumentos. Reserve global para o estado real do nível de módulo — flags de configuração, contadores ou caches — e use-o com moderação.
Escopo Embutido (Built-in)
O escopo embutido contém nomes que Python fornece automaticamente. Eles estão disponíveis em todos os módulos sem qualquer importação.
Os nomes embutidos comuns incluem print, len, range, type, int, str, list, dict, set, tuple, open, input, max, min, sum, sorted, enumerate, zip e map.
Não sobreponha nomes embutidos
Como o escopo embutido é pesquisado por último, qualquer nome local ou global com a mesma grafia o sobreporá. Este é um erro comum:
# Bad: shadows the built-in 'list'
list = [1, 2, 3]
print(type(list)) # <class 'list'> — still works here
new = list([4, 5]) # TypeError: 'list' object is not callableExclua o nome sobreposto para restaurar o embutido:
del list # remove the local/global shadowing name
new = list([4, 5]) # works again: [4, 5]O módulo embutido está disponível como builtins caso você precise acessá-lo explicitamente:
import builtins
print(builtins.len([1, 2, 3])) # 3Armadilhas Comuns
UnboundLocalError
O erro de escopo mais frequente em Python é ler um nome antes de atribuí-lo dentro de uma função quando também há uma atribuição a esse nome em qualquer lugar na mesma função:
x = 10
def bad_func():
print(x) # UnboundLocalError! Python sees x = 20 below
x = 20 # this makes 'x' local for the whole function
bad_func()Python decide em tempo de compilação que x é local (porque é atribuído na função). A tentativa de lê-lo antes da atribuição lança UnboundLocalError: local variable 'x' referenced before assignment.
Corrija declarando global x ou simplesmente não atribuindo a x dentro da função.
Sombreamento de variáveis
Uma variável local que compartilha um nome com uma global silenciosamente sobrep a global. Isso geralmente é intencional, mas pode causar bugs sutis quando você espera estar lendo a global:
x = 10 # global
def my_func():
x = 20 # local — shadows the global
print(x) # 20, not 10
my_func()
print(x) # 10 — global unchangedInspecionando o Escopo em Tempo de Execução
Python expõe o conteúdo do escopo atual por meio de duas funções embutidas.
locals() retorna um dicionário do escopo local atual (ou o namespace do nível do módulo se chamado no nível superior):
def show_locals():
a = 1
b = "hello"
print(locals()) # {'a': 1, 'b': 'hello'}
show_locals()globals() retorna o dicionário do namespace global (nível do módulo):
language = "Python"
print("language" in globals()) # TrueEssas funções são úteis para depuração e introspecção, mas não devem ser usadas para manipular variáveis dinamicamente em código de produção.
Escopo e Funções
Funções em Python são objetos e são, elas próprias, nomes que vivem em algum escopo. Uma função definida no topo de um módulo é global; uma função definida dentro de outra função é local à função delimitadora.
def outer():
def helper(): # helper is local to outer
return 42
return helper()
print(outer()) # 42
# helper() # NameError: helper is not defined hereConsulte Python Functions para saber como as funções são definidas, e Python Lambda para funções anônimas que também obedecem à regra LEGB.
Referência Rápida
| Palavra-chave | Efeito |
|---|---|
| (nenhuma) | Lê do escopo delimitador mais próximo pela busca LEGB |
global x | Informa à função atual que x se refere ao nome no nível do módulo |
nonlocal x | Informa à função atual que x se refere ao nome na função delimitadora mais próxima |