Entrevistas de Python backend cobrem detalhes internos da linguagem, programação assíncrona, Django ou FastAPI, e padrões de acesso a banco de dados. Abaixo estão as perguntas mais comuns com respostas modelo. Middle: compreensão mais profunda, otimização e situações reais de trabalho.
1
O que o GIL realmente impede, e quando threads ainda ajudam?
Resposta
O Global Interpreter Lock permite que apenas uma thread execute bytecode Python por vez, então código Python puro nunca roda em paralelo entre núcleos. Threads ainda ajudam sempre que o trabalho é esperar em vez de calcular — chamadas de rede, disco, banco de dados — porque o lock é liberado durante I/O bloqueante. Para trabalho limitado por CPU você precisa de processos, uma extensão em C que solte o GIL, ou mover a parte quente para fora do Python.
2
O que o await realmente faz, e quando async não faz sentido?
Resposta
O await devolve o controle ao event loop para que ele possa rodar outra coisa até a operação esperada terminar; ele não cria uma thread e nada roda em paralelo. Async não faz sentido quando o trabalho é limitado por CPU, porque um cálculo longo trava o loop e todas as outras tasks junto. Também não faz sentido se alguma biblioteca no caminho é síncrona — um driver de banco de dados bloqueante para o loop inteiro.
3
Escreva um decorator. Por que ele precisa de functools.wraps?
Resposta
Um decorator é uma função que recebe uma função e retorna um substituto, geralmente um closure que chama a original. Sem functools.wraps o substituto carrega seu próprio nome e docstring, então a função decorada se reporta como 'wrapper' — o que quebra a introspecção, o help() e qualquer framework que roteie pelo nome da função. O wraps copia os metadados adiante.
4
Você tem um problema N+1 no ORM. Como encontrar e corrigir?
Resposta
Você encontra olhando o log de queries ou a debug toolbar e vendo uma consulta por linha de uma lista. A causa é lazy loading dentro de um loop. select_related resolve para foreign keys diretas com um join; prefetch_related resolve para relações reversas e many-to-many com uma segunda consulta e um match em memória. A armadilha é corrigir o sintoma cacheando o resultado em vez da consulta.
5
Quando você retornaria um generator em vez de uma lista?
Resposta
Quando quem chama itera uma vez e os dados não precisam caber na memória — ler um arquivo grande, streaming de resultados de consulta, um pipeline de transformações. O custo é que um generator é consumido: você não pode pegar seu tamanho, indexá-lo, ou iterá-lo duas vezes sem materializá-lo. Retornar um a partir de uma API pública surpreende quem espera uma sequência, então deveria ser uma decisão documentada.
6
O que um context manager garante?
Resposta
Que __exit__ roda quer o bloco termine normalmente ou lance uma exceção, por isso file handles, locks e transações pertencem a um. Escrito com contextlib.contextmanager, o código antes do yield é setup e o código depois é teardown — mas só se o teardown estiver num finally, senão uma exceção o pula. A garantia é sobre a limpeza, não sobre suprimir o erro.
7
O que você mocka num teste, e o que não?
Resposta
Mocke o que você não possui e não controla: APIs de terceiros, o relógio, aleatoriedade, envio de e-mails. Não mocke sua própria lógica de domínio, porque aí o teste está apenas afirmando que o seu mock se comporta como você o escreveu. Mockar o banco de dados geralmente também é um erro — uma transação revertida depois de cada teste dá comportamento real a baixo custo, e os bugs do ORM são exatamente o que os mocks escondem.