Type hints
Esta aula apresenta os type hints em Python, desde as anotações básicas de tipo até o uso do módulo typing com tipos como List, Dict e Optional. Explica por que adotar type hints no código e dá uma visão geral do mypy como ferramenta de verificação estática de tipos.
Type hints (ou anotações de tipo) são uma funcionalidade introduzida no Python 3.5 que permite indicar os tipos esperados de variáveis, parâmetros de funções e valores de retorno. Eles não afetam a execução do código, mas ajudam na legibilidade, documentação e na detecção precoce de erros de tipo com ferramentas externas. Esta aula cobre desde a sintaxe básica até o uso do módulo typing e a ferramenta mypy.
Embora o Python continue sendo uma linguagem de tipagem dinâmica, os type hints trazem os benefícios da tipagem estática sem perder a flexibilidade. Eles são especialmente úteis em projetos grandes, onde a clareza e a manutenibilidade são cruciais.
Anotações de tipo
As anotações de tipo são escritas usando a sintaxe variavel: tipo para variáveis e def funcao(param: tipo) -> tipo_retorno: para funções. Elas são opcionais e ignoradas pelo interpretador em tempo de execução.
Exemplo básico:
nome: str = "Alice"
idade: int = 30
def saudacao(nome: str) -> str:
return f"Olá, {nome}!"
print(saudacao(nome)) # Funciona normalmenteAs anotações podem ser usadas em qualquer lugar onde uma variável é definida, inclusive em atributos de classe e em loops. No entanto, o uso mais comum é em funções e métodos.
typing (List, Dict, Optional)
O módulo typing fornece tipos genéricos para estruturas de dados como listas, dicionários, tuplas, conjuntos e tipos opcionais. Esses tipos permitem especificar o tipo dos elementos contidos.
Exemplos comuns:
from typing import List, Dict, Optional, Tuple, Set
# Lista de inteiros
numeros: List[int] = [1, 2, 3]
# Dicionário com chave string e valor inteiro
contagem: Dict[str, int] = {"a": 1, "b": 2}
# Tupla de dois elementos: string e float
dado: Tuple[str, float] = ("temperatura", 25.5)
# Conjunto de strings
tags: Set[str] = {"python", "type hint"}
# Tipo opcional: pode ser int ou None
idade: Optional[int] = None
Optional[X] é equivalente a Union[X, None]. Também existem Any (qualquer tipo), Union (união de tipos) e Callable (para funções).
Exemplo de função com tipos complexos:
from typing import List, Optional
def processar_itens(itens: List[str], max_itens: Optional[int] = None) -> List[str]:
if max_itens is not None:
return itens[:max_itens]
return itens
Por que usar
Os type hints trazem diversos benefícios para o desenvolvimento de software em Python:
- Documentação automática: indicam claramente o que uma função espera e retorna, facilitando o entendimento do código por outros desenvolvedores.
- Detecção precoce de erros: ferramentas como mypy, Pyright e Pylance podem analisar o código e apontar inconsistências de tipo antes da execução.
- Melhor suporte em IDEs: editores como VS Code e PyCharm usam type hints para fornecer autocompletar, sugestões e verificação em tempo real.
- Refatoração segura: com tipos explícitos, é mais fácil modificar o código sabendo quais partes dependem de quais tipos.
- Redução de bugs: muitos erros comuns, como passar um argumento do tipo errado, podem ser capturados estaticamente.
Embora exijam um esforço inicial, os type hints se pagam rapidamente em projetos de médio e grande porte, melhorando a qualidade e a manutenibilidade do código.
mypy (visão geral)
mypy é uma ferramenta de verificação estática de tipos para Python. Ela analisa o código-fonte e reporta erros de tipo baseados nas anotações fornecidas. mypy suporta a maior parte do módulo typing e pode ser integrada a editores e pipelines de CI/CD.
Instalação e uso básico:
pip install mypy
mypy meu_arquivo.pyExemplo de código com erro detectado pelo mypy:
# arquivo: exemplo.py
def soma(a: int, b: int) -> int:
return a + b
resultado = soma(1, "2") # Erro: argumento 2 deve ser int, não str
Ao executar mypy exemplo.py, a ferramenta indicará o erro:
exemplo.py:4: error: Argument 2 to "soma" has incompatible type "str"; expected "int"mypy também oferece opções como --strict para habilitar verificações mais rigorosas, e suporte a arquivos de configuração (mypy.ini ou pyproject.toml). É uma ferramenta madura e amplamente adotada na comunidade Python.
Boas práticas
- Use type hints em todas as funções públicas de módulos e classes.
- Prefira
list[int]em vez deList[int]a partir do Python 3.9 (tipos embutidos genéricos). - Evite
Anysempre que possível; prefira tipos mais específicos. - Mantenha a configuração do mypy no projeto para garantir consistência.
- Considere usar
TypeVarpara funções genéricas quando necessário.
Referências
- Documentação oficial do módulo typing
- Documentação oficial do mypy
- PEP 484 – Type Hints
- Anotações de tipo na documentação do Python
- Guia de type checking do Real Python
Exercícios
- Escreva uma função que receba uma lista de números inteiros e retorne a soma deles, usando type hints.
- Crie uma função que aceite um dicionário com chaves string e valores float, e retorne a média dos valores.
- Implemente uma função que receba um nome (string) e uma idade opcional (int ou None), e retorne uma saudação personalizada.
- Escreva uma função que receba uma lista de strings e retorne uma nova lista contendo apenas as strings que começam com a letra 'A', usando type hints.
- Use o mypy para verificar o código abaixo e corrija os erros de tipo. Escreva a versão corrigida do código com type hints adequados.
from typing import List
def soma_numeros(numeros: List[int]) -> int:
return sum(numeros)from typing import Dict
def media_valores(dados: Dict[str, float]) -> float:
if not dados:
return 0.0
return sum(dados.values()) / len(dados)from typing import Optional
def saudacao(nome: str, idade: Optional[int] = None) -> str:
if idade is not None:
return f"Olá, {nome}! Você tem {idade} anos."
return f"Olá, {nome}!"from typing import List
def filtrar_a(palavras: List[str]) -> List[str]:
return [palavra for palavra in palavras if palavra.startswith('A')]# Código original (com erros):
# def multiplicar(a, b):
# return a * b
# resultado = multiplicar(2, "3")
# Versão corrigida:
from typing import Union
def multiplicar(a: int, b: int) -> int:
return a * b
resultado = multiplicar(2, 3) # Agora ambos são int