Módulo functools

functools é um módulo do Python que fornece ferramentas para manipulação e criação de funções de maneira mais eficiente. Ele é usado principalmente para melhorar o desempenho, criar decoradores e manipular objetos que se comportam como funções.

Principais características do functools:
  1. Redução de código repetitivo: Inclui utilitários para aplicar funções de forma eficiente.
  2. Decoração e modificação de funções: Facilita a criação e aplicação de decoradores.
  3. Desempenho: Oferece ferramentas para melhorar a performance, como memoization (cache).
Função Descrição
functools.partial Permite criar versões parciais de uma função, com alguns argumentos já definidos.
functools.lru_cache Implementa um cache para funções, armazenando resultados de chamadas anteriores para otimização.
functools.reduce Aplica uma função acumuladora a um iterável, reduzindo-o a um único valor.
functools.total_ordering Simplifica a implementação de todos os operadores de comparação em classes personalizadas.
functools.wraps Facilita a criação de decoradores preservando metadados da função original.
functools.cache Similar a lru_cache, mas mais simples, sem controle de tamanho ou limpeza do cache.
functools.singledispatch Permite criar funções genéricas que mudam seu comportamento com base no tipo do argumento.

cache

@functools.cache esse decorador salva na memória o cache do resultado da função.

cache.py
import functools

@functools.cache
def calcular_fatorial(n):
    print("Valor de n atual: ",n)
    if n == 0:
        return 1
    return n * calcular_fatorial(n-1)

# Executou a função completa pela primeira vez
print(calcular_fatorial(4))

# Dessa vez ele nem entra na função e já entrega o resultado por causa do cache quando o valor do parametro é 4
print(calcular_fatorial(4))

 # Pegou o cache do valor 4 e so efetuou a recursão no 6 5 no 5
print(calcular_fatorial(6))

# Já estava no cache
print(calcular_fatorial(3))

Executa da primeira vez, mas na próxima ele "lembra e já da o resultado sem executar"


partial

Cria uma função com alguns argumentos já definidos, reduzindo a necessidade de passar esses valores sempre. fixa alguns dos seus parâmetros na função original, criando uma nova função que usa esses valores predefinidos.

partial.py
from functools import partial

# Função original
def multiplicar(x, y):
    return x * y

# Recebe uma função e os/o argumento a ser pré-definido/padrão. Fixa o primeiro argumento em 2
dobrar = partial(multiplicar, 2)

# Usar a nova função
print(dobrar(5))  # 10
print(dobrar(10))  # 20

Nesse caso, também é possivel identificar o parametro nominalmente ex.: partial(multiplicar, y=2)

partial_sorted.py
from functools import partial

# Uso uma função anônima para gerar uma lista para sorted ordenar
ordenar_lista_numerica = partial(sorted,key=lambda x: x if x > 2 and x <= 7 else 20)

lista_desordenada = [3,7,5,9,2,1,8,0,4,6]
print(ordenar_lista_numerica(lista_desordenada))

Toda vez que eu precisar ordenar uma lista com uma logica especifica, nesse caso apenas do 3 ao 7, chamo essa função já pronta ao invés de recriar o sorted toda vez.

obs.: sorted recebe uma função e uma lista como parâmetro.

Saída: [3, 4, 5, 6, 7, 9, 2, 1, 8, 0]

Obs.: o else 20. joga os numero que não estiverem entre 3 e 7 na chave 20 da lista (por ultimo). se fosse chave 1 seria em primeiro na lista.