---
title: "Tipagem Estatica em Python com Mypy"
url: "https://python.dev.br/blog/tipagem-estatica-python-mypy/"
markdown_url: "https://python.dev.br/blog/tipagem-estatica-python-mypy.MD"
description: "Aprenda a usar tipagem estatica em Python com mypy. Descubra como type hints tornam seu codigo mais seguro, legivel e facil de manter."
date: "2025-08-15"
author: "Equipe Python Brasil"
---

# Tipagem Estatica em Python com Mypy

Aprenda a usar tipagem estatica em Python com mypy. Descubra como type hints tornam seu codigo mais seguro, legivel e facil de manter.


Python sempre foi uma linguagem de tipagem dinamica, mas desde a versao 3.5, com a PEP 484, passou a suportar type hints. Combinados com ferramentas como o mypy, esses hints transformam a experiencia de desenvolvimento, detectando erros antes mesmo de executar o codigo. Neste artigo, vamos explorar como usar tipagem estatica em Python de forma pratica e eficiente.

## O Que Sao Type Hints

Type hints sao anotacoes que indicam os tipos esperados de variaveis, parametros e retornos de funcoes. Eles nao alteram o comportamento do programa em tempo de execucao, mas servem como documentacao viva e permitem a analise estatica.

```python
# Sem type hints
def calcular_desconto(preco, percentual):
    return preco * (1 - percentual / 100)

# Com type hints
def calcular_desconto(preco: float, percentual: float) -> float:
    return preco * (1 - percentual / 100)
```

A segunda versao deixa claro que a funcao recebe dois floats e retorna um float. Qualquer desenvolvedor que leia esse codigo entende imediatamente o contrato da funcao.

## Instalando e Configurando o Mypy

O mypy e o verificador de tipos mais popular para Python. A instalacao e simples:

```python
pip install mypy
```

Para verificar um arquivo, basta executar:

```bash
mypy meu_arquivo.py
```

Para projetos maiores, crie um arquivo `mypy.ini` ou adicione configuracoes no `pyproject.toml`:

```toml
[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
check_untyped_defs = true
strict_optional = true
```

Com `disallow_untyped_defs = true`, o mypy exigira que todas as funcoes tenham anotacoes de tipo, garantindo cobertura completa.

## Tipos Basicos e Compostos

Python oferece uma variedade de tipos para anotacoes. Os mais comuns sao:

```python
# Tipos primitivos
nome: str = "Maria"
idade: int = 28
salario: float = 5500.00
ativo: bool = True

# Listas e dicionarios (Python 3.9+)
nomes: list[str] = ["Ana", "Carlos", "Bruno"]
notas: dict[str, float] = {"matematica": 8.5, "portugues": 9.0}

# Tuplas
coordenada: tuple[float, float] = (23.5505, 46.6333)

# Conjuntos
tags: set[str] = {"python", "programacao", "backend"}
```

Para versoes anteriores ao Python 3.9, use os tipos do modulo `typing`:

```python
from typing import List, Dict, Tuple, Set

nomes: List[str] = ["Ana", "Carlos"]
notas: Dict[str, float] = {"matematica": 8.5}
```

## Tipos Opcionais e Union

Muitas vezes uma variavel pode ter mais de um tipo ou ser `None`. Para isso, usamos `Optional` e `Union`:

```python
from typing import Optional, Union

def buscar_usuario(user_id: int) -> Optional[dict]:
    """Retorna o usuario ou None se nao encontrado."""
    usuarios = {1: {"nome": "Ana", "email": "ana@email.com"}}
    return usuarios.get(user_id)

def formatar_valor(valor: Union[int, float]) -> str:
    """Aceita int ou float e retorna string formatada."""
    return f"R$ {valor:,.2f}"

# Python 3.10+ permite a sintaxe com pipe
def buscar_usuario_novo(user_id: int) -> dict | None:
    usuarios = {1: {"nome": "Ana"}}
    return usuarios.get(user_id)
```

O mypy vai alertar se voce tentar acessar atributos do resultado de `buscar_usuario` sem antes verificar se ele nao e `None`.

## TypedDict e Dataclasses Tipadas

Para dicionarios com estrutura fixa, `TypedDict` e extremamente util:

```python
from typing import TypedDict

class Usuario(TypedDict):
    nome: str
    email: str
    idade: int
    ativo: bool

def criar_usuario(nome: str, email: str, idade: int) -> Usuario:
    return {
        "nome": nome,
        "email": email,
        "idade": idade,
        "ativo": True,
    }

usuario = criar_usuario("Carlos", "carlos@email.com", 30)
print(usuario["nome"])  # OK
# print(usuario["telefone"])  # mypy: erro! chave nao existe
```

Dataclasses com tipagem oferecem uma alternativa ainda mais robusta:

```python
from dataclasses import dataclass

@dataclass
class Produto:
    nome: str
    preco: float
    estoque: int = 0

    def aplicar_desconto(self, percentual: float) -> float:
        return self.preco * (1 - percentual / 100)

produto = Produto(nome="Notebook", preco=3500.00, estoque=10)
valor_final = produto.aplicar_desconto(15)
print(f"Preco com desconto: R$ {valor_final:.2f}")
```

## Generics e Protocolos

Para funcoes que operam com diferentes tipos, use generics:

```python
from typing import TypeVar, Sequence

T = TypeVar("T")

def primeiro_elemento(sequencia: Sequence[T]) -> T:
    """Retorna o primeiro elemento de qualquer sequencia."""
    if not sequencia:
        raise ValueError("Sequencia vazia")
    return sequencia[0]

# mypy infere o tipo de retorno automaticamente
numero = primeiro_elemento([1, 2, 3])       # int
texto = primeiro_elemento(["a", "b", "c"])   # str
```

Protocolos permitem tipagem estrutural, semelhante a duck typing com verificacao estatica:

```python
from typing import Protocol

class Enviavel(Protocol):
    def enviar(self, mensagem: str) -> bool: ...

class EmailService:
    def enviar(self, mensagem: str) -> bool:
        print(f"Email enviado: {mensagem}")
        return True

class SMSService:
    def enviar(self, mensagem: str) -> bool:
        print(f"SMS enviado: {mensagem}")
        return True

def notificar(servico: Enviavel, mensagem: str) -> None:
    sucesso = servico.enviar(mensagem)
    if sucesso:
        print("Notificacao enviada com sucesso")

notificar(EmailService(), "Bem-vindo!")
notificar(SMSService(), "Codigo: 1234")
```

## Integrando Mypy no Fluxo de Trabalho

A melhor forma de aproveitar o mypy e integra-lo ao seu pipeline de desenvolvimento. Adicione-o como pre-commit hook:

```yaml
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.8.0
    hooks:
      - id: mypy
        additional_dependencies: [types-requests]
```

Tambem e possivel integra-lo ao CI/CD no GitHub Actions:

```yaml
# .github/workflows/typecheck.yml
name: Type Check
on: [push, pull_request]
jobs:
  mypy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install mypy
      - run: mypy src/
```

## Boas Praticas de Tipagem

Adotar tipagem estatica de forma eficiente requer alguns cuidados. Primeiro, comece pelos modulos mais criticos do seu projeto, como a camada de dados e as interfaces publicas da API. Nao tente tipar tudo de uma vez em um projeto existente.

Segundo, use `reveal_type()` durante o desenvolvimento para entender como o mypy infere os tipos:

```python
x = [1, 2, 3]
reveal_type(x)  # mypy revela: list[int]
```

Terceiro, evite o uso excessivo de `Any`. Ele desativa a verificacao de tipos e anula os beneficios do mypy. Se precisar usar `Any`, documente o motivo.

Por fim, mantenha as dependencias de tipos atualizadas. Pacotes como `types-requests`, `types-redis` e `types-PyYAML` fornecem stubs de tipos para bibliotecas populares que ainda nao possuem anotacoes nativas.

## Conclusao

Tipagem estatica com mypy eleva a qualidade do codigo Python a outro patamar. Ela reduz bugs, melhora a legibilidade e facilita refatoracoes em projetos de qualquer tamanho. Comece com type hints basicos, configure o mypy no seu projeto e evolua gradualmente para generics e protocolos. O investimento inicial se paga rapidamente em menos erros em producao e maior confianca nas mudancas de codigo.

> **Tipagem em outras linguagens**: se voce gosta da seguranca que type hints trazem, vale explorar <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust</a>, onde o sistema de tipos em tempo de compilacao elimina categorias inteiras de bugs como null pointer exceptions e data races. <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin</a> tambem oferece null safety nativa e inferencia de tipos avancada, sendo uma evolucao natural para quem vem do Java.
