Python tricks não são mágica - são conhecimento prático que transforma código complicado em algo limpo, rápido e fácil de manter. Muitos programadores passam anos usando Python da mesma forma que aprendem nos tutoriais básicos, sem nunca descobrir que existem maneiras muito mais eficientes de fazer as mesmas coisas. O que parece um pequeno detalhe - como usar um operador de desempacotamento ou uma compreensão de lista - pode economizar horas de trabalho e deixar seu código mais legível para os outros. Este guia não é sobre teoria. É sobre o que você realmente pode usar amanhã no seu projeto.
Desempacotamento inteligente: menos linhas, mais clareza
Você já teve que trocar valores entre duas variáveis? Na maioria das linguagens, você precisaria de uma terceira variável temporária. Em Python, basta uma linha:
a, b = b, a
Isso funciona porque Python cria uma tupla invisível à direita e desempacota na ordem à esquerda. Mas isso não é só para trocar variáveis. Imagine que você recebe uma lista de dados de um usuário: nome, idade, cidade, e-mail. Em vez de fazer:
dados = ['João', 28, 'Recife', '[email protected]']
nome = dados[0]
idade = dados[1]
cidade = dados[2]
e_mail = dados[3]
Use desempacotamento:
nome, idade, cidade, e_mail = dados
Se você só quer os dois primeiros valores e ignora o resto, use o operador *:
nome, idade, *outros = dados
Agora outros é uma lista com ['Recife', '[email protected]']. Isso é útil quando você lida com entradas de API ou arquivos CSV onde a estrutura pode variar.
Compreensão de lista: o jeito Python de transformar dados
Quem já escreveu algo assim?
quadrados = []
for x in range(10):
quadrados.append(x ** 2)
Isso funciona. Mas é verbose. Em Python, você pode fazer tudo em uma linha:
quadrados = [x ** 2 for x in range(10)]
E se quiser só os pares?
quadrados_pares = [x ** 2 for x in range(10) if x % 2 == 0]
Isso é mais rápido e mais legível. Mas atenção: não force compreensões em casos complexos. Se a lógica tiver mais de duas condições ou chamar funções externas, use um loop normal. A legibilidade vem antes da elegância.
Compreensões também funcionam com dicionários:
quadrados_dict = {x: x ** 2 for x in range(5)}
# Resultado: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Operador Walrus: atribuir e testar na mesma linha
Introduzido no Python 3.8, o operador := (chamado de "walrus", por causa da forma que lembra olhos e presas de uma morsa) permite atribuir valor e usar a variável na mesma expressão. Antes, você fazia algo como:
nome = input('Digite seu nome: ')
if len(nome) > 5:
print('Nome longo!')
Agora, pode fazer:
if (nome := input('Digite seu nome: ')) and len(nome) > 5:
print('Nome longo!')
Isso é útil em loops e expressões condicionais onde você precisa usar o mesmo valor mais de uma vez. Por exemplo, ao processar linhas de um arquivo:
while (linha := arquivo.readline()) != '':
processar(linha)
Evite abusar. Se o código fica confuso, volte ao jeito tradicional. O walrus não é para tornar o código mais curto - é para evitar repetição e melhorar desempenho.
Context managers e o with: gerencie recursos sem esquecer
Quem já esqueceu de fechar um arquivo? Ou de liberar uma conexão de banco? Em Python, você usa with para garantir que os recursos sejam limpos automaticamente, mesmo se ocorrer um erro.
with open('dados.txt', 'r') as arquivo:
conteudo = arquivo.read()
# O arquivo é fechado automaticamente aqui, mesmo se der erro
Isso não funciona só com arquivos. Funciona com conexões de banco, sockets, threads e até bibliotecas que você escreve. Basta implementar os métodos __enter__ e __exit__.
Exemplo prático: você precisa conectar ao banco de dados e executar uma query. Sem with, você teria que escrever conexao.close() em vários lugares. Com with:
with sqlite3.connect('meu_banco.db') as conn:
cursor = conn.cursor()
cursor.execute('SELECT * FROM usuarios')
resultados = cursor.fetchall()
# Conexão fechada automaticamente
Isso elimina vazamentos de memória e erros de conexão que só aparecem em produção.
Funções lambda e map: quando usar e quando evitar
Funções lambda são úteis para operações simples e rápidas. Mas muita gente as usa onde não deveria.
Exemplo bom:
numeros = [1, 2, 3, 4, 5]
dobrados = list(map(lambda x: x * 2, numeros))
Exemplo ruim:
# Evite isso
resultado = list(map(lambda x: x if x > 0 else None if x < 0 else 'zero', numeros))
Isso é confuso. Use uma função normal:
def classificar(x):
if x > 0:
return x
elif x < 0:
return None
else:
return 'zero'
resultado = list(map(classificar, numeros))
Lambda é para funções de uma linha, sem lógica complexa. E prefira compreensões de lista a map() quando possível - são mais legíveis e mais rápidas em Python.
Iteradores e geradores: não carregue tudo na memória
Quando você usa range(1000000), o Python não cria uma lista com um milhão de números. Ele gera cada número sob demanda. Isso é um iterador. E você pode criar os seus próprios com geradores.
Exemplo:
def numeros_pares(n):
for i in range(n):
if i % 2 == 0:
yield i
Agora você pode usar:
for par in numeros_pares(1000000):
print(par)
if par > 100:
break
Isso consome pouca memória. Se você tivesse usado uma lista, o Python teria guardado todos os números pares até 1.000.000 na memória - algo que pode travar seu sistema.
Geradores são essenciais quando você lida com arquivos grandes, streams de dados ou APIs que retornam milhares de registros. Nunca carregue tudo de uma vez. Use yield.
Decoradores: estenda funções sem modificar o código
Decoradores são uma das características mais poderosas do Python. Eles permitem adicionar funcionalidades a funções sem alterar seu código original. Por exemplo, você quer medir o tempo de execução de uma função?
import time
def cronometrar(func):
def wrapper(*args, **kwargs):
inicio = time.time()
resultado = func(*args, **kwargs)
fim = time.time()
print(f"{func.__name__} levou {fim - inicio:.2f} segundos")
return resultado
return wrapper
@cronometrar
def calculo_lento():
time.sleep(2)
return sum(range(1000000))
calculo_lento()
# Saída: calculo_lento levou 2.00 segundos
Isso é útil para logging, autenticação, cache, validação - qualquer coisa que você queira aplicar a várias funções sem repetir código. O @ é só uma sintaxe elegante para calculo_lento = cronometrar(calculo_lento).
Use decoradores para coisas que são transversais - não para lógica de negócio. Mantenha seu código limpo.
Usar __slots__ para reduzir uso de memória
Classes em Python criam um dicionário interno para armazenar atributos. Isso é flexível, mas pesado. Se você tem milhares de objetos da mesma classe, isso pode consumir muita memória.
Com __slots__, você define exatamente quais atributos a classe pode ter - e elimina o dicionário.
class Ponto:
__slots__ = ['x', 'y']
def __init__(self, x, y):
self.x = x
self.y = y
Isso reduz o uso de memória em até 40% e acelera o acesso aos atributos. Mas tem um custo: você não pode adicionar atributos dinâmicos depois. Se precisar de flexibilidade, não use __slots__. Use quando você tem muitos objetos iguais - como pontos em um gráfico, registros de banco de dados ou entidades em jogos.
Combinando tudo: um exemplo real
Vamos juntar tudo isso em um exemplo prático. Suponha que você tem um arquivo CSV com 500 mil linhas de vendas: data, produto, valor, cliente. Você quer:
- Carregar só as vendas acima de R$ 1.000
- Calcular o total por cliente
- Mostrar o tempo de processamento
Sem truques, você faria algo como:
import csv
vendas = []
with open('vendas.csv', 'r') as f:
leitor = csv.reader(f)
for linha in leitor:
valor = float(linha[2])
if valor > 1000:
vendas.append(linha)
total_por_cliente = {}
for venda in vendas:
cliente = venda[3]
valor = float(venda[2])
if cliente in total_por_cliente:
total_por_cliente[cliente] += valor
else:
total_por_cliente[cliente] = valor
Com Python tricks:
import csv
import time
def processar_vendas(arquivo):
total_por_cliente = {}
with open(arquivo, 'r') as f:
leitor = csv.reader(f)
for linha in leitor:
valor = float(linha[2])
cliente = linha[3]
if valor > 1000:
total_por_cliente[cliente] = total_por_cliente.get(cliente, 0) + valor
return total_por_cliente
@cronometrar
def main():
resultado = processar_vendas('vendas.csv')
print(f"Total de {len(resultado)} clientes com vendas acima de R$ 1.000")
main()
Veja como ficou:
- Usamos
withpara garantir que o arquivo seja fechado - Evitamos carregar tudo na memória - processamos linha por linha
- Usamos
get()para evitar verificação explícita de chave - Aplicamos um decorador para medir tempo automaticamente
Menos código, mais eficiência, menos erros.
Como saber se você está usando Python bem?
Não é sobre usar todos os truques. É sobre saber quando não usá-los. Python é uma linguagem que valoriza clareza acima de tudo. Um código simples e legível vale mais que um truque elegante que só você entende.
Teste seu código com estas perguntas:
- Um colega que nunca viu esse código vai entender em 30 segundos?
- Se eu remover um truque, o código ainda funciona?
- Estou usando isso porque é mais rápido, ou só porque parece "mais Python"?
Python tricks são ferramentas. Não são regras. Use-as para resolver problemas, não para impressionar.
O que é um Python trick?
Um Python trick é uma técnica prática, não óbvia, que torna o código mais eficiente, limpo ou elegante. Não são recursos novos da linguagem, mas formas inteligentes de usar recursos já existentes - como desempacotamento, compreensão de lista, geradores e decoradores.
Essas dicas funcionam em todas as versões do Python?
Não. Alguns truques, como o operador walrus (:=), só existem desde o Python 3.8. Compreensões de lista e with funcionam desde o Python 2.2. Sempre verifique a versão mínima necessária antes de usar um truque em produção. Se você trabalha com sistemas legados, priorize soluções compatíveis.
Posso usar essas técnicas em projetos de equipe?
Sim, mas com cuidado. Truques como __slots__ ou decoradores complexos podem confundir desenvolvedores menos experientes. O ideal é documentar o uso dessas técnicas em um guia interno da equipe. Priorize clareza - se um truque exige mais explicação que o código original, talvez não valha a pena.
Esses truques melhoram o desempenho?
Às vezes. Compreensões de lista são mais rápidas que loops tradicionais. Geradores economizam memória. Mas a maior vantagem é a legibilidade. Um código mais limpo é mais fácil de otimizar depois. Nunca otimize por truques - otimize por necessidade real. Use ferramentas como cProfile para identificar gargalos antes de tentar "acelerar" o código.
Onde posso aprender mais truques como esses?
O livro "Effective Python" de Brett Slatkin é uma excelente fonte. Também vale a pena estudar o código-fonte de bibliotecas populares como Requests, Pandas e Django. Muitos truques são usados lá de forma natural. Pratique revisando código de colegas - você aprende mais vendo como outros resolvem problemas do que lendo tutoriais.