Módulo 2 - Tipagem estática
Callable, Any e apelidos de tipo
9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Anotar funções que recebem ou devolvem funções com Callable.
- Entender que Any desliga a verificação e usá-lo com parcimônia.
- Criar apelidos de tipo para dar nome a tipos complexos.
- Escolher entre Any, object e um tipo específico com critério.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Callable, Any e apelidos de tipo.
Os objetivos desta aula. Anotar funções que recebem ou devolvem funções com Callable. Entender que Any desliga a verificação e usá-lo com parcimônia. Criar apelidos de tipo para dar nome a tipos complexos. Escolher entre Any, object e um tipo específico com critério.
Veja o essencial, parte por parte.
Callable: quando a função é o argumento. Callable[[int, int], int] é uma função que recebe dois inteiros e devolve um inteiro.
Any: o tipo que desliga a verificação. Any some com a verificação; object a mantém e exige que você prove o tipo antes de usar.
Apelidos de tipo para legibilidade. Quando um tipo fica longo, repeti-lo em várias assinaturas polui o código.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Callable: quando a função é o argumento
Funções são objetos em Python, então uma função pode receber outra função como argumento. Para anotar isso existe o Callable, importado do typing. A sintaxe tem duas partes: uma lista com os tipos dos parâmetros e, depois, o tipo de retorno. Callable[[int, int], int] descreve uma função que recebe dois inteiros e devolve um inteiro. Isso é comum em código que recebe uma função de comparação, um callback ou uma operação para aplicar.
from typing import Callable
def aplicar(operacao: Callable[[int, int], int], a: int, b: int) -> int:
return operacao(a, b)
def somar(x: int, y: int) -> int:
return x + y
def multiplicar(x: int, y: int) -> int:
return x * y
print(aplicar(somar, 3, 4)) # 7
print(aplicar(multiplicar, 3, 4)) # 12aplicar recebe uma função Callable[[int, int], int] e a usa com dois inteiros.
No exemplo, aplicar aceita qualquer função que se encaixe no contrato: dois inteiros entram, um inteiro sai. Tanto somar quanto multiplicar servem. Se você tentasse passar uma função com assinatura diferente, o mypy avisaria. Quando os parâmetros não importam para a anotação, você pode usar reticências no lugar da lista: Callable[..., int] aceita qualquer assinatura desde que o retorno seja inteiro.
Any: o tipo que desliga a verificação
Any é um tipo especial que combina com tudo. Um valor anotado como Any pode receber qualquer coisa e ser usado de qualquer jeito, sem o mypy reclamar. Isso soa conveniente, mas é justamente o problema: onde entra Any, a verificação de tipos se desliga. Um pouco de Any é inevitável, por exemplo ao lidar com dados de fora ainda sem forma definida. Muito Any transforma o código tipado em código sem tipos, com todo o custo de escrever anotações e nenhum benefício.
Any
- Aceita qualquer valor e permite qualquer operação
- Desliga a verificação naquele ponto
- Use quando o tipo é genuinamente desconhecido
- Perigoso se virar hábito: mascara erros
object
- Aceita qualquer valor, pois tudo herda de object
- Mantém a verificação: só permite o que object oferece
- Use quando aceita qualquer coisa mas quer segurança
- Mais seguro: o mypy cobra checagem antes de usar
Apelidos de tipo para legibilidade
Quando um tipo fica longo, repeti-lo em várias assinaturas polui o código. Um apelido de tipo resolve isso: você atribui o tipo a um nome e usa o nome no lugar. Se um sistema de coordenadas usa muito list[tuple[float, float]], criar Trajeto = list[tuple[float, float]] deixa as assinaturas curtas e o significado claro. O apelido não cria um tipo novo; é só um nome mais legível para o mesmo tipo. Em versões recentes há a palavra type para deixar isso ainda mais explícito.
Trajeto = list[tuple[float, float]]
TabelaPrecos = dict[str, float]
def distancia_total(rota: Trajeto) -> float:
total = 0.0
for i in range(1, len(rota)):
x1, y1 = rota[i - 1]
x2, y2 = rota[i]
total += ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
return total
caminho: Trajeto = [(0.0, 0.0), (3.0, 4.0)]
print(distancia_total(caminho)) # 5.0Trajeto é um apelido para list[tuple[float, float]]; a assinatura fica legível.
O apelido Trajeto conta a intenção que list[tuple[float, float]] esconde. Quem lê distancia_total(rota: Trajeto) entende de imediato que a função recebe um caminho, não uma lista qualquer de pares. Esse tipo de nomeação é engenharia de legibilidade: o programa faz o mesmo, mas fica mais fácil de manter. Na próxima aula você conhece TypeVar e generics, que levam essa ideia adiante ao escrever código que funciona para qualquer tipo sem abrir mão da verificação.
Teste rápido
Por que usar Any por toda parte anula a vantagem da tipagem?
Perguntas frequentes
- Como anoto uma função que não recebe nenhum argumento?
- Com uma lista de parâmetros vazia: Callable[[], int] descreve uma função sem argumentos que devolve um inteiro. Os colchetes internos ficam vazios justamente para indicar que nada entra. O segundo elemento continua sendo o tipo de retorno.
- Quando é aceitável usar Any de verdade?
- Quando o tipo é genuinamente desconhecido naquele ponto, como ao receber dados de uma fonte externa sem forma fixa, ou ao integrar com uma biblioteca sem tipos. Mesmo assim, o ideal é converter esse Any para um tipo concreto o quanto antes, validando o dado na fronteira.
- Apelido de tipo cria um tipo novo?
- Não. Um apelido é só um nome alternativo para um tipo existente. Trajeto = list[tuple[float, float]] não gera uma classe nova; para o mypy, Trajeto e list[tuple[float, float]] são idênticos. O ganho é de legibilidade, não de comportamento.
- Callable serve para métodos também, não só funções soltas?
- Sim. Métodos, funções e qualquer objeto que se possa chamar com parênteses se encaixam no tipo Callable, desde que a assinatura combine. Isso inclui funções lambda e instâncias de classes que definem o método especial de chamada. O que importa é a forma de chamar.
- Qual a diferença prática entre Any e object no dia a dia?
- Com Any você pode fazer qualquer operação sem o mypy reclamar, o que é arriscado. Com object o mypy só permite o que todo objeto tem e cobra que você verifique o tipo real antes de usar métodos específicos. Para aceitar qualquer valor com segurança, object é a escolha melhor.
- Preciso importar Callable e Any de onde?
- Ambos vêm do módulo typing: from typing import Callable, Any. Em versões recentes, Callable também está disponível em collections.abc, mas importar do typing continua funcionando e é o mais comum em material didático.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.