1. Objetos de Função
Em Python, funções são objetos de primeira classe, o que significa que podem ser tratadas como qualquer outro valor: atribuídas a variáveis, passadas como argumentos ou retornadas por outras funções.
1.1 Atribuição a variáveis
def saudacao():
print('Olá!')
msg = saudacao # msg agora referencia a função
msg() # Chama a função através da variável
1.2 Passagem como argumento
def executar(funcao):
funcao()
def cumprimentar():
print('Bom dia!')
executar(cumprimentar)
1.3 Retorno de funções
def criar_saudacao():
def interna():
return "Oi!"
return interna
saudar = criar_saudacao()
print(saudar()) # Saída: Oi!
1.4 Armazenamento em estruturas de dados
def opcao_a(): print("Opção A")
def opcao_b(): print("Opção B")
acoes = [opcao_a, opcao_b]
acoes[0]() # Executa opcao_a
menu = {'1': opcao_a, '2': opcao_b}
menu['2']() # Executa opcao_b
1.5 Exempplo prático: menu interativo
def login(): print("Autenticando...")
def registrar(): print("Criando conta...")
def transferir(): print("Transferindo...")
acoes = {
'0': ('Sair', None),
'1': ('Login', login),
'2': ('Registrar', registrar),
'3': ('Transferir', transferir)
}
while True:
for chave, (descricao, _) in acoes.items():
print(f"{chave}: {descricao}")
escolha = input("Escolha uma opção: ").strip()
if escolha == '0':
break
elif escolha in acoes and acoes[escolha][1]:
acoes[escolha][1]()
else:
print("Opção inválida.")
2. Clousres
Um closure ocorre quando uma função aninhada captura e mantém referências a variáveis não globais do escopo externo, mesmo após a função externa ter retornado.
2.1 Exemplo básico
x_global = 100
def externa():
x_local = 200
def interna():
print(x_local) # Captura x_local do escopo externo
return interna
funcao = externa()
funcao() # Imprime 200, não 100
2.2 Preservação de estado com closures
# Abordagem insegura com variável global
valores = []
def media_insegura(novo_valor):
valores.append(novo_valor)
return sum(valores) / len(valores)
# Abordagem segura com closure
def criar_calculadora_media():
serie = []
def calcular(novo_valor):
serie.append(novo_valor)
return sum(serie) / len(serie)
return calcular
media = criar_calculadora_media()
print(media(10)) # 10.0
print(media(20)) # 15.0
print(media(30)) # 20.0
2.3 Inspeção de closures
def fabrica():
contador = 0
def incrementar():
nonlocal contador
contador += 1
return contador
return incrementar
inc = fabrica()
print(inc.__code__.co_freevars) # ('contador',)
print(inc.__code__.co_varnames) # ()
print(inc.__closure__[0].cell_contents) # 0 (após chamada, será 1, 2, etc.)
2.4 Caso de uso: configuração de requisições HTTP
import requests
def criar_requisicao(url_base):
def buscar():
resposta = requests.get(url_base)
return len(resposta.text)
return buscar
baixar_pagina = criar_requisicao('https://example.com')
print(baixar_pagina()) # Tamanho da página
print(baixar_pagina()) # Reutiliza a mesma URL sem repetir o parâmetro