Anotações que descrevem, não impõem
Um type hint é uma nota que você prende a um nome — geralmente um parâmetro de função — dizendo "isto deveria ser um int", "isto retorna uma lista de strings", e assim por diante. O Python não checa em tempo de execução. Passar uma string onde você anotou int não dispara erro. Seu editor e ferramentas externas (mypy, pyright, Pyright via Pylance do VS Code) leem as anotações e te avisam antes do código rodar.
O caso mais simples possível:
name: str anota o parâmetro. -> str anota o valor de retorno. As duas chamadas rodam. A segunda está errada — um type checker estático apontaria — mas o próprio Python processa alegremente porque 42 por acaso suporta interpolação f"{...}".
Esse é o modelo mental crucial: hints são documentação que uma máquina consegue ler. Não mudam o runtime.
Por que incomodar?
Três ganhos concretos, em ordem de quão rápido se pagam:
- Seu editor fica mais esperto. Autocomplete mostra os métodos certos, renomeações propagam corretamente e passar o mouse numa variável te diz o tipo.
- Assinaturas de função ficam autoexplicativas.
def fetch(url: str, timeout: float = 5.0) -> dict:diz a um leitor exatamente o que passar e o que vai voltar — sem precisar ler o corpo. - Type checkers pegam erros antes de rodar. Rodar
mypy .num projeto traz à tona o tipo de bug que testes unitários muitas vezes perdem —Noneretornado onde você esperava um valor, um dict usado onde pertence uma lista.
Para um script de um arquivo que é só você e só para hoje, pule as anotações. Para qualquer coisa à qual você vai voltar ou compartilhar, os quinze segundos que elas levam para escrever se pagam em uma hora.
Tipos embutidos básicos
Você não precisa de import para nenhum desses:
Anotações de variável (name: str = "Rosa") raramente são necessárias — o Python infere o tipo pelo lado direito. Guarde para parâmetros, tipos de retorno e o caso ocasional em que o tipo inferido é ambíguo.
Funções que não retornam nada usam -> None:
Listas, dicts, tuplas e sets
Containers precisam de mais uma informação — o que contêm. O Python moderno permite indexar os tipos embutidos diretamente:
Lendo em voz alta:
list[float]— uma lista de floats.dict[str, int]— um dict com chaves string e valores int.tuple[float, float]— uma tupla de exatamente dois floats.set[str]— um set de strings.
A sintaxe de subscrição list[...], dict[...] funciona no Python 3.9 e posterior. Em código mais antigo você vai ver List, Dict, Tuple importados de typing — mesmo significado, ortografia antiga.
Valores opcionais
"Pode ser None" é comum. Tem duas ortografias equivalentes — as duas estão bem, mas a mais nova lê melhor:
str | None significa "uma string, ou None". A sintaxe | funciona no Python 3.10+. Em código mais antigo você vai ver Optional[str] do módulo typing, que significa a mesma coisa.
Quem chama e vê -> str | None sabe que precisa checar por None antes de usar o resultado — esse é o ponto todo da anotação.
Union types: isso ou aquilo
Quando um valor pode ser um de vários tipos, use |:
Você pode unir mais de dois tipos. int | str | float significa "qualquer um desses três".
Anotando variáveis dentro de funções
Na maior parte do tempo, o Python consegue descobrir o tipo de uma variável local pelo inicializador. Você só precisa de uma anotação quando:
- O container começa vazio e o type checker não consegue adivinhar o conteúdo.
- O valor poderia ser de vários tipos e você quer se comprometer com um.
- Você quer documentar a intenção para um leitor humano.
typing.Any é a válvula de escape — "não quero anotar isso com precisão". Use com parcimônia. Abusar de Any torna o resto das suas type hints inúteis.
Anotando classes
Atributos de classe e assinaturas de método anotam da mesma forma que qualquer outra função:
Dataclasses na verdade exigem anotações de tipo — o decorador @dataclass lê para gerar __init__ e __repr__. Esse é o único lugar em que anotações afetam o comportamento em runtime.
Tuplas e o caso "qualquer tamanho"
tuple[...] tem dois formatos que confundem iniciantes:
tuple[float, float]— exatamente dois floats.tuple[int, ...]— qualquer número de ints. O...(um elemento sintático real no sistema de tipos) significa "e assim por diante".
Callables e aliases de tipo
Quando uma função recebe ou retorna outra função, use Callable:
Callable[[int], int] significa "uma função que recebe um int e retorna um int".
Quando uma anotação fica repetitiva, dê um nome:
Um alias é só uma atribuição Python comum. Em qualquer lugar em que você usaria a forma longa, o nome curto funciona.
Rodando um type checker
O interpretador Python ignora as type hints. Para de fato checar, instale um type checker. mypy é o original; pyright (usado pelo Pylance do VS Code) é mais rápido.
pip install mypy
mypy seu_projeto/
A primeira execução vai revelar erros em lugares que você não tinha notado. Trabalhe neles incrementalmente — # type: ignore silencia uma linha quando você precisa seguir em frente.
IDEs modernos rodam type checking continuamente enquanto você edita, então a maioria do feedback chega antes de você salvar.
Quando type hints não encaixam
- Scripts exploratórios rápidos. Anotações adicionam atrito a código que vive por uma hora.
- Código muito dinâmico. Metaprogramação, sistemas de plugin e padrões parecidos muitas vezes ultrapassam o que o sistema de tipos consegue descrever. Anote a API externa e deixe o miolo solto.
- Bibliotecas de terceiros sem tipos. Se uma biblioteca que você importa não tem info de tipo,
Anyvaza para seu código. Tudo bem — não é seu código para anotar.
Para tudo no meio, type hints são um hábito pequeno com grande retorno. O custo é algumas teclas a mais por assinatura de função. O retorno é menos bugs, refactors mais fáceis e código que se documenta.
Próxima: módulos e imports
Agora você tem toda a ferramenta em nível de função — argumentos, decoradores, type hints. A seguir vamos olhar como o Python organiza código entre arquivos: módulos, pacotes e o sistema de import.
Perguntas frequentes
O que são type hints em Python?
Type hints são anotações que descrevem os tipos esperados de variáveis, parâmetros de função e valores de retorno. O próprio Python não aplica em tempo de execução — são para ferramentas (IDEs, linters, type checkers como mypy ou pyright) e para humanos lendo o código.
Type hints deixam o Python mais rápido?
Não. O interpretador Python ignora type hints em tempo de execução. O ganho é no seu loop de desenvolvimento — menos typos pegos pelos editores, assinaturas de função mais claras, refactors mais seguros.
Quando devo adicionar type hints?
Adicione em assinaturas públicas de função — parâmetros e tipos de retorno. Adicione com parcimônia dentro do corpo das funções, só onde o tipo de uma variável não é óbvio. Para scripts de uma vez, são opcionais. Para código compartilhado e bibliotecas, se pagam rápido.