Objetos de Função e Closures em Python

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

Tags: Python Closure function-object first-class-functions

Publicado em 10-8 20:46